1#![forbid(unsafe_code)]
2#![warn(rust_2018_idioms)]
3#![warn(future_incompatible)]
4#![forbid(missing_docs)]
5
6use p256::{
9 AffinePoint, NistP256, Scalar,
10 elliptic_curve::{
11 Curve,
12 generic_array::{GenericArray, typenum::Unsigned},
13 },
14};
15use rand::{CryptoRng, RngCore};
16use std::sync::LazyLock;
17use zeroize::ZeroizeOnDrop;
18
19#[derive(Clone, Debug)]
21pub enum KeyDecodingError {
22 InvalidKeyEncoding(String),
24 InvalidPemEncoding(String),
26 UnexpectedPemLabel(String),
28}
29
30static ECDSA_OID: LazyLock<simple_asn1::OID> =
31 LazyLock::new(|| simple_asn1::oid!(1, 2, 840, 10045, 2, 1));
32
33static SECP256R1_OID: LazyLock<simple_asn1::OID> =
35 LazyLock::new(|| simple_asn1::oid!(1, 2, 840, 10045, 3, 1, 7));
36
37#[derive(Clone, Debug)]
39pub struct DerivationIndex(pub Vec<u8>);
40
41#[derive(Clone, Debug)]
45pub struct DerivationPath {
46 path: Vec<DerivationIndex>,
47}
48
49impl DerivationPath {
50 pub fn new_bip32(bip32: &[u32]) -> Self {
55 let mut path = Vec::with_capacity(bip32.len());
56 for n in bip32 {
57 path.push(DerivationIndex(n.to_be_bytes().to_vec()));
58 }
59 Self::new(path)
60 }
61
62 pub fn new(path: Vec<DerivationIndex>) -> Self {
64 Self { path }
65 }
66
67 pub fn from_canister_id_and_path(canister_id: &[u8], path: &[Vec<u8>]) -> Self {
69 let mut vpath = Vec::with_capacity(1 + path.len());
70 vpath.push(DerivationIndex(canister_id.to_vec()));
71
72 for n in path {
73 vpath.push(DerivationIndex(n.to_vec()));
74 }
75 Self::new(vpath)
76 }
77
78 pub fn len(&self) -> usize {
80 self.path.len()
81 }
82
83 pub fn is_empty(&self) -> bool {
85 self.len() == 0
86 }
87
88 pub fn path(&self) -> &[DerivationIndex] {
90 &self.path
91 }
92
93 fn ckd(idx: &[u8], input: &[u8], chain_code: &[u8; 32]) -> ([u8; 32], Scalar) {
94 use hmac::{Hmac, Mac};
95 use p256::elliptic_curve::ops::Reduce;
96 use sha2::Sha512;
97
98 let mut hmac = Hmac::<Sha512>::new_from_slice(chain_code)
99 .expect("HMAC-SHA-512 should accept 256 bit key");
100
101 hmac.update(input);
102 hmac.update(idx);
103
104 let hmac_output: [u8; 64] = hmac.finalize().into_bytes().into();
105
106 let fb = p256::FieldBytes::from_slice(&hmac_output[..32]);
107 let next_offset = <p256::Scalar as Reduce<p256::U256>>::reduce_bytes(fb);
108 let next_chain_key: [u8; 32] = hmac_output[32..].to_vec().try_into().expect("Correct size");
109
110 if next_offset.to_bytes().to_vec() != hmac_output[..32] {
112 let mut next_input = [0u8; 33];
113 next_input[0] = 0x01;
114 next_input[1..].copy_from_slice(&next_chain_key);
115 Self::ckd(idx, &next_input, chain_code)
116 } else {
117 (next_chain_key, next_offset)
118 }
119 }
120
121 fn ckd_pub(
122 idx: &[u8],
123 pt: AffinePoint,
124 chain_code: &[u8; 32],
125 ) -> ([u8; 32], Scalar, AffinePoint) {
126 use p256::ProjectivePoint;
127 use p256::elliptic_curve::{group::GroupEncoding, ops::MulByGenerator};
128
129 let mut ckd_input = pt.to_bytes();
130
131 let pt: ProjectivePoint = pt.into();
132
133 loop {
134 let (next_chain_code, next_offset) = Self::ckd(idx, &ckd_input, chain_code);
135
136 let next_pt = (pt + ProjectivePoint::mul_by_generator(&next_offset)).to_affine();
137
138 if !bool::from(next_pt.is_identity()) {
140 return (next_chain_code, next_offset, next_pt);
141 }
142
143 ckd_input[0] = 0x01;
145 ckd_input[1..].copy_from_slice(&next_chain_code);
146 }
147 }
148
149 fn derive_offset(
150 &self,
151 pt: AffinePoint,
152 chain_code: &[u8; 32],
153 ) -> (AffinePoint, Scalar, [u8; 32]) {
154 let mut offset = Scalar::ZERO;
155 let mut pt = pt;
156 let mut chain_code = *chain_code;
157
158 for idx in self.path() {
159 let (next_chain_code, next_offset, next_pt) = Self::ckd_pub(&idx.0, pt, &chain_code);
160 chain_code = next_chain_code;
161 pt = next_pt;
162 offset = offset.add(&next_offset);
163 }
164
165 (pt, offset, chain_code)
166 }
167}
168
169const PEM_HEADER_PKCS8: &str = "PRIVATE KEY";
170const PEM_HEADER_RFC5915: &str = "EC PRIVATE KEY";
171
172fn der_encode_ecdsa_spki_pubkey(public_point: &[u8]) -> Vec<u8> {
176 use simple_asn1::*;
177
178 let ecdsa_oid = ASN1Block::ObjectIdentifier(0, ECDSA_OID.clone());
182 let secp256r1_oid = ASN1Block::ObjectIdentifier(0, SECP256R1_OID.clone());
183 let alg_id = ASN1Block::Sequence(0, vec![ecdsa_oid, secp256r1_oid]);
184
185 let key_bytes = ASN1Block::BitString(0, public_point.len() * 8, public_point.to_vec());
186
187 let blocks = vec![alg_id, key_bytes];
188
189 simple_asn1::to_der(&ASN1Block::Sequence(0, blocks))
190 .expect("Failed to encode ECDSA private key as DER")
191}
192
193fn der_encode_rfc5915_privatekey(
194 secret_key: &[u8],
195 include_curve: bool,
196 public_key: Option<Vec<u8>>,
197) -> Vec<u8> {
198 use simple_asn1::*;
199
200 let ecdsa_version = ASN1Block::Integer(0, BigInt::new(num_bigint::Sign::Plus, vec![1]));
204 let key_bytes = ASN1Block::OctetString(0, secret_key.to_vec());
205 let mut key_blocks = vec![ecdsa_version, key_bytes];
206
207 if include_curve {
208 let tag0 = BigUint::new(vec![0]);
209 let secp256r1_oid = Box::new(ASN1Block::ObjectIdentifier(0, SECP256R1_OID.clone()));
210 let oid_param = ASN1Block::Explicit(ASN1Class::ContextSpecific, 0, tag0, secp256r1_oid);
211 key_blocks.push(oid_param);
212 }
213
214 if let Some(public_key) = public_key {
215 let tag1 = BigUint::new(vec![1]);
216 let pk_bs = Box::new(ASN1Block::BitString(
217 0,
218 public_key.len() * 8,
219 public_key.to_vec(),
220 ));
221 let pk_param = ASN1Block::Explicit(ASN1Class::ContextSpecific, 0, tag1, pk_bs);
222 key_blocks.push(pk_param);
223 }
224
225 to_der(&ASN1Block::Sequence(0, key_blocks))
226 .expect("Failed to encode ECDSA private key as RFC 5915 DER")
227}
228
229fn der_encode_pkcs8_rfc5208_private_key(secret_key: &[u8]) -> Vec<u8> {
230 use simple_asn1::*;
231
232 let pkcs8_version = ASN1Block::Integer(0, BigInt::new(num_bigint::Sign::Plus, vec![0]));
236 let ecdsa_oid = ASN1Block::ObjectIdentifier(0, ECDSA_OID.clone());
237 let secp256r1_oid = ASN1Block::ObjectIdentifier(0, SECP256R1_OID.clone());
238
239 let alg_id = ASN1Block::Sequence(0, vec![ecdsa_oid, secp256r1_oid]);
240
241 let octet_string =
242 ASN1Block::OctetString(0, der_encode_rfc5915_privatekey(secret_key, false, None));
243
244 let blocks = vec![pkcs8_version, alg_id, octet_string];
245
246 simple_asn1::to_der(&ASN1Block::Sequence(0, blocks))
247 .expect("Failed to encode ECDSA private key as DER")
248}
249
250fn der_decode_rfc5915_privatekey(der: &[u8]) -> Result<Vec<u8>, KeyDecodingError> {
251 use simple_asn1::*;
252
253 let der = simple_asn1::from_der(der)
254 .map_err(|e| KeyDecodingError::InvalidKeyEncoding(format!("{e:?}")))?;
255
256 let seq = match der.len() {
257 1 => der.first(),
258 x => {
259 return Err(KeyDecodingError::InvalidKeyEncoding(format!(
260 "Unexpected number of elements {x}"
261 )));
262 }
263 };
264
265 if let Some(ASN1Block::Sequence(_, seq)) = seq {
266 match seq.first() {
268 Some(ASN1Block::Integer(_, _version)) => {}
269 _ => {
270 return Err(KeyDecodingError::InvalidKeyEncoding(
271 "Version field was not an integer".to_string(),
272 ));
273 }
274 };
275
276 let private_key = match seq.get(1) {
278 Some(ASN1Block::OctetString(_, sk)) => sk.clone(),
279 _ => {
280 return Err(KeyDecodingError::InvalidKeyEncoding(
281 "Not an octet string".to_string(),
282 ));
283 }
284 };
285
286 Ok(private_key)
290 } else {
291 Err(KeyDecodingError::InvalidKeyEncoding(
292 "Not a sequence".to_string(),
293 ))
294 }
295}
296
297fn pem_encode(raw: &[u8], label: &'static str) -> String {
298 pem::encode(&pem::Pem::new(label, raw))
299}
300
301#[derive(Copy, Clone, Debug)]
303pub enum InvalidSignatureEncoding {
304 InvalidEncoding,
306}
307
308#[derive(Clone, Debug)]
310pub struct Signature {
311 sig: p256::ecdsa::Signature,
312}
313
314impl Signature {
315 pub const BYTES: usize = 64;
320
321 fn new(sig: p256::ecdsa::Signature) -> Self {
322 Self { sig }
323 }
324
325 fn inner(&self) -> &p256::ecdsa::Signature {
326 &self.sig
327 }
328
329 pub fn deserialize(bytes: &[u8]) -> Result<Self, InvalidSignatureEncoding> {
334 p256::ecdsa::Signature::try_from(bytes)
335 .map_err(|_| InvalidSignatureEncoding::InvalidEncoding)
336 .map(Self::new)
337 }
338
339 pub fn deserialize_der(der: &[u8]) -> Result<Self, InvalidSignatureEncoding> {
341 p256::ecdsa::Signature::from_der(der)
342 .map_err(|_| InvalidSignatureEncoding::InvalidEncoding)
343 .map(Self::new)
344 }
345
346 pub fn serialize(&self) -> [u8; Signature::BYTES] {
351 self.sig.to_bytes().into()
352 }
353
354 pub fn serialize_der(&self) -> Vec<u8> {
358 self.sig.to_der().as_bytes().to_vec()
359 }
360}
361
362#[derive(Clone, ZeroizeOnDrop)]
364pub struct PrivateKey {
365 key: p256::ecdsa::SigningKey,
366}
367
368impl PrivateKey {
369 pub fn generate() -> Self {
371 let mut rng = rand::thread_rng();
372 Self::generate_using_rng(&mut rng)
373 }
374
375 pub fn generate_insecure_key_for_testing(seed: u64) -> Self {
377 use rand::SeedableRng;
378 let mut rng = rand_chacha::ChaCha20Rng::seed_from_u64(seed);
379 Self::generate_using_rng(&mut rng)
380 }
381
382 pub fn generate_using_rng<R: RngCore + CryptoRng>(rng: &mut R) -> Self {
384 let key = p256::ecdsa::SigningKey::random(rng);
385 Self { key }
386 }
387
388 pub fn deserialize_sec1(bytes: &[u8]) -> Result<Self, KeyDecodingError> {
390 let byte_array: [u8; <NistP256 as Curve>::FieldBytesSize::USIZE] =
391 bytes.try_into().map_err(|_e| {
392 KeyDecodingError::InvalidKeyEncoding(format!("invalid key size = {}.", bytes.len()))
393 })?;
394
395 let key = p256::ecdsa::SigningKey::from_bytes(&GenericArray::from(byte_array))
396 .map_err(|e| KeyDecodingError::InvalidKeyEncoding(format!("{e:?}")))?;
397 Ok(Self { key })
398 }
399
400 pub fn deserialize_rfc5915_der(der: &[u8]) -> Result<Self, KeyDecodingError> {
402 let key = der_decode_rfc5915_privatekey(der)?;
403 Self::deserialize_sec1(&key)
404 }
405
406 pub fn deserialize_pkcs8_der(der: &[u8]) -> Result<Self, KeyDecodingError> {
408 use p256::pkcs8::DecodePrivateKey;
409 let key = p256::ecdsa::SigningKey::from_pkcs8_der(der)
410 .map_err(|e| KeyDecodingError::InvalidKeyEncoding(format!("{e:?}")))?;
411 Ok(Self { key })
412 }
413
414 pub fn deserialize_pkcs8_pem(pem: &str) -> Result<Self, KeyDecodingError> {
416 let der =
417 pem::parse(pem).map_err(|e| KeyDecodingError::InvalidPemEncoding(format!("{e:?}")))?;
418 if der.tag() != PEM_HEADER_PKCS8 {
419 return Err(KeyDecodingError::UnexpectedPemLabel(der.tag().to_string()));
420 }
421
422 Self::deserialize_pkcs8_der(der.contents())
423 }
424
425 pub fn deserialize_rfc5915_pem(pem: &str) -> Result<Self, KeyDecodingError> {
427 let der =
428 pem::parse(pem).map_err(|e| KeyDecodingError::InvalidPemEncoding(format!("{e:?}")))?;
429 if der.tag() != PEM_HEADER_RFC5915 {
430 return Err(KeyDecodingError::UnexpectedPemLabel(der.tag().to_string()));
431 }
432
433 Self::deserialize_rfc5915_der(der.contents())
434 }
435
436 pub fn serialize_rfc5915_der(&self) -> Vec<u8> {
438 let sk = self.serialize_sec1();
439 let pk = self.public_key().serialize_sec1(false);
440 der_encode_rfc5915_privatekey(&sk, true, Some(pk))
441 }
442
443 pub fn serialize_rfc5915_pem(&self) -> String {
445 pem_encode(&self.serialize_rfc5915_der(), PEM_HEADER_RFC5915)
446 }
447
448 pub fn serialize_sec1(&self) -> Vec<u8> {
454 self.key.to_bytes().to_vec()
455 }
456
457 pub fn serialize_pkcs8_der(&self) -> Vec<u8> {
459 der_encode_pkcs8_rfc5208_private_key(&self.serialize_sec1())
460 }
461
462 pub fn serialize_pkcs8_pem(&self) -> String {
464 pem_encode(&self.serialize_pkcs8_der(), PEM_HEADER_PKCS8)
465 }
466
467 pub fn sign_message(&self, message: &[u8]) -> [u8; Signature::BYTES] {
471 use p256::ecdsa::signature::Signer;
472 let sig = Signature::new(self.key.sign(message));
473 sig.serialize()
474 }
475
476 pub fn sign_message_with_der_encoded_sig(&self, message: &[u8]) -> Vec<u8> {
480 use p256::ecdsa::signature::Signer;
481 let sig = Signature::new(self.key.sign(message));
482 sig.serialize_der()
483 }
484
485 pub fn sign_digest(&self, digest: &[u8]) -> Option<[u8; 64]> {
487 if digest.len() < 16 {
488 return None;
490 }
491
492 use p256::ecdsa::{Signature, signature::hazmat::PrehashSigner};
493 let sig: Signature = self
494 .key
495 .sign_prehash(digest)
496 .expect("Failed to sign digest");
497 Some(sig.to_bytes().into())
498 }
499
500 pub fn public_key(&self) -> PublicKey {
502 let key = self.key.verifying_key();
503 PublicKey { key: *key }
504 }
505
506 pub fn derive_subkey(&self, derivation_path: &DerivationPath) -> (Self, [u8; 32]) {
512 let chain_code = [0u8; 32];
513 self.derive_subkey_with_chain_code(derivation_path, &chain_code)
514 }
515
516 pub fn derive_subkey_with_chain_code(
523 &self,
524 derivation_path: &DerivationPath,
525 chain_code: &[u8; 32],
526 ) -> (Self, [u8; 32]) {
527 use p256::NonZeroScalar;
528
529 let public_key: AffinePoint = *self.key.verifying_key().as_affine();
530 let (_pt, offset, derived_chain_code) =
531 derivation_path.derive_offset(public_key, chain_code);
532
533 let derived_scalar = self.key.as_nonzero_scalar().as_ref().add(&offset);
534
535 let nz_ds =
536 NonZeroScalar::new(derived_scalar).expect("Derivation always produces non-zero sum");
537
538 let derived_key = Self {
539 key: p256::ecdsa::SigningKey::from(nz_ds),
540 };
541
542 (derived_key, derived_chain_code)
543 }
544}
545
546#[derive(Clone, Eq, PartialEq, Debug)]
548pub struct PublicKey {
549 key: p256::ecdsa::VerifyingKey,
550}
551
552impl PublicKey {
553 pub fn deserialize_sec1(bytes: &[u8]) -> Result<Self, KeyDecodingError> {
560 let key = p256::ecdsa::VerifyingKey::from_sec1_bytes(bytes)
561 .map_err(|e| KeyDecodingError::InvalidKeyEncoding(format!("{e:?}")))?;
562 Ok(Self { key })
563 }
564
565 pub fn deserialize_from_xy(x: &[u8], y: &[u8]) -> Result<Self, KeyDecodingError> {
569 const FIELD_BYTES: usize = 32;
570
571 if x.len() != FIELD_BYTES || y.len() != FIELD_BYTES {
572 return Err(KeyDecodingError::InvalidKeyEncoding(
573 "ECDSA x/y coordinates of invalid length".to_string(),
574 ));
575 }
576
577 let mut sec1 = [0u8; 1 + FIELD_BYTES * 2];
578 sec1[0] = 0x04;
579 sec1[1..(1 + FIELD_BYTES)].copy_from_slice(x);
580 sec1[(1 + FIELD_BYTES)..(1 + 2 * FIELD_BYTES)].copy_from_slice(y);
581
582 Self::deserialize_sec1(&sec1)
583 }
584
585 pub fn deserialize_der(bytes: &[u8]) -> Result<Self, KeyDecodingError> {
587 use p256::pkcs8::DecodePublicKey;
588 let key = p256::ecdsa::VerifyingKey::from_public_key_der(bytes)
589 .map_err(|e| KeyDecodingError::InvalidKeyEncoding(format!("{e:?}")))?;
590 Ok(Self { key })
591 }
592
593 pub fn deserialize_canonical_der(bytes: &[u8]) -> Result<Self, KeyDecodingError> {
599 let pk = Self::deserialize_der(bytes)?;
600
601 if pk.serialize_der() != bytes {
602 return Err(KeyDecodingError::InvalidKeyEncoding(
603 "Non-canonical encoding".to_string(),
604 ));
605 }
606
607 Ok(pk)
608 }
609
610 pub fn deserialize_pem(pem: &str) -> Result<Self, KeyDecodingError> {
612 let der =
613 pem::parse(pem).map_err(|e| KeyDecodingError::InvalidPemEncoding(format!("{e:?}")))?;
614 if der.tag() != "PUBLIC KEY" {
615 return Err(KeyDecodingError::UnexpectedPemLabel(der.tag().to_string()));
616 }
617
618 Self::deserialize_der(der.contents())
619 }
620
621 pub fn serialize_sec1(&self, compressed: bool) -> Vec<u8> {
627 self.key.to_encoded_point(compressed).to_bytes().to_vec()
628 }
629
630 pub fn serialize_der(&self) -> Vec<u8> {
632 der_encode_ecdsa_spki_pubkey(&self.serialize_sec1(false))
633 }
634
635 pub fn serialize_pem(&self) -> String {
637 pem_encode(&self.serialize_der(), "PUBLIC KEY")
638 }
639
640 pub fn verify_signature(&self, message: &[u8], signature: &[u8]) -> bool {
655 use p256::ecdsa::signature::Verifier;
656
657 if let Ok(sig) = Signature::deserialize(signature) {
658 self.key.verify(message, sig.inner()).is_ok()
659 } else {
660 false
661 }
662 }
663
664 pub fn verify_signature_with_der_encoded_sig(&self, message: &[u8], signature: &[u8]) -> bool {
669 use p256::ecdsa::signature::Verifier;
670
671 if let Ok(sig) = Signature::deserialize_der(signature) {
672 self.key.verify(message, sig.inner()).is_ok()
673 } else {
674 false
675 }
676 }
677
678 pub fn verify_signature_prehashed(&self, digest: &[u8], signature: &[u8]) -> bool {
680 use p256::ecdsa::signature::hazmat::PrehashVerifier;
681
682 if let Ok(sig) = Signature::deserialize(signature) {
683 self.key.verify_prehash(digest, sig.inner()).is_ok()
684 } else {
685 false
686 }
687 }
688
689 pub fn derive_subkey(&self, derivation_path: &DerivationPath) -> (Self, [u8; 32]) {
692 let chain_code = [0u8; 32];
693 self.derive_subkey_with_chain_code(derivation_path, &chain_code)
694 }
695
696 pub fn derive_subkey_with_chain_code(
701 &self,
702 derivation_path: &DerivationPath,
703 chain_code: &[u8; 32],
704 ) -> (Self, [u8; 32]) {
705 let public_key: AffinePoint = *self.key.as_affine();
706 let (pt, _offset, chain_code) = derivation_path.derive_offset(public_key, chain_code);
707
708 let derived_key = Self {
709 key: p256::ecdsa::VerifyingKey::from(
710 p256::PublicKey::from_affine(pt).expect("Derived point is valid"),
711 ),
712 };
713
714 (derived_key, chain_code)
715 }
716}