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