Skip to main content

wire_e2e_identity/acquisition/
thumbprint.rs

1use jwt_simple::prelude::*;
2use rusty_jwt_tools::{
3    jwk::TryIntoJwk,
4    prelude::{HashAlgorithm, JwkThumbprint, JwsAlgorithm},
5};
6use x509_cert::spki::SubjectPublicKeyInfoOwned;
7
8use crate::{acme, acquisition::error::CertificateError};
9
10/// The hash algorithm used for all thumbprints, regardless of the MLS ciphersuite.
11const THUMBPRINT_HASH_ALG: HashAlgorithm = HashAlgorithm::SHA256;
12
13/// Used to compute the MLS thumbprint of a Basic Credential
14pub fn compute_raw_key_thumbprint(sign_alg: JwsAlgorithm, signature_public_key: &[u8]) -> acme::Result<String> {
15    let jwk = match sign_alg {
16        JwsAlgorithm::Ed25519 => Ed25519PublicKey::from_bytes(signature_public_key)?.try_into_jwk()?,
17        JwsAlgorithm::P256 => ES256PublicKey::from_bytes(signature_public_key)?.try_into_jwk()?,
18        JwsAlgorithm::P384 => ES384PublicKey::from_bytes(signature_public_key)?.try_into_jwk()?,
19        JwsAlgorithm::P521 => ES512PublicKey::from_bytes(signature_public_key)?.try_into_jwk()?,
20    };
21    let thumbprint = JwkThumbprint::generate(&jwk, THUMBPRINT_HASH_ALG)?;
22    Ok(thumbprint.kid)
23}
24
25/// See: <https://datatracker.ietf.org/doc/html/rfc8037#appendix-A.3>
26pub(crate) fn try_compute_jwk_canonicalized_thumbprint(
27    cert: &x509_cert::TbsCertificate,
28) -> Result<String, CertificateError> {
29    let jwk = try_into_jwk(cert.subject_public_key_info())?;
30    let thumbprint = JwkThumbprint::generate(&jwk, THUMBPRINT_HASH_ALG)?;
31    Ok(thumbprint.kid)
32}
33
34fn try_into_jwk(spki: &SubjectPublicKeyInfoOwned) -> Result<Jwk, CertificateError> {
35    use const_oid::db::{
36        rfc5912::{ID_EC_PUBLIC_KEY, SECP_256_R_1, SECP_384_R_1, SECP_521_R_1},
37        rfc8410::{ID_ED_448, ID_ED_25519},
38    };
39    let params = spki
40        .algorithm
41        .parameters
42        .as_ref()
43        .and_then(|param| x509_cert::spki::ObjectIdentifier::from_bytes(param.value()).ok());
44
45    match (spki.algorithm.oid, params) {
46        (ID_ED_25519, None) => Ok(Ed25519PublicKey::from_bytes(spki.subject_public_key.raw_bytes())?.try_into_jwk()?),
47        (ID_ED_448, None) => Err(CertificateError::UnsupportedPublicKey),
48        (ID_EC_PUBLIC_KEY, Some(SECP_256_R_1)) => {
49            Ok(ES256PublicKey::from_bytes(spki.subject_public_key.raw_bytes())?.try_into_jwk()?)
50        }
51        (ID_EC_PUBLIC_KEY, Some(SECP_384_R_1)) => {
52            Ok(ES384PublicKey::from_bytes(spki.subject_public_key.raw_bytes())?.try_into_jwk()?)
53        }
54        (ID_EC_PUBLIC_KEY, Some(SECP_521_R_1)) => {
55            Ok(ES512PublicKey::from_bytes(spki.subject_public_key.raw_bytes())?.try_into_jwk()?)
56        }
57        _ => Err(CertificateError::UnsupportedPublicKey),
58    }
59}