Compare commits
No commits in common. "7e51c915bc6b47b1c75901d1bca0a167efc347bd" and "6d1ae370fa02f39ab9b9d601fd7a6bb45e6a9c02" have entirely different histories.
7e51c915bc
...
6d1ae370fa
3 changed files with 5 additions and 112 deletions
|
@ -100,28 +100,3 @@ pub const GET_STH: Endpoint = (reqwest::Method::GET, "/ct/v1/get-sth");
|
||||||
/// ```
|
/// ```
|
||||||
pub const GET_STH_CONSISTENCY: Endpoint =
|
pub const GET_STH_CONSISTENCY: Endpoint =
|
||||||
(reqwest::Method::GET, "/ct/v1/get-sth-consistency");
|
(reqwest::Method::GET, "/ct/v1/get-sth-consistency");
|
||||||
|
|
||||||
/// Reference: https://datatracker.ietf.org/doc/html/rfc6962#section-4.4
|
|
||||||
/// ```txt
|
|
||||||
/// GET https://<log server>/ct/v1/get-proof-by-hash
|
|
||||||
///
|
|
||||||
/// Inputs:
|
|
||||||
///
|
|
||||||
/// hash: A base64-encoded v1 leaf hash.
|
|
||||||
///
|
|
||||||
/// tree_size: The tree_size of the tree on which to base the proof,
|
|
||||||
/// in decimal.
|
|
||||||
///
|
|
||||||
/// The "hash" must be calculated as defined in Section 3.4. The
|
|
||||||
/// "tree_size" must designate an existing v1 STH.
|
|
||||||
///
|
|
||||||
/// Outputs:
|
|
||||||
///
|
|
||||||
/// leaf_index: The 0-based index of the end entity corresponding to
|
|
||||||
/// the "hash" parameter.
|
|
||||||
///
|
|
||||||
/// audit_path: An array of base64-encoded Merkle Tree nodes proving
|
|
||||||
/// the inclusion of the chosen certificate.
|
|
||||||
/// ```
|
|
||||||
pub const GET_PROOF_BY_HASH: Endpoint =
|
|
||||||
(reqwest::Method::GET, "/ct/v1/get-proof-by-hash");
|
|
||||||
|
|
|
@ -1,10 +1,7 @@
|
||||||
use std::sync::Arc;
|
|
||||||
|
|
||||||
use reqwest::Url;
|
use reqwest::Url;
|
||||||
use responses::{
|
use responses::{
|
||||||
AddChainRequest,
|
AddChainRequest,
|
||||||
AddChainResponse,
|
AddChainResponse,
|
||||||
GetProofByHashResponse,
|
|
||||||
GetSthConsistencyResponse,
|
GetSthConsistencyResponse,
|
||||||
GetSthResponse
|
GetSthResponse
|
||||||
};
|
};
|
||||||
|
@ -12,50 +9,20 @@ use responses::{
|
||||||
pub mod endpoints;
|
pub mod endpoints;
|
||||||
pub mod responses;
|
pub mod responses;
|
||||||
|
|
||||||
/// An API client used for interfacing with a specific CT log. This can be
|
|
||||||
/// constructed with [`CtApiClient::new`] to automatically create an inner
|
|
||||||
/// [`reqwest::Client`], or an [`Arc`] of one can be passed manually with
|
|
||||||
/// [`CtApiClient::new_with_client`] to re-use an existing client between code.
|
|
||||||
/// Re-using clients if one is already created is recommended, as it allows
|
|
||||||
/// connection-pools to be re-used and will have less overhead between requests.
|
|
||||||
pub struct CtApiClient {
|
pub struct CtApiClient {
|
||||||
inner_client: Arc<reqwest::Client>,
|
inner_client: reqwest::Client,
|
||||||
log_url: Url
|
log_url: Url
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CtApiClient {
|
impl CtApiClient {
|
||||||
/// Creates a new [`CtApiClient`] given a specific log URL. This log URL can
|
|
||||||
/// contain a subpath if the specific log uses one. Anything besides a
|
|
||||||
/// scheme, host information (ip/port), and a standard path is not supported
|
|
||||||
/// and will likely cause requests to fail.
|
|
||||||
///
|
|
||||||
/// ## Errors
|
|
||||||
///
|
|
||||||
/// As this automatically constructs a [`reqwest::Client`], this will error
|
|
||||||
/// if the client fails to be created for whatever reason, usually due to it
|
|
||||||
/// being unable to find TLS configuration and root store for the platform.
|
|
||||||
pub fn new(log_url: Url) -> reqwest::Result<Self> {
|
pub fn new(log_url: Url) -> reqwest::Result<Self> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
inner_client: Arc::new(reqwest::Client::builder().https_only(true).build()?),
|
inner_client: reqwest::Client::builder().https_only(true).build()?,
|
||||||
log_url
|
log_url
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a new [`CtApiClient`] given a specific log URL and
|
/// Adds a standard x509 chain to the CT log.
|
||||||
/// [`reqwest::Client`]. This log URL can contain a subpath if the specific
|
|
||||||
/// log uses one. Anything besides a scheme, host information (ip/port),
|
|
||||||
/// and a standard path is not supported and will likely cause requests to
|
|
||||||
/// fail.
|
|
||||||
pub fn new_with_client(log_url: Url, inner_client: Arc<reqwest::Client>) -> Self {
|
|
||||||
Self {
|
|
||||||
inner_client,
|
|
||||||
log_url
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Adds a standard x509 chain to the CT log. The log will then return
|
|
||||||
/// information needed to construct a valid SCT entry, including timestamp,
|
|
||||||
/// CT log signature, sct version, and any log operator extensions.
|
|
||||||
///
|
///
|
||||||
/// See: [`endpoints::ADD_CHAIN`]
|
/// See: [`endpoints::ADD_CHAIN`]
|
||||||
///
|
///
|
||||||
|
@ -86,7 +53,6 @@ impl CtApiClient {
|
||||||
/// Adds a precetificate chain to the CT log. This is largely the same as
|
/// Adds a precetificate chain to the CT log. This is largely the same as
|
||||||
/// [`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.
|
||||||
/// Response data is exactly the same as [`CtApiClient::add_chain`].
|
|
||||||
///
|
///
|
||||||
/// See: [`endpoints::ADD_PRE_CHAIN`]
|
/// See: [`endpoints::ADD_PRE_CHAIN`]
|
||||||
///
|
///
|
||||||
|
@ -117,11 +83,7 @@ impl CtApiClient {
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Fetches the Signed Tree Head information for the current CT log tree.
|
/// Fetches the Signed Tree Head information for the current CT log tree
|
||||||
/// The response contains the tree size, timestamp, root hash, and a
|
|
||||||
/// signature of all of the above from the CT log. This data can be used to
|
|
||||||
/// verify the integrity of the tree at any point, and verify inclusion of a
|
|
||||||
/// leaf in the tree.
|
|
||||||
///
|
///
|
||||||
/// See: [`endpoints::GET_STH`]
|
/// See: [`endpoints::GET_STH`]
|
||||||
///
|
///
|
||||||
|
@ -143,9 +105,7 @@ impl CtApiClient {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Fetches the Signed Tree Head consistency proof for a specified start
|
/// Fetches the Signed Tree Head consistency proof for a specified start
|
||||||
/// tree_size and end tree_size. This consistency proof is simply a list of
|
/// tree_size and end tree_size.
|
||||||
/// each merkle tree node necessary to verify the append-only nature of the
|
|
||||||
/// log between the specified first and second tree sizes.
|
|
||||||
///
|
///
|
||||||
/// See: [`endpoints::GET_STH_CONSISTENCY`]
|
/// See: [`endpoints::GET_STH_CONSISTENCY`]
|
||||||
///
|
///
|
||||||
|
@ -173,36 +133,4 @@ impl CtApiClient {
|
||||||
.json()
|
.json()
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Fetches a single merkle audit proof for a specific leaf node by hash
|
|
||||||
/// from the CT log. The response both includes the index of the hashed
|
|
||||||
/// leaf node and the list of Merkle Tree nodes required to verify proof of
|
|
||||||
/// existence of your specified node in the full tree.
|
|
||||||
///
|
|
||||||
/// See: [`endpoints::GET_PROOF_BY_HASH`]
|
|
||||||
///
|
|
||||||
/// ## 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 provided hash was not a hash
|
|
||||||
/// of a valid node at the tree size specified.
|
|
||||||
pub async fn get_merkle_audit_proof_by_hash(
|
|
||||||
&self,
|
|
||||||
hash: &str,
|
|
||||||
tree_size: u64
|
|
||||||
) -> reqwest::Result<GetProofByHashResponse> {
|
|
||||||
self.inner_client
|
|
||||||
.request(
|
|
||||||
endpoints::GET_PROOF_BY_HASH.0,
|
|
||||||
self.log_url.to_string() + endpoints::GET_PROOF_BY_HASH.1
|
|
||||||
)
|
|
||||||
.query(&[("hash", hash)])
|
|
||||||
.query(&[("tree_size", tree_size)])
|
|
||||||
.send()
|
|
||||||
.await?
|
|
||||||
.error_for_status()?
|
|
||||||
.json()
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,13 +41,3 @@ pub struct GetSthResponse {
|
||||||
pub struct GetSthConsistencyResponse {
|
pub struct GetSthConsistencyResponse {
|
||||||
pub consistency: Vec<String>
|
pub consistency: Vec<String>
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A response given when fetching the Merkle Audit Proof from a CT log merkle
|
|
||||||
/// leaf.
|
|
||||||
///
|
|
||||||
/// See: [`super::endpoints::GET_PROOF_BY_HASH`]
|
|
||||||
#[derive(Debug, Deserialize)]
|
|
||||||
pub struct GetProofByHashResponse {
|
|
||||||
pub leaf_index: u64,
|
|
||||||
pub audit_path: Vec<String>
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in a new issue