Compare commits
4 commits
43b4220de2
...
6d1ae370fa
Author | SHA1 | Date | |
---|---|---|---|
6d1ae370fa | |||
2358a22d38 | |||
d4762205dc | |||
b718fe2792 |
3 changed files with 131 additions and 13 deletions
|
@ -43,7 +43,7 @@ type Endpoint<'a> = (reqwest::Method, &'a str);
|
||||||
/// we could completely change it without requiring an upgrade to v1
|
/// we could completely change it without requiring an upgrade to v1
|
||||||
/// clients.)
|
/// clients.)
|
||||||
/// ```
|
/// ```
|
||||||
pub const ADD_CHAIN_ENDPOINT: Endpoint = (reqwest::Method::POST, "/ct/v1/add-chain");
|
pub const ADD_CHAIN: Endpoint = (reqwest::Method::POST, "/ct/v1/add-chain");
|
||||||
|
|
||||||
/// Reference: https://datatracker.ietf.org/doc/html/rfc6962#section-4.2
|
/// Reference: https://datatracker.ietf.org/doc/html/rfc6962#section-4.2
|
||||||
/// ```txt
|
/// ```txt
|
||||||
|
@ -59,4 +59,44 @@ pub const ADD_CHAIN_ENDPOINT: Endpoint = (reqwest::Method::POST, "/ct/v1/add-cha
|
||||||
///
|
///
|
||||||
/// Outputs are the same as in Section 4.1.
|
/// Outputs are the same as in Section 4.1.
|
||||||
/// ```
|
/// ```
|
||||||
pub const ADD_PRE_CHAIN_ENDPOINT: Endpoint = (reqwest::Method::POST, "/ct/v1/add-pre-chain");
|
pub const ADD_PRE_CHAIN: Endpoint = (reqwest::Method::POST, "/ct/v1/add-pre-chain");
|
||||||
|
|
||||||
|
/// Reference: https://datatracker.ietf.org/doc/html/rfc6962#section-4.3
|
||||||
|
/// ```txt
|
||||||
|
/// GET https://<log server>/ct/v1/get-sth
|
||||||
|
///
|
||||||
|
/// No inputs.
|
||||||
|
///
|
||||||
|
/// Outputs:
|
||||||
|
///
|
||||||
|
/// tree_size: The size of the tree, in entries, in decimal.
|
||||||
|
///
|
||||||
|
/// timestamp: The timestamp, in decimal.
|
||||||
|
///
|
||||||
|
/// sha256_root_hash: The Merkle Tree Hash of the tree, in base64.
|
||||||
|
///
|
||||||
|
/// tree_head_signature: A TreeHeadSignature for the above data.
|
||||||
|
/// ```
|
||||||
|
pub const GET_STH: Endpoint = (reqwest::Method::GET, "/ct/v1/get-sth");
|
||||||
|
|
||||||
|
/// Reference: https://datatracker.ietf.org/doc/html/rfc6962#section-4.4
|
||||||
|
/// ```txt
|
||||||
|
/// GET https://<log server>/ct/v1/get-sth-consistency
|
||||||
|
///
|
||||||
|
/// Inputs:
|
||||||
|
///
|
||||||
|
/// first: The tree_size of the first tree, in decimal.
|
||||||
|
///
|
||||||
|
/// second: The tree_size of the second tree, in decimal.
|
||||||
|
///
|
||||||
|
/// Both tree sizes must be from existing v1 STHs (Signed Tree Heads).
|
||||||
|
///
|
||||||
|
/// Outputs:
|
||||||
|
///
|
||||||
|
/// consistency: An array of Merkle Tree nodes, base64 encoded.
|
||||||
|
///
|
||||||
|
/// Note that no signature is required on this data, as it is used to
|
||||||
|
/// verify an STH, which is signed.
|
||||||
|
/// ```
|
||||||
|
pub const GET_STH_CONSISTENCY: Endpoint =
|
||||||
|
(reqwest::Method::GET, "/ct/v1/get-sth-consistency");
|
||||||
|
|
|
@ -1,5 +1,10 @@
|
||||||
use reqwest::Url;
|
use reqwest::Url;
|
||||||
use responses::{AddChainRequest, AddChainResponse};
|
use responses::{
|
||||||
|
AddChainRequest,
|
||||||
|
AddChainResponse,
|
||||||
|
GetSthConsistencyResponse,
|
||||||
|
GetSthResponse
|
||||||
|
};
|
||||||
|
|
||||||
pub mod endpoints;
|
pub mod endpoints;
|
||||||
pub mod responses;
|
pub mod responses;
|
||||||
|
@ -19,7 +24,7 @@ impl CtApiClient {
|
||||||
|
|
||||||
/// Adds a standard x509 chain to the CT log.
|
/// Adds a standard x509 chain to the CT log.
|
||||||
///
|
///
|
||||||
/// See: [`endpoints::ADD_CHAIN_ENDPOINT`]
|
/// See: [`endpoints::ADD_CHAIN`]
|
||||||
///
|
///
|
||||||
/// ## Errors
|
/// ## Errors
|
||||||
///
|
///
|
||||||
|
@ -34,8 +39,8 @@ impl CtApiClient {
|
||||||
) -> reqwest::Result<AddChainResponse> {
|
) -> reqwest::Result<AddChainResponse> {
|
||||||
self.inner_client
|
self.inner_client
|
||||||
.request(
|
.request(
|
||||||
endpoints::ADD_CHAIN_ENDPOINT.0,
|
endpoints::ADD_CHAIN.0,
|
||||||
self.log_url.to_string() + endpoints::ADD_CHAIN_ENDPOINT.1
|
self.log_url.to_string() + endpoints::ADD_CHAIN.1
|
||||||
)
|
)
|
||||||
.json(&AddChainRequest { chain })
|
.json(&AddChainRequest { chain })
|
||||||
.send()
|
.send()
|
||||||
|
@ -49,7 +54,7 @@ impl CtApiClient {
|
||||||
/// [`CtApiClient::add_chain`], except is used specifically when the chain
|
/// [`CtApiClient::add_chain`], except is used specifically when the chain
|
||||||
/// starts with a precertificate rather than the final end-user certificate.
|
/// starts with a precertificate rather than the final end-user certificate.
|
||||||
///
|
///
|
||||||
/// See: [`endpoints::ADD_PRE_CHAIN_ENDPOINT`]
|
/// See: [`endpoints::ADD_PRE_CHAIN`]
|
||||||
///
|
///
|
||||||
/// ## Errors
|
/// ## Errors
|
||||||
///
|
///
|
||||||
|
@ -67,8 +72,8 @@ impl CtApiClient {
|
||||||
) -> reqwest::Result<AddChainResponse> {
|
) -> reqwest::Result<AddChainResponse> {
|
||||||
self.inner_client
|
self.inner_client
|
||||||
.request(
|
.request(
|
||||||
endpoints::ADD_PRE_CHAIN_ENDPOINT.0,
|
endpoints::ADD_PRE_CHAIN.0,
|
||||||
self.log_url.to_string() + endpoints::ADD_PRE_CHAIN_ENDPOINT.1
|
self.log_url.to_string() + endpoints::ADD_PRE_CHAIN.1
|
||||||
)
|
)
|
||||||
.json(&AddChainRequest { chain })
|
.json(&AddChainRequest { chain })
|
||||||
.send()
|
.send()
|
||||||
|
@ -77,4 +82,55 @@ impl CtApiClient {
|
||||||
.json()
|
.json()
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Fetches the Signed Tree Head information for the current CT log tree
|
||||||
|
///
|
||||||
|
/// See: [`endpoints::GET_STH`]
|
||||||
|
///
|
||||||
|
/// ## Errors
|
||||||
|
///
|
||||||
|
/// This may error if either the request failed (due to lack of internet or
|
||||||
|
/// invalid domain, for example).
|
||||||
|
pub async fn get_signed_tree_head(&self) -> reqwest::Result<GetSthResponse> {
|
||||||
|
self.inner_client
|
||||||
|
.request(
|
||||||
|
endpoints::GET_STH.0,
|
||||||
|
self.log_url.to_string() + endpoints::GET_STH.1
|
||||||
|
)
|
||||||
|
.send()
|
||||||
|
.await?
|
||||||
|
.error_for_status()?
|
||||||
|
.json()
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Fetches the Signed Tree Head consistency proof for a specified start
|
||||||
|
/// tree_size and end tree_size.
|
||||||
|
///
|
||||||
|
/// See: [`endpoints::GET_STH_CONSISTENCY`]
|
||||||
|
///
|
||||||
|
/// ## Errors
|
||||||
|
///
|
||||||
|
/// This may error if either the request failed (due to lack of internet or
|
||||||
|
/// invalid domain, for example), or if the CT log gave a 4xx/5xx response.
|
||||||
|
/// The CT log may error the response if your first and second tree sizes
|
||||||
|
/// are invalid, for example if the second is smaller than the first or if
|
||||||
|
/// the tree has never contained a size specified in `first` or `second`.
|
||||||
|
pub async fn get_signed_tree_head_consistency(
|
||||||
|
&self,
|
||||||
|
first: u64,
|
||||||
|
second: u64
|
||||||
|
) -> reqwest::Result<GetSthConsistencyResponse> {
|
||||||
|
self.inner_client
|
||||||
|
.request(
|
||||||
|
endpoints::GET_STH_CONSISTENCY.0,
|
||||||
|
self.log_url.to_string() + endpoints::GET_STH_CONSISTENCY.1
|
||||||
|
)
|
||||||
|
.query(&[("first", first), ("second", second)])
|
||||||
|
.send()
|
||||||
|
.await?
|
||||||
|
.error_for_status()?
|
||||||
|
.json()
|
||||||
|
.await
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,8 @@ use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
/// A request payload for adding a chain to a CT log
|
/// A request payload for adding a chain to a CT log
|
||||||
///
|
///
|
||||||
/// See: [`super::endpoints::ADD_CHAIN_ENDPOINT`] or [`super::endpoints::ADD_PRE_CHAIN_ENDPOINT`]
|
/// See: [`super::endpoints::ADD_CHAIN`] or
|
||||||
|
/// [`super::endpoints::ADD_PRE_CHAIN`]
|
||||||
#[derive(Debug, Serialize)]
|
#[derive(Debug, Serialize)]
|
||||||
pub struct AddChainRequest {
|
pub struct AddChainRequest {
|
||||||
pub chain: Vec<String>
|
pub chain: Vec<String>
|
||||||
|
@ -10,7 +11,8 @@ pub struct AddChainRequest {
|
||||||
|
|
||||||
/// A response given when adding a chain to a CT log
|
/// A response given when adding a chain to a CT log
|
||||||
///
|
///
|
||||||
/// See: [`super::endpoints::ADD_CHAIN_ENDPOINT`] or [`super::endpoints::ADD_PRE_CHAIN_ENDPOINT`]
|
/// See: [`super::endpoints::ADD_CHAIN`] or
|
||||||
|
/// [`super::endpoints::ADD_PRE_CHAIN`]
|
||||||
#[derive(Debug, Deserialize)]
|
#[derive(Debug, Deserialize)]
|
||||||
pub struct AddChainResponse {
|
pub struct AddChainResponse {
|
||||||
pub sct_version: u8,
|
pub sct_version: u8,
|
||||||
|
@ -19,3 +21,23 @@ pub struct AddChainResponse {
|
||||||
pub extensions: String,
|
pub extensions: String,
|
||||||
pub signature: String
|
pub signature: String
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A response given when fetching the Signed Tree Head of a CT log
|
||||||
|
///
|
||||||
|
/// See: [`super::endpoints::GET_STH`]
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
|
pub struct GetSthResponse {
|
||||||
|
pub tree_size: u64,
|
||||||
|
pub timestamp: u64,
|
||||||
|
pub sha256_root_hash: String,
|
||||||
|
pub tree_head_signature: String
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A response given when fetching the Signed Tree Head consistency proof of a
|
||||||
|
/// CT log
|
||||||
|
///
|
||||||
|
/// See: [`super::endpoints::GET_STH_CONSISTENCY`]
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
|
pub struct GetSthConsistencyResponse {
|
||||||
|
pub consistency: Vec<String>
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue