oasis_runtime_sdk/crypto/signature/
secp384r1.rs1use base64::prelude::*;
3use digest::{common::BlockSizeUser, consts::U48, Digest, FixedOutput, FixedOutputReset};
4use p384::{
5 self,
6 ecdsa::{
7 self,
8 signature::{
9 hazmat::{PrehashSigner, PrehashVerifier},
10 Signer as _, Verifier as _,
11 },
12 },
13};
14use rand::TryCryptoRng;
15
16use crate::crypto::signature::{Error, Signature};
17
18#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
20pub struct PublicKey(p384::Sec1Point);
21
22impl PublicKey {
23 pub fn as_bytes(&self) -> &[u8] {
25 self.0.as_bytes()
26 }
27
28 pub fn from_bytes(bytes: &[u8]) -> Result<Self, Error> {
30 p384::Sec1Point::from_bytes(bytes)
31 .map_err(|_| Error::MalformedPublicKey)
32 .map(PublicKey)
33 }
34
35 pub fn verify(
37 &self,
38 context: &[u8],
39 message: &[u8],
40 signature: &Signature,
41 ) -> Result<(), Error> {
42 let digest = sha2::Sha384::new()
43 .chain_update(context)
44 .chain_update(message);
45 self.verify_digest(digest, signature)
46 }
47
48 pub fn verify_raw(&self, message: &[u8], signature: &Signature) -> Result<(), Error> {
50 let sig = ecdsa::Signature::from_der(signature.0.as_ref())
51 .map_err(|_| Error::MalformedSignature)?;
52 let verify_key =
53 ecdsa::VerifyingKey::from_sec1_point(&self.0).map_err(|_| Error::MalformedPublicKey)?;
54 verify_key
55 .verify(message, &sig)
56 .map_err(|_| Error::VerificationFailed)
57 }
58
59 pub fn verify_digest<D>(&self, digest: D, signature: &Signature) -> Result<(), Error>
61 where
62 D: Digest + FixedOutput<OutputSize = U48>,
63 {
64 let sig = ecdsa::Signature::from_der(signature.as_ref())
65 .map_err(|_| Error::MalformedSignature)?;
66 let verify_key =
67 ecdsa::VerifyingKey::from_sec1_point(&self.0).map_err(|_| Error::MalformedPublicKey)?;
68 let prehash = digest.finalize_fixed();
69 verify_key
70 .verify_prehash(&prehash, &sig)
71 .map_err(|_| Error::VerificationFailed)
72 }
73}
74
75impl From<&'static str> for PublicKey {
76 fn from(s: &'static str) -> PublicKey {
77 PublicKey::from_bytes(&BASE64_STANDARD.decode(s).unwrap()).unwrap()
78 }
79}
80
81impl cbor::Encode for PublicKey {
82 fn into_cbor_value(self) -> cbor::Value {
83 cbor::Value::ByteString(self.as_bytes().to_vec())
84 }
85}
86
87impl cbor::Decode for PublicKey {
88 fn try_from_cbor_value(value: cbor::Value) -> Result<Self, cbor::DecodeError> {
89 match value {
90 cbor::Value::ByteString(data) => {
91 Self::from_bytes(&data).map_err(|_| cbor::DecodeError::UnexpectedType)
92 }
93 _ => Err(cbor::DecodeError::UnexpectedType),
94 }
95 }
96}
97
98pub struct MemorySigner {
100 sk: ecdsa::SigningKey,
101}
102
103impl MemorySigner {
104 pub fn sign_digest<D>(&self, digest: D) -> Result<Signature, Error>
105 where
106 D: Digest + FixedOutput<OutputSize = U48> + BlockSizeUser + FixedOutputReset,
107 {
108 let prehash = digest.finalize_fixed();
109 let signature: ecdsa::Signature = self
110 .sk
111 .sign_prehash(&prehash)
112 .map_err(|_| Error::SigningError)?;
113 Ok(signature.to_der().as_bytes().to_vec().into())
114 }
115}
116
117impl super::Signer for MemorySigner {
118 fn random(rng: &mut impl TryCryptoRng) -> Result<Self, Error> {
119 let mut seed = [0u8; 48];
120 rng.try_fill_bytes(&mut seed).map_err(|_| Error::RngError)?;
121 Self::new_from_seed(&seed)
122 }
123
124 fn new_from_seed(seed: &[u8]) -> Result<Self, Error> {
125 let sk = ecdsa::SigningKey::from_slice(seed).map_err(|_| Error::InvalidArgument)?;
126 Ok(Self { sk })
127 }
128
129 fn from_bytes(bytes: &[u8]) -> Result<Self, Error> {
130 Ok(Self {
131 sk: ecdsa::SigningKey::from_slice(bytes).map_err(|_| Error::MalformedPrivateKey)?,
132 })
133 }
134
135 fn to_bytes(&self) -> Vec<u8> {
136 self.sk.to_bytes().to_vec()
137 }
138
139 fn public_key(&self) -> super::PublicKey {
140 super::PublicKey::Secp384r1(PublicKey(self.sk.verifying_key().to_sec1_point(true)))
141 }
142
143 fn sign(&self, context: &[u8], message: &[u8]) -> Result<Signature, Error> {
144 let digest = sha2::Sha384::new()
145 .chain_update(context)
146 .chain_update(message);
147 let prehash = digest.finalize_fixed();
148 let signature: ecdsa::Signature = self
149 .sk
150 .sign_prehash(&prehash)
151 .map_err(|_| Error::SigningError)?;
152 Ok(signature.to_der().as_bytes().to_vec().into())
153 }
154
155 fn sign_raw(&self, message: &[u8]) -> Result<Signature, Error> {
156 let signature: ecdsa::Signature = self.sk.sign(message);
157 Ok(signature.to_der().as_bytes().to_vec().into())
158 }
159}