Skip to main content

ic_secp256r1/
lib.rs

1#![forbid(unsafe_code)]
2#![warn(rust_2018_idioms)]
3#![warn(future_incompatible)]
4#![forbid(missing_docs)]
5
6//! A crate with handling of ECDSA keys over the secp256r1 curve
7
8use 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/// An error indicating that decoding a key failed
20#[derive(Clone, Debug)]
21pub enum KeyDecodingError {
22    /// The key encoding was invalid in some way
23    InvalidKeyEncoding(String),
24    /// The PEM encoding was invalid
25    InvalidPemEncoding(String),
26    /// The PEM encoding had an unexpected label
27    UnexpectedPemLabel(String),
28}
29
30static ECDSA_OID: LazyLock<simple_asn1::OID> =
31    LazyLock::new(|| simple_asn1::oid!(1, 2, 840, 10045, 2, 1));
32
33/// See RFC 5759 section 3.2
34static SECP256R1_OID: LazyLock<simple_asn1::OID> =
35    LazyLock::new(|| simple_asn1::oid!(1, 2, 840, 10045, 3, 1, 7));
36
37/// A component of a derivation path
38#[derive(Clone, Debug)]
39pub struct DerivationIndex(pub Vec<u8>);
40
41/// Derivation Path
42///
43/// A derivation path is simply a sequence of DerivationIndex
44#[derive(Clone, Debug)]
45pub struct DerivationPath {
46    path: Vec<DerivationIndex>,
47}
48
49impl DerivationPath {
50    /// Create a BIP32-style derivation path
51    ///
52    /// See SLIP-10 <https://github.com/satoshilabs/slips/blob/master/slip-0010.md>
53    /// for details of derivation paths
54    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    /// Create a free-form derivation path
63    pub fn new(path: Vec<DerivationIndex>) -> Self {
64        Self { path }
65    }
66
67    /// Create a path from a canister ID and a user provided path
68    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    /// Return the length of this path
79    pub fn len(&self) -> usize {
80        self.path.len()
81    }
82
83    /// Return if this path is empty
84    pub fn is_empty(&self) -> bool {
85        self.len() == 0
86    }
87
88    /// Return the components of the derivation path
89    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 iL >= order, try again with the "next" index as described in SLIP-10
111        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 the new key is not infinity, we're done: return the new key
139            if !bool::from(next_pt.is_identity()) {
140                return (next_chain_code, next_offset, next_pt);
141            }
142
143            // Otherwise set up the next input as defined by SLIP-0010
144            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
172/// DER encode the public point into a SubjectPublicKeyInfo
173///
174/// The public_point can be either the compressed or uncompressed format
175fn der_encode_ecdsa_spki_pubkey(public_point: &[u8]) -> Vec<u8> {
176    use simple_asn1::*;
177
178    // simple_asn1::to_der can only fail if you use an invalid object identifier
179    // so to avoid returning a Result from this function we use expect
180
181    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    // simple_asn1::to_der can only fail if you use an invalid object identifier
201    // so to avoid returning a Result from this function we use expect
202
203    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    // simple_asn1::to_der can only fail if you use an invalid object identifier
233    // so to avoid returning a Result from this function we use expect
234
235    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        // mandatory field: version, should be equal to 1
267        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        // mandatory field: the private key
277        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        // following may be optional params and/or public key, which
287        // we ignore
288
289        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/// Error if a signature is not a valid encoding
302#[derive(Copy, Clone, Debug)]
303pub enum InvalidSignatureEncoding {
304    /// The encoding was not valid; no further details available
305    InvalidEncoding,
306}
307
308/// An ECDSA P-256 signature
309#[derive(Clone, Debug)]
310pub struct Signature {
311    sig: p256::ecdsa::Signature,
312}
313
314impl Signature {
315    /// The length of a P-256 signature
316    ///
317    /// Note this is the length for the underlying signature rather than the DER encoding,
318    /// which has a variable length
319    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    /// Deserialize a signature in the standard encoding
330    ///
331    /// This consists of r || s both encoded as a fixed length field
332    /// Sometimes referred to as IEEE 1363 format
333    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    /// Deserialize a DER encoded signature
340    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    /// Return the signature encoded in the standard encoding
347    ///
348    /// This consists of r || s both encoded as a fixed length field
349    /// Sometimes referred to as IEEE 1363 format
350    pub fn serialize(&self) -> [u8; Signature::BYTES] {
351        self.sig.to_bytes().into()
352    }
353
354    /// Return the signature in DER encoding
355    ///
356    /// This encoding is variable length due to use of ASN.1
357    pub fn serialize_der(&self) -> Vec<u8> {
358        self.sig.to_der().as_bytes().to_vec()
359    }
360}
361
362/// An ECDSA private key
363#[derive(Clone, ZeroizeOnDrop)]
364pub struct PrivateKey {
365    key: p256::ecdsa::SigningKey,
366}
367
368impl PrivateKey {
369    /// Generate a new random private key
370    pub fn generate() -> Self {
371        let mut rng = rand::thread_rng();
372        Self::generate_using_rng(&mut rng)
373    }
374
375    /// Generate an INSECURE key usable for testing
376    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    /// Generate a new random private key using some provided RNG
383    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    /// Deserialize a private key encoded in SEC1 format
389    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    /// Deserialize a private key encoded in RFC 5915 format
401    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    /// Deserialize a private key encoded in PKCS8 format
407    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    /// Deserialize a private key encoded in PKCS8 format with PEM encoding
415    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    /// Deserialize a private key encoded in RFC 5915 format with PEM encoding
426    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    /// Serialize the private key as RFC 5915
437    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    /// Serialize the private key as RFC5915 format in PEM encoding
444    pub fn serialize_rfc5915_pem(&self) -> String {
445        pem_encode(&self.serialize_rfc5915_der(), PEM_HEADER_RFC5915)
446    }
447
448    /// Serialize the private key to a simple bytestring
449    ///
450    /// This uses the SEC1 encoding, which is just the representation
451    /// of the secret integer in a 32-byte array, encoding it using
452    /// big-endian notation.
453    pub fn serialize_sec1(&self) -> Vec<u8> {
454        self.key.to_bytes().to_vec()
455    }
456
457    /// Serialize the private key as PKCS8 format in DER encoding
458    pub fn serialize_pkcs8_der(&self) -> Vec<u8> {
459        der_encode_pkcs8_rfc5208_private_key(&self.serialize_sec1())
460    }
461
462    /// Serialize the private key as PKCS8 format in PEM encoding
463    pub fn serialize_pkcs8_pem(&self) -> String {
464        pem_encode(&self.serialize_pkcs8_der(), PEM_HEADER_PKCS8)
465    }
466
467    /// Sign a message
468    ///
469    /// The message is hashed with SHA-256
470    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    /// Sign a message, using a DER encoded signature
477    ///
478    /// The message is hashed with SHA-256
479    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    /// Sign a message digest
486    pub fn sign_digest(&self, digest: &[u8]) -> Option<[u8; 64]> {
487        if digest.len() < 16 {
488            // p256 arbitrarily rejects digests that are < 128 bits
489            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    /// Return the public key corresponding to this private key
501    pub fn public_key(&self) -> PublicKey {
502        let key = self.key.verifying_key();
503        PublicKey { key: *key }
504    }
505
506    /// Derive a private key from this private key using a derivation path
507    ///
508    /// As long as each index of the derivation path is a 4-byte input with the highest
509    /// bit cleared, this derivation scheme matches SLIP-10
510    ///
511    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    /// Derive a private key from this private key using a derivation path
517    /// and chain code
518    ///
519    /// As long as each index of the derivation path is a 4-byte input with the highest
520    /// bit cleared, this derivation scheme matches SLIP-10
521    ///
522    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/// An ECDSA public key
547#[derive(Clone, Eq, PartialEq, Debug)]
548pub struct PublicKey {
549    key: p256::ecdsa::VerifyingKey,
550}
551
552impl PublicKey {
553    /// Deserialize a public key stored in SEC1 format
554    ///
555    /// This is just the encoding of the point. Both compressed and uncompressed
556    /// points are accepted
557    ///
558    /// See SEC1 <https://www.secg.org/sec1-v2.pdf> section 2.3.3 for details of the format
559    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    /// Deserialize a public key from (x,y) coordinates
566    ///
567    /// The x and y values must be exactly equal to the field length
568    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    /// Deserialize a public key stored in DER SubjectPublicKeyInfo format
586    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    /// Deserialize a public key stored in DER SubjectPublicKeyInfo format
594    ///
595    /// The public key must be in uncompressed format. The originally provided
596    /// input is compared with the re-encoded DER to prevent using non-canonical
597    /// encodings that might be accepted otherwise
598    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    /// Deserialize a public key stored in PEM SubjectPublicKeyInfo format
611    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    /// Serialize a public key in SEC1 format
622    ///
623    /// The point can optionally be compressed
624    ///
625    /// See SEC1 <https://www.secg.org/sec1-v2.pdf> section 2.3.3 for details of the format
626    pub fn serialize_sec1(&self, compressed: bool) -> Vec<u8> {
627        self.key.to_encoded_point(compressed).to_bytes().to_vec()
628    }
629
630    /// Serialize a public key in DER as a SubjectPublicKeyInfo
631    pub fn serialize_der(&self) -> Vec<u8> {
632        der_encode_ecdsa_spki_pubkey(&self.serialize_sec1(false))
633    }
634
635    /// Serialize a public key in PEM encoding of a SubjectPublicKeyInfo
636    pub fn serialize_pem(&self) -> String {
637        pem_encode(&self.serialize_der(), "PUBLIC KEY")
638    }
639
640    /// Verify a (message,signature) pair
641    ///
642    /// Be aware that this verification does not ensure non-malleability
643    ///
644    /// Some usages of ECDSA rely on non-malleability properties of ECDSA.  This
645    /// particularly arises in the context of crypto currencies of various
646    /// types. ECDSA signatures are usually malleable, in that if (r,s) is a
647    /// valid signature, then (r,-s) is also valid. To avoid this malleability,
648    /// some systems require that s be "normalized" to the smallest value.
649    ///
650    /// This normalization is quite common on secp256k1, but is virtually
651    /// unknown and unimplemented for secp256r1. The vast majority of secp256r1
652    /// signatures will not be normalized. Thus this verification *does not*
653    /// ensure any non-malleability properties.
654    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    /// Verify a (message,signature) pair
665    ///
666    /// This is a variant of verify_signature which requires that the signature
667    /// be in the DER encoded form which is used by certain protocols
668    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    /// Verify a (message digest,signature) pair
679    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    /// Derive a public key from this public key using a derivation path
690    ///
691    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    /// Derive a public key from this public key using a derivation path
697    /// and chain code
698    ///
699    /// This derivation matches SLIP-10
700    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}