oasis_runtime_sdk/crypto/signature/
secp384r1.rs

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