oasis_runtime_sdk/crypto/signature/
secp256r1.rs

1//! Secp256r1 signatures.
2use base64::prelude::*;
3use digest::{consts::U32, core_api::BlockSizeUser, Digest, FixedOutput, FixedOutputReset};
4use k256::sha2::Sha512_256;
5use p256::{
6    self,
7    ecdsa::{
8        self,
9        signature::{DigestSigner as _, DigestVerifier, Signer as _, Verifier as _},
10    },
11};
12use rand_core::{CryptoRng, RngCore};
13
14use crate::crypto::signature::{Error, Signature};
15
16/// A Secp256r1 public key (in compressed form).
17#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
18pub struct PublicKey(p256::EncodedPoint);
19
20impl PublicKey {
21    /// Return a byte representation of this public key.
22    pub fn as_bytes(&self) -> &[u8] {
23        self.0.as_bytes()
24    }
25
26    /// Construct a public key from a slice of bytes.
27    pub fn from_bytes(bytes: &[u8]) -> Result<Self, Error> {
28        p256::EncodedPoint::from_bytes(bytes)
29            .map_err(|_| Error::MalformedPublicKey)
30            .map(PublicKey)
31    }
32
33    /// Verify a signature.
34    pub fn verify(
35        &self,
36        context: &[u8],
37        message: &[u8],
38        signature: &Signature,
39    ) -> Result<(), Error> {
40        let digest = Sha512_256::new()
41            .chain_update(context)
42            .chain_update(message);
43        self.verify_digest(digest, signature)
44    }
45
46    /// Verify signature without using any domain separation scheme.
47    pub fn verify_raw(&self, message: &[u8], signature: &Signature) -> Result<(), Error> {
48        let sig = ecdsa::Signature::from_der(signature.0.as_ref())
49            .map_err(|_| Error::MalformedSignature)?;
50        let verify_key = ecdsa::VerifyingKey::from_encoded_point(&self.0)
51            .map_err(|_| Error::MalformedPublicKey)?;
52        verify_key
53            .verify(message, &sig)
54            .map_err(|_| Error::VerificationFailed)
55    }
56
57    /// Verify signature of a pre-hashed message.
58    pub fn verify_digest<D>(&self, digest: D, signature: &Signature) -> Result<(), Error>
59    where
60        D: Digest + FixedOutput<OutputSize = U32>,
61    {
62        let sig = ecdsa::Signature::from_der(signature.as_ref())
63            .map_err(|_| Error::MalformedSignature)?;
64        let verify_key = ecdsa::VerifyingKey::from_encoded_point(&self.0)
65            .map_err(|_| Error::MalformedPublicKey)?;
66        verify_key
67            .verify_digest(digest, &sig)
68            .map_err(|_| Error::VerificationFailed)
69    }
70}
71
72impl From<&'static str> for PublicKey {
73    fn from(s: &'static str) -> PublicKey {
74        PublicKey::from_bytes(&BASE64_STANDARD.decode(s).unwrap()).unwrap()
75    }
76}
77
78impl cbor::Encode for PublicKey {
79    fn into_cbor_value(self) -> cbor::Value {
80        cbor::Value::ByteString(self.as_bytes().to_vec())
81    }
82}
83
84impl cbor::Decode for PublicKey {
85    fn try_from_cbor_value(value: cbor::Value) -> Result<Self, cbor::DecodeError> {
86        match value {
87            cbor::Value::ByteString(data) => {
88                Self::from_bytes(&data).map_err(|_| cbor::DecodeError::UnexpectedType)
89            }
90            _ => Err(cbor::DecodeError::UnexpectedType),
91        }
92    }
93}
94
95/// A memory-backed signer for Secp256r1.
96pub struct MemorySigner {
97    sk: ecdsa::SigningKey,
98}
99
100impl MemorySigner {
101    pub fn sign_digest<D>(&self, digest: D) -> Result<Signature, Error>
102    where
103        D: Digest + FixedOutput<OutputSize = U32> + BlockSizeUser + FixedOutputReset,
104    {
105        let signature: ecdsa::Signature = self.sk.sign_digest(digest);
106        Ok(signature.to_der().as_bytes().to_vec().into())
107    }
108}
109
110impl super::Signer for MemorySigner {
111    fn random(rng: &mut (impl RngCore + CryptoRng)) -> Result<Self, Error> {
112        let mut seed = [0u8; 32];
113        rng.fill_bytes(&mut seed);
114        Self::new_from_seed(&seed)
115    }
116
117    fn new_from_seed(seed: &[u8]) -> Result<Self, Error> {
118        let sk = ecdsa::SigningKey::from_slice(seed).map_err(|_| Error::InvalidArgument)?;
119        Ok(Self { sk })
120    }
121
122    fn from_bytes(bytes: &[u8]) -> Result<Self, Error> {
123        Ok(Self {
124            sk: ecdsa::SigningKey::from_slice(bytes).map_err(|_| Error::MalformedPrivateKey)?,
125        })
126    }
127
128    fn to_bytes(&self) -> Vec<u8> {
129        self.sk.to_bytes().to_vec()
130    }
131
132    fn public_key(&self) -> super::PublicKey {
133        super::PublicKey::Secp256r1(PublicKey(self.sk.verifying_key().to_encoded_point(true)))
134    }
135
136    fn sign(&self, context: &[u8], message: &[u8]) -> Result<Signature, Error> {
137        let digest = sha2::Sha256::new()
138            .chain_update(context)
139            .chain_update(message);
140        let signature: ecdsa::Signature = self.sk.sign_digest(digest);
141        Ok(signature.to_der().as_bytes().to_vec().into())
142    }
143
144    fn sign_raw(&self, message: &[u8]) -> Result<Signature, Error> {
145        let signature: ecdsa::Signature = self.sk.sign(message);
146        Ok(signature.to_der().as_bytes().to_vec().into())
147    }
148}