1use super::AlgorithmName;
2use crate::{
3 error::{HttpSigError, HttpSigResult},
4 trace::*,
5};
6use ecdsa::{
7 elliptic_curve::{sec1::ToEncodedPoint, PublicKey as EcPublicKey, SecretKey as EcSecretKey},
8 signature::{DigestSigner, DigestVerifier},
9};
10use ed25519_compact::{PublicKey as Ed25519PublicKey, SecretKey as Ed25519SecretKey};
11use p256::NistP256;
12use p384::NistP384;
13use pkcs8::{der::Decode, Document, PrivateKeyInfo};
14use sha2::{Digest, Sha256, Sha384};
15use spki::SubjectPublicKeyInfoRef;
16
17#[allow(non_upper_case_globals, dead_code)]
18mod algorithm_oids {
20 pub const EC: &str = "1.2.840.10045.2.1";
22 pub const Ed25519: &str = "1.3.101.112";
24}
25#[allow(non_upper_case_globals, dead_code)]
26mod params_oids {
28 pub const Secp256r1: &str = "1.2.840.10045.3.1.7";
30 pub const Secp384r1: &str = "1.3.132.0.34";
32}
33
34#[derive(Debug, Clone)]
36pub enum SecretKey {
39 EcdsaP384Sha384(EcSecretKey<NistP384>),
41 EcdsaP256Sha256(EcSecretKey<NistP256>),
43 Ed25519(Ed25519SecretKey),
45}
46
47impl SecretKey {
48 pub fn from_bytes(alg: AlgorithmName, bytes: &[u8]) -> HttpSigResult<Self> {
50 match alg {
51 AlgorithmName::EcdsaP256Sha256 => {
52 debug!("Read P256 private key");
53 let sk = EcSecretKey::from_bytes(bytes.into()).map_err(|e| HttpSigError::ParsePrivateKeyError(e.to_string()))?;
54 Ok(Self::EcdsaP256Sha256(sk))
55 }
56 AlgorithmName::EcdsaP384Sha384 => {
57 debug!("Read P384 private key");
58 let sk = EcSecretKey::from_bytes(bytes.into()).map_err(|e| HttpSigError::ParsePrivateKeyError(e.to_string()))?;
59 Ok(Self::EcdsaP384Sha384(sk))
60 }
61 AlgorithmName::Ed25519 => {
62 debug!("Read Ed25519 private key");
63 let mut seed = [0u8; 32];
64 seed.copy_from_slice(bytes);
65 let sk = ed25519_compact::KeyPair::from_seed(ed25519_compact::Seed::new(seed)).sk;
66 Ok(Self::Ed25519(sk))
67 }
68 _ => Err(HttpSigError::ParsePrivateKeyError("Unsupported algorithm".to_string())),
69 }
70 }
71 pub fn from_der(der: &[u8]) -> HttpSigResult<Self> {
74 let pki = PrivateKeyInfo::from_der(der).map_err(|e| HttpSigError::ParsePrivateKeyError(e.to_string()))?;
75
76 let (algorithm_name, sk_bytes) = match pki.algorithm.oid.to_string().as_ref() {
77 algorithm_oids::EC => {
79 let param = pki
80 .algorithm
81 .parameters_oid()
82 .map_err(|e| HttpSigError::ParsePrivateKeyError(e.to_string()))?;
83 let algorithm_name = match param.to_string().as_ref() {
84 params_oids::Secp256r1 => AlgorithmName::EcdsaP256Sha256,
85 params_oids::Secp384r1 => AlgorithmName::EcdsaP384Sha384,
86 _ => return Err(HttpSigError::ParsePrivateKeyError("Unsupported curve".to_string())),
87 };
88 let sk_bytes = sec1::EcPrivateKey::try_from(pki.private_key)
89 .map_err(|e| HttpSigError::ParsePrivateKeyError(format!("Error decoding EcPrivateKey: {e}")))?
90 .private_key;
91 (algorithm_name, sk_bytes)
92 }
93 algorithm_oids::Ed25519 => (AlgorithmName::Ed25519, &pki.private_key[2..]),
95 _ => return Err(HttpSigError::ParsePrivateKeyError("Unsupported algorithm".to_string())),
96 };
97 let sk = Self::from_bytes(algorithm_name, sk_bytes)?;
98 Ok(sk)
99 }
100
101 pub fn from_pem(pem: &str) -> HttpSigResult<Self> {
103 let (tag, doc) = Document::from_pem(pem).map_err(|e| HttpSigError::ParsePrivateKeyError(e.to_string()))?;
104 if tag != "PRIVATE KEY" {
105 return Err(HttpSigError::ParsePrivateKeyError("Invalid tag".to_string()));
106 };
107 Self::from_der(doc.as_bytes())
108 }
109
110 pub fn public_key(&self) -> PublicKey {
112 match &self {
113 Self::EcdsaP256Sha256(key) => PublicKey::EcdsaP256Sha256(key.public_key()),
114 Self::EcdsaP384Sha384(key) => PublicKey::EcdsaP384Sha384(key.public_key()),
115 Self::Ed25519(key) => PublicKey::Ed25519(key.public_key()),
116 }
117 }
118}
119
120impl super::SigningKey for SecretKey {
121 fn sign(&self, data: &[u8]) -> HttpSigResult<Vec<u8>> {
123 match &self {
124 Self::EcdsaP256Sha256(sk) => {
125 debug!("Sign EcdsaP256Sha256");
126 let sk = ecdsa::SigningKey::from(sk);
127 let mut digest = <Sha256 as Digest>::new();
128 digest.update(data);
129 let sig: ecdsa::Signature<NistP256> = sk.sign_digest(digest);
130 Ok(sig.to_bytes().to_vec())
131 }
132 Self::EcdsaP384Sha384(sk) => {
133 debug!("Sign EcdsaP384Sha384");
134 let sk = ecdsa::SigningKey::from(sk);
135 let mut digest = <Sha384 as Digest>::new();
136 digest.update(data);
137 let sig: ecdsa::Signature<NistP384> = sk.sign_digest(digest);
138 Ok(sig.to_bytes().to_vec())
139 }
140 Self::Ed25519(sk) => {
141 debug!("Sign Ed25519");
142 let sig = sk.sign(data, Some(ed25519_compact::Noise::default()));
143 Ok(sig.as_ref().to_vec())
144 }
145 }
146 }
147
148 fn key_id(&self) -> String {
149 use super::VerifyingKey;
150 self.public_key().key_id()
151 }
152
153 fn alg(&self) -> AlgorithmName {
154 use super::VerifyingKey;
155 self.public_key().alg()
156 }
157}
158
159impl super::VerifyingKey for SecretKey {
160 fn verify(&self, data: &[u8], signature: &[u8]) -> HttpSigResult<()> {
161 self.public_key().verify(data, signature)
162 }
163
164 fn key_id(&self) -> String {
165 self.public_key().key_id()
166 }
167
168 fn alg(&self) -> AlgorithmName {
169 self.public_key().alg()
170 }
171}
172
173#[derive(Debug, Clone)]
175pub enum PublicKey {
178 EcdsaP256Sha256(EcPublicKey<NistP256>),
180 EcdsaP384Sha384(EcPublicKey<NistP384>),
182 Ed25519(Ed25519PublicKey),
184}
185
186impl PublicKey {
187 pub fn from_bytes(alg: AlgorithmName, bytes: &[u8]) -> HttpSigResult<Self> {
189 match alg {
190 AlgorithmName::EcdsaP256Sha256 => {
191 debug!("Read P256 public key");
192 let pk = EcPublicKey::from_sec1_bytes(bytes).map_err(|e| HttpSigError::ParsePublicKeyError(e.to_string()))?;
193 Ok(Self::EcdsaP256Sha256(pk))
194 }
195 AlgorithmName::EcdsaP384Sha384 => {
196 debug!("Read P384 public key");
197 let pk = EcPublicKey::from_sec1_bytes(bytes).map_err(|e| HttpSigError::ParsePublicKeyError(e.to_string()))?;
198 Ok(Self::EcdsaP384Sha384(pk))
199 }
200 AlgorithmName::Ed25519 => {
201 debug!("Read Ed25519 public key");
202 let pk = ed25519_compact::PublicKey::from_slice(bytes).map_err(|e| HttpSigError::ParsePublicKeyError(e.to_string()))?;
203 Ok(Self::Ed25519(pk))
204 }
205 _ => Err(HttpSigError::ParsePublicKeyError("Unsupported algorithm".to_string())),
206 }
207 }
208
209 #[allow(dead_code)]
210 pub fn from_pem(pem: &str) -> HttpSigResult<Self> {
212 let (tag, doc) = Document::from_pem(pem).map_err(|e| HttpSigError::ParsePublicKeyError(e.to_string()))?;
213 if tag != "PUBLIC KEY" {
214 return Err(HttpSigError::ParsePublicKeyError("Invalid tag".to_string()));
215 };
216
217 let spki_ref = SubjectPublicKeyInfoRef::from_der(doc.as_bytes())
218 .map_err(|e| HttpSigError::ParsePublicKeyError(format!("Error decoding SubjectPublicKeyInfo: {e}").to_string()))?;
219
220 let (algorithm_name, pk_bytes) = match spki_ref.algorithm.oid.to_string().as_ref() {
221 algorithm_oids::EC => {
223 let param = spki_ref
224 .algorithm
225 .parameters_oid()
226 .map_err(|e| HttpSigError::ParsePublicKeyError(e.to_string()))?;
227 let algorithm_name = match param.to_string().as_ref() {
228 params_oids::Secp256r1 => AlgorithmName::EcdsaP256Sha256,
229 params_oids::Secp384r1 => AlgorithmName::EcdsaP384Sha384,
230 _ => return Err(HttpSigError::ParsePublicKeyError("Unsupported curve".to_string())),
231 };
232 let pk_bytes = spki_ref
233 .subject_public_key
234 .as_bytes()
235 .ok_or(HttpSigError::ParsePublicKeyError("Invalid public key".to_string()))?;
236 (algorithm_name, pk_bytes)
237 }
238 algorithm_oids::Ed25519 => (
240 AlgorithmName::Ed25519,
241 spki_ref
242 .subject_public_key
243 .as_bytes()
244 .ok_or(HttpSigError::ParsePublicKeyError("Invalid public key".to_string()))?,
245 ),
246 _ => return Err(HttpSigError::ParsePublicKeyError("Unsupported algorithm".to_string())),
247 };
248 Self::from_bytes(algorithm_name, pk_bytes)
249 }
250}
251
252impl super::VerifyingKey for PublicKey {
253 fn verify(&self, data: &[u8], signature: &[u8]) -> HttpSigResult<()> {
255 match self {
256 Self::EcdsaP256Sha256(pk) => {
257 debug!("Verify EcdsaP256Sha256");
258 let signature = ecdsa::Signature::<NistP256>::from_bytes(signature.into())
259 .map_err(|e| HttpSigError::ParseSignatureError(e.to_string()))?;
260 let vk = ecdsa::VerifyingKey::from(pk);
261 let mut digest = <Sha256 as Digest>::new();
262 digest.update(data);
263 vk.verify_digest(digest, &signature)
264 .map_err(|e| HttpSigError::InvalidSignature(e.to_string()))
265 }
266 Self::EcdsaP384Sha384(pk) => {
267 debug!("Verify EcdsaP384Sha384");
268 let signature = ecdsa::Signature::<NistP384>::from_bytes(signature.into())
269 .map_err(|e| HttpSigError::ParseSignatureError(e.to_string()))?;
270 let vk = ecdsa::VerifyingKey::from(pk);
271 let mut digest = <Sha384 as Digest>::new();
272 digest.update(data);
273 vk.verify_digest(digest, &signature)
274 .map_err(|e| HttpSigError::InvalidSignature(e.to_string()))
275 }
276 Self::Ed25519(pk) => {
277 debug!("Verify Ed25519");
278 let sig =
279 ed25519_compact::Signature::from_slice(signature).map_err(|e| HttpSigError::ParseSignatureError(e.to_string()))?;
280 pk.verify(data, &sig)
281 .map_err(|e| HttpSigError::InvalidSignature(e.to_string()))
282 }
283 }
284 }
285
286 fn key_id(&self) -> String {
288 use base64::{engine::general_purpose, Engine as _};
289
290 let bytes = match self {
291 Self::EcdsaP256Sha256(vk) => vk.to_encoded_point(true).as_bytes().to_vec(),
292 Self::EcdsaP384Sha384(vk) => vk.to_encoded_point(true).as_bytes().to_vec(),
293 Self::Ed25519(vk) => vk.as_ref().to_vec(),
294 };
295 let mut hasher = <Sha256 as Digest>::new();
296 hasher.update(&bytes);
297 let hash = hasher.finalize();
298 general_purpose::STANDARD.encode(hash)
299 }
300
301 fn alg(&self) -> AlgorithmName {
303 match self {
304 Self::EcdsaP256Sha256(_) => AlgorithmName::EcdsaP256Sha256,
305 Self::EcdsaP384Sha384(_) => AlgorithmName::EcdsaP384Sha384,
306 Self::Ed25519(_) => AlgorithmName::Ed25519,
307 }
308 }
309}
310
311#[cfg(test)]
312mod tests {
313 use p256::elliptic_curve::group::GroupEncoding;
314
315 use super::*;
316 use std::matches;
317
318 const P256_SECERT_KEY: &str = r##"-----BEGIN PRIVATE KEY-----
319MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgv7zxW56ojrWwmSo1
3204uOdbVhUfj9Jd+5aZIB9u8gtWnihRANCAARGYsMe0CT6pIypwRvoJlLNs4+cTh2K
321L7fUNb5i6WbKxkpAoO+6T3pMBG5Yw7+8NuGTvvtrZAXduA2giPxQ8zCf
322-----END PRIVATE KEY-----
323"##;
324 const P256_PUBLIC_KEY: &str = r##"-----BEGIN PUBLIC KEY-----
325MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAERmLDHtAk+qSMqcEb6CZSzbOPnE4d
326ii+31DW+YulmysZKQKDvuk96TARuWMO/vDbhk777a2QF3bgNoIj8UPMwnw==
327-----END PUBLIC KEY-----
328"##;
329 const P384_SECERT_KEY: &str = r##"-----BEGIN PRIVATE KEY-----
330MIG2AgEAMBAGByqGSM49AgEGBSuBBAAiBIGeMIGbAgEBBDCPYbeLLlIQKUzVyVGH
331MeuFp/9o2Lr+4GrI3bsbHuViMMceiuM+8xqzFCSm4Ltl5UyhZANiAARKg3yM+Ltx
332n4ZptF3hI6Q167crEtPRklCEsRTyWUqy+VrrnM5LU/+fqxVbyniBZHd4vmQVYtjF
333xsv8P3DpjvpKJZqFfVdIr2ZR+kYDKHwIruIF9fCPawAH2tnbuc3xEzQ=
334-----END PRIVATE KEY-----
335"##;
336 const P384_PUBLIC_KEY: &str = r##"-----BEGIN PUBLIC KEY-----
337MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAESoN8jPi7cZ+GabRd4SOkNeu3KxLT0ZJQ
338hLEU8llKsvla65zOS1P/n6sVW8p4gWR3eL5kFWLYxcbL/D9w6Y76SiWahX1XSK9m
339UfpGAyh8CK7iBfXwj2sAB9rZ27nN8RM0
340-----END PUBLIC KEY-----
341"##;
342
343 const EDDSA_SECRET_KEY: &str = r##"-----BEGIN PRIVATE KEY-----
344MC4CAQAwBQYDK2VwBCIEIDSHAE++q1BP7T8tk+mJtS+hLf81B0o6CFyWgucDFN/C
345-----END PRIVATE KEY-----
346"##;
347 const EDDSA_PUBLIC_KEY: &str = r##"-----BEGIN PUBLIC KEY-----
348MCowBQYDK2VwAyEA1ixMQcxO46PLlgQfYS46ivFd+n0CcDHSKUnuhm3i1O0=
349-----END PUBLIC KEY-----
350"##;
351
352 #[test]
353 fn test_from_bytes() {
354 let ed25519_kp = ed25519_compact::KeyPair::from_seed(ed25519_compact::Seed::default());
355 let ed25519_sk = ed25519_kp.sk.seed().to_vec();
356 let ed25519_pk = ed25519_kp.pk.as_ref();
357 let sk = SecretKey::from_bytes(AlgorithmName::Ed25519, &ed25519_sk).unwrap();
358 assert!(matches!(sk, SecretKey::Ed25519(_)));
359 let pk = PublicKey::from_bytes(AlgorithmName::Ed25519, ed25519_pk).unwrap();
360 assert!(matches!(pk, PublicKey::Ed25519(_)));
361
362 let mut rng = rand_085::thread_rng();
363 let es256_sk = p256::ecdsa::SigningKey::random(&mut rng);
364 let es256_pk = es256_sk.verifying_key();
365 let sk = SecretKey::from_bytes(AlgorithmName::EcdsaP256Sha256, es256_sk.to_bytes().as_ref()).unwrap();
366 assert!(matches!(sk, SecretKey::EcdsaP256Sha256(_)));
367 let pk_bytes = es256_pk.as_affine().to_bytes();
368 let pk = PublicKey::from_bytes(AlgorithmName::EcdsaP256Sha256, pk_bytes.as_ref()).unwrap();
369 assert!(matches!(pk, PublicKey::EcdsaP256Sha256(_)));
370 }
371
372 #[test]
373 fn test_from_pem() {
374 let sk = SecretKey::from_pem(P256_SECERT_KEY).unwrap();
375 assert!(matches!(sk, SecretKey::EcdsaP256Sha256(_)));
376 let pk = PublicKey::from_pem(P256_PUBLIC_KEY).unwrap();
377 assert!(matches!(pk, PublicKey::EcdsaP256Sha256(_)));
378
379 let sk = SecretKey::from_pem(P384_SECERT_KEY).unwrap();
380 assert!(matches!(sk, SecretKey::EcdsaP384Sha384(_)));
381 let pk = PublicKey::from_pem(P384_PUBLIC_KEY).unwrap();
382 assert!(matches!(pk, PublicKey::EcdsaP384Sha384(_)));
383
384 let sk = SecretKey::from_pem(EDDSA_SECRET_KEY).unwrap();
385 assert!(matches!(sk, SecretKey::Ed25519(_)));
386 let pk = PublicKey::from_pem(EDDSA_PUBLIC_KEY).unwrap();
387 assert!(matches!(pk, PublicKey::Ed25519(_)));
388 }
389
390 #[test]
391 fn test_sign_verify() {
392 use super::super::{SigningKey, VerifyingKey};
393 let sk = SecretKey::from_pem(P256_SECERT_KEY).unwrap();
394 let pk = PublicKey::from_pem(P256_PUBLIC_KEY).unwrap();
395 let data = b"hello world";
396 let signature = sk.sign(data).unwrap();
397 pk.verify(data, &signature).unwrap();
398 assert!(pk.verify(b"hello", &signature).is_err());
399
400 let sk = SecretKey::from_pem(P384_SECERT_KEY).unwrap();
401 let pk = PublicKey::from_pem(P384_PUBLIC_KEY).unwrap();
402 let data = b"hello world";
403 let signature = sk.sign(data).unwrap();
404 pk.verify(data, &signature).unwrap();
405 assert!(pk.verify(b"hello", &signature).is_err());
406
407 let sk = SecretKey::from_pem(EDDSA_SECRET_KEY).unwrap();
408 let pk = PublicKey::from_pem(EDDSA_PUBLIC_KEY).unwrap();
409 let data = b"hello world";
410 let signature = sk.sign(data).unwrap();
411 pk.verify(data, &signature).unwrap();
412 assert!(pk.verify(b"hello", &signature).is_err());
413 }
414
415 #[test]
416 fn test_kid() -> HttpSigResult<()> {
417 use super::super::VerifyingKey;
418 let sk = SecretKey::from_pem(P256_SECERT_KEY)?;
419 let pk = PublicKey::from_pem(P256_PUBLIC_KEY)?;
420 assert_eq!(sk.public_key().key_id(), pk.key_id());
421 assert_eq!(pk.key_id(), "k34r3Nqfak67bhJSXTjTRo5tCIr1Bsre1cPoJ3LJ9xE=");
422
423 let sk = SecretKey::from_pem(P384_SECERT_KEY)?;
424 let pk = PublicKey::from_pem(P384_PUBLIC_KEY)?;
425 assert_eq!(sk.public_key().key_id(), pk.key_id());
426 assert_eq!(pk.key_id(), "JluSJKLaQsbGcgg1Ves4FfP/Kf7qS11RT88TvU0eNSo=");
427
428 let sk = SecretKey::from_pem(EDDSA_SECRET_KEY)?;
429 let pk = PublicKey::from_pem(EDDSA_PUBLIC_KEY)?;
430 assert_eq!(sk.public_key().key_id(), pk.key_id());
431 assert_eq!(pk.key_id(), "gjrE7ACMxgzYfFHgabgf4kLTg1eKIdsJ94AiFTFj1is=");
432 Ok(())
433 }
434}