ts_crypto/
any.rs

1//! Any supported cryptographic key and associated methods.
2
3use const_oid::db::{
4    rfc5753::ID_EC_PUBLIC_KEY,
5    rfc5912::{RSA_ENCRYPTION, SECP_256_R_1, SECP_384_R_1, SECP_521_R_1},
6    rfc8410::{ID_ED_448, ID_ED_25519},
7};
8use der::{Decode, asn1::OctetString, pem::PemLabel};
9use pkcs8::DecodePrivateKey;
10use rsa::pkcs1::{DecodeRsaPrivateKey, DecodeRsaPublicKey};
11use spki::DecodePublicKey;
12
13use crate::{
14    EdwardsSigningKey, EdwardsVerifyingKey, EllipticSigningKey, EllipticVerifyingKey,
15    RsaSigningKey, RsaVerifyingKey,
16};
17
18/// Any supported verifying key.
19pub enum VerifyingKey {
20    /// An RSA key.
21    Rsa(RsaVerifyingKey),
22    /// An elliptic curve key.
23    Elliptic(EllipticVerifyingKey),
24    /// An Edwards curve key.
25    Edwards(EdwardsVerifyingKey),
26}
27
28/// Any supported signing key.
29#[expect(clippy::large_enum_variant)]
30pub enum SigningKey {
31    /// An RSA key.
32    Rsa(RsaSigningKey),
33    /// An elliptic curve key.
34    Elliptic(EllipticSigningKey),
35    /// And Edwards curve key.
36    Edwards(EdwardsSigningKey),
37}
38
39impl VerifyingKey {
40    /// Parse a verifying key from a PEM.
41    pub fn from_pem(pem: &[u8]) -> Option<Self> {
42        let (label, der) = der::pem::decode_vec(pem).ok()?;
43        match label {
44            spki::SubjectPublicKeyInfoOwned::PEM_LABEL => {
45                let spki = spki::SubjectPublicKeyInfoRef::from_der(&der).ok()?;
46                match spki.algorithm.oid {
47                    ID_EC_PUBLIC_KEY => match spki.algorithm.parameters_oid().ok()? {
48                        SECP_256_R_1 => {
49                            let key = p256::ecdsa::VerifyingKey::from_public_key_der(&der).ok()?;
50                            Some(Self::Elliptic(EllipticVerifyingKey::Prime256(key)))
51                        }
52                        SECP_384_R_1 => {
53                            let key = p384::ecdsa::VerifyingKey::from_public_key_der(&der).ok()?;
54                            Some(Self::Elliptic(EllipticVerifyingKey::Prime384(key)))
55                        }
56                        SECP_521_R_1 => {
57                            let key = p521::ecdsa::VerifyingKey::from_public_key_der(&der).ok()?;
58                            Some(Self::Elliptic(EllipticVerifyingKey::Prime521(key)))
59                        }
60                        _ => None,
61                    },
62                    RSA_ENCRYPTION => {
63                        let key = rsa::RsaPublicKey::from_public_key_der(&der).ok()?;
64                        Some(Self::Rsa(RsaVerifyingKey(key)))
65                    }
66                    ID_ED_25519 => {
67                        let key = ed25519_dalek::VerifyingKey::from_public_key_der(&der).ok()?;
68                        Some(Self::Edwards(EdwardsVerifyingKey::Ed25519(key)))
69                    }
70                    ID_ED_448 => {
71                        let key = ed448_goldilocks::VerifyingKey::from_public_key_der(&der).ok()?;
72                        Some(Self::Edwards(EdwardsVerifyingKey::Ed448(key)))
73                    }
74                    _ => None,
75                }
76            }
77            rsa::pkcs1::RsaPublicKey::PEM_LABEL => {
78                let key = rsa::RsaPublicKey::from_pkcs1_der(&der).ok()?;
79                Some(Self::Rsa(RsaVerifyingKey(key)))
80            }
81            _ => None,
82        }
83    }
84
85    /// Get the ID for this key.
86    pub fn key_id(&self) -> Vec<u8> {
87        match &self {
88            Self::Rsa(key) => key.key_id(),
89            Self::Elliptic(key) => key.key_id(),
90            Self::Edwards(key) => key.key_id(),
91        }
92    }
93}
94
95impl SigningKey {
96    /// Parse a signing key from a PEM.
97    pub fn from_pem(pem: &[u8]) -> Option<Self> {
98        let (label, der) = der::pem::decode_vec(pem).ok()?;
99
100        match label {
101            sec1::EcPrivateKey::PEM_LABEL => {
102                let sec1 = sec1::EcPrivateKey::from_der(&der).ok()?;
103                let curve = sec1.parameters?.named_curve()?;
104                match curve {
105                    SECP_256_R_1 => {
106                        let key = p256::ecdsa::SigningKey::from_slice(sec1.private_key).ok()?;
107                        Some(Self::Elliptic(EllipticSigningKey::Prime256(key)))
108                    }
109                    SECP_384_R_1 => {
110                        let key = p384::ecdsa::SigningKey::from_slice(sec1.private_key).ok()?;
111                        Some(Self::Elliptic(EllipticSigningKey::Prime384(key)))
112                    }
113                    SECP_521_R_1 => {
114                        let key = p521::ecdsa::SigningKey::from_slice(sec1.private_key).ok()?;
115                        Some(Self::Elliptic(EllipticSigningKey::Prime521(key)))
116                    }
117                    _ => None,
118                }
119            }
120            rsa::pkcs1::RsaPrivateKey::PEM_LABEL => {
121                let key = rsa::RsaPrivateKey::from_pkcs1_der(&der).ok()?;
122                Some(Self::Rsa(RsaSigningKey(key)))
123            }
124            pkcs8::PrivateKeyInfoOwned::PEM_LABEL => {
125                let pkcs8 = pkcs8::PrivateKeyInfoRef::from_der(&der).ok()?;
126                let algorithm = pkcs8.algorithm.oid;
127                match algorithm {
128                    ID_EC_PUBLIC_KEY => match pkcs8.algorithm.parameters_oid().ok()? {
129                        SECP_256_R_1 => {
130                            let key = p256::ecdsa::SigningKey::from_pkcs8_der(&der).ok()?;
131                            Some(Self::Elliptic(EllipticSigningKey::Prime256(key)))
132                        }
133                        SECP_384_R_1 => {
134                            let key = p384::ecdsa::SigningKey::from_pkcs8_der(&der).ok()?;
135                            Some(Self::Elliptic(EllipticSigningKey::Prime384(key)))
136                        }
137                        SECP_521_R_1 => {
138                            let key = p521::ecdsa::SigningKey::from_pkcs8_der(&der).ok()?;
139                            Some(Self::Elliptic(EllipticSigningKey::Prime521(key)))
140                        }
141                        _ => None,
142                    },
143                    RSA_ENCRYPTION => {
144                        let key = rsa::RsaPrivateKey::from_pkcs8_der(&der).ok()?;
145                        Some(Self::Rsa(RsaSigningKey(key)))
146                    }
147                    ID_ED_25519 => {
148                        let key = ed25519_dalek::SigningKey::from_pkcs8_der(&der).ok()?;
149                        Some(Self::Edwards(EdwardsSigningKey::Ed25519(key)))
150                    }
151                    ID_ED_448 => {
152                        // The current rust-crypto implementation of from_pkcs8 for ed448 fails, so some manual decoding is required.
153                        // See <https://github.com/RustCrypto/elliptic-curves/issues/1326>
154                        let octet_string =
155                            <OctetString as Decode>::from_der(pkcs8.private_key.as_bytes()).ok()?;
156                        let secret_key =
157                            ed448_goldilocks::SecretKey::try_from(octet_string.as_bytes()).ok()?;
158                        let key = ed448_goldilocks::SigningKey::from(secret_key);
159
160                        // let key = ed448_goldilocks::SigningKey::from_pkcs8_der(&der).ok()?;
161                        Some(Self::Edwards(EdwardsSigningKey::Ed448(key)))
162                    }
163                    _ => None,
164                }
165            }
166            _ => None,
167        }
168    }
169
170    /// Get the verifying key for this signing key.
171    pub fn verifying_key(&self) -> VerifyingKey {
172        match &self {
173            Self::Rsa(key) => VerifyingKey::Rsa(key.verifying_key()),
174            Self::Elliptic(key) => VerifyingKey::Elliptic(key.verifying_key()),
175            Self::Edwards(key) => VerifyingKey::Edwards(key.verifying_key()),
176        }
177    }
178}