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