oasis_runtime_sdk/crypto/signature/
secp384r1.rs1use 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#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
17pub struct PublicKey(p384::EncodedPoint);
18
19impl PublicKey {
20 pub fn as_bytes(&self) -> &[u8] {
22 self.0.as_bytes()
23 }
24
25 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 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 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 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
94pub 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}