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