picky/x509/
key_id_gen_method.rs

1use crate::hash::HashAlgorithm;
2use crate::key::{KeyError, PublicKey};
3use picky_asn1::wrapper::BitStringAsn1Container;
4use picky_asn1_der::Asn1DerError;
5use thiserror::Error;
6
7#[derive(Debug, Error)]
8pub enum KeyIdGenError {
9    /// asn1 serialization error
10    #[error("(asn1) couldn't serialize {element}: {source}")]
11    Asn1Serialization {
12        element: &'static str,
13        source: Asn1DerError,
14    },
15
16    /// invalid key
17    #[error("invalid key: {source}")]
18    InvalidKey { source: KeyError },
19}
20
21/// Describes which method to use to generate key identifiers.
22///
23/// See [RFC5280 #4](https://tools.ietf.org/html/rfc5280#section-4.2.1.2) and
24/// [RFC7093 #2](https://tools.ietf.org/html/rfc7093#section-2).
25#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
26pub enum KeyIdGenMethod {
27    /// Hash the leftmost 160-bits of the
28    /// SHA-256 hash of the value of the BIT STRING subjectPublicKey
29    /// (excluding the tag, length, and number of unused bits).
30    SPKValueHashedLeftmost160(HashAlgorithm),
31    /// Hash the DER encoding of the SubjectPublicKeyInfo value.
32    SPKFullDER(HashAlgorithm),
33}
34
35impl KeyIdGenMethod {
36    pub fn generate_from(self, public_key: &PublicKey) -> Result<Vec<u8>, KeyIdGenError> {
37        use picky_asn1_x509::PublicKey as InnerPublicKey;
38
39        match self {
40            KeyIdGenMethod::SPKValueHashedLeftmost160(hash_algo) => match &public_key.as_inner().subject_public_key {
41                InnerPublicKey::Rsa(BitStringAsn1Container(rsa_pk)) => {
42                    let der = picky_asn1_der::to_vec(rsa_pk).map_err(|e| KeyIdGenError::Asn1Serialization {
43                        source: e,
44                        element: "RSA private key",
45                    })?;
46                    Ok(hash_algo.digest(&der)[..20].to_vec())
47                }
48                InnerPublicKey::Ec(bitstring) => {
49                    let der = bitstring.0.payload_view();
50                    Ok(hash_algo.digest(&der)[..20].to_vec())
51                }
52                InnerPublicKey::Ed(bitstring) => {
53                    let der = bitstring.0.payload_view();
54                    Ok(hash_algo.digest(&der)[..20].to_vec())
55                }
56            },
57            KeyIdGenMethod::SPKFullDER(hash_algo) => {
58                let der = public_key
59                    .to_der()
60                    .map_err(|e| KeyIdGenError::InvalidKey { source: e })?;
61                Ok(hash_algo.digest(&der))
62            }
63        }
64    }
65}