1pub mod evm;
8
9use std::{
10 borrow::Cow,
11 fmt,
12 hash::{Hash, Hasher},
13 str::FromStr,
14};
15
16use k256::{
17 ecdsa::{Signature, SigningKey, VerifyingKey},
18 elliptic_curve::sec1::FromEncodedPoint,
19 EncodedPoint,
20};
21use linera_witty::{
22 GuestPointer, HList, InstanceWithMemory, Layout, Memory, Runtime, RuntimeError, RuntimeMemory,
23 WitLoad, WitStore, WitType,
24};
25use serde::{Deserialize, Serialize};
26
27use super::{BcsHashable, BcsSignable, CryptoError, CryptoHash, HasTypeName};
28use crate::doc_scalar;
29
30const SECP256K1_SCHEME_LABEL: &str = "secp256k1";
32
33const SECP256K1_PUBLIC_KEY_SIZE: usize = 33;
35
36const SECP256K1_SIGNATURE_SIZE: usize = 64;
38
39#[derive(Eq, PartialEq)]
41pub struct Secp256k1SecretKey(pub SigningKey);
42
43#[derive(Eq, PartialEq, Ord, PartialOrd, Copy, Clone)]
45pub struct Secp256k1PublicKey(pub VerifyingKey);
46
47impl Hash for Secp256k1PublicKey {
48 fn hash<H: Hasher>(&self, state: &mut H) {
49 self.0.to_encoded_point(true).as_bytes().hash(state);
50 }
51}
52
53#[derive(Debug, PartialEq, Eq)]
55pub struct Secp256k1KeyPair {
56 pub secret_key: Secp256k1SecretKey,
58 pub public_key: Secp256k1PublicKey,
60}
61
62#[derive(Eq, PartialEq, Copy, Clone)]
64pub struct Secp256k1Signature(pub Signature);
65
66impl Secp256k1PublicKey {
67 #[cfg(all(with_testing, not(target_arch = "wasm32")))]
69 pub fn test_key(seed: u8) -> Self {
70 use rand::SeedableRng;
71 let mut rng = rand::rngs::StdRng::seed_from_u64(seed as u64);
72 let sk = k256::SecretKey::random(&mut rng);
73 Self(sk.public_key().into())
74 }
75
76 pub fn as_bytes(&self) -> [u8; SECP256K1_PUBLIC_KEY_SIZE] {
78 self.0.to_encoded_point(true).as_bytes().try_into().unwrap()
80 }
81
82 pub fn from_bytes(bytes: &[u8]) -> Result<Self, CryptoError> {
87 let encoded_point =
88 EncodedPoint::from_bytes(bytes).map_err(|_| CryptoError::IncorrectPublicKeySize {
89 scheme: SECP256K1_SCHEME_LABEL,
90 len: bytes.len(),
91 expected: SECP256K1_PUBLIC_KEY_SIZE,
92 })?;
93
94 match k256::PublicKey::from_encoded_point(&encoded_point).into_option() {
95 Some(public_key) => Ok(Self(public_key.into())),
96 None => {
97 let error = CryptoError::Secp256k1PointAtInfinity(hex::encode(bytes));
98 Err(error)
99 }
100 }
101 }
102}
103
104impl fmt::Debug for Secp256k1SecretKey {
105 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
106 write!(f, "<redacted for Secp256k1 secret key>")
107 }
108}
109
110impl Serialize for Secp256k1SecretKey {
111 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
112 where
113 S: serde::ser::Serializer,
114 {
115 assert!(serializer.is_human_readable());
117 serializer.serialize_str(&hex::encode(self.0.to_bytes()))
118 }
119}
120
121impl<'de> Deserialize<'de> for Secp256k1SecretKey {
122 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
123 where
124 D: serde::de::Deserializer<'de>,
125 {
126 assert!(deserializer.is_human_readable());
128 let str = String::deserialize(deserializer)?;
129 let bytes = hex::decode(&str).map_err(serde::de::Error::custom)?;
130 let sk = k256::ecdsa::SigningKey::from_slice(&bytes).map_err(serde::de::Error::custom)?;
131 Ok(Secp256k1SecretKey(sk))
132 }
133}
134
135impl Serialize for Secp256k1PublicKey {
136 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
137 where
138 S: serde::ser::Serializer,
139 {
140 if serializer.is_human_readable() {
141 serializer.serialize_str(&hex::encode(self.as_bytes()))
142 } else {
143 let compact_pk = serde_utils::CompressedPublicKey(self.as_bytes());
144 serializer.serialize_newtype_struct("Secp256k1PublicKey", &compact_pk)
145 }
146 }
147}
148
149impl<'de> Deserialize<'de> for Secp256k1PublicKey {
150 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
151 where
152 D: serde::de::Deserializer<'de>,
153 {
154 if deserializer.is_human_readable() {
155 let s = String::deserialize(deserializer)?;
156 let value = hex::decode(s).map_err(serde::de::Error::custom)?;
157 Ok(Secp256k1PublicKey::from_bytes(&value).map_err(serde::de::Error::custom)?)
158 } else {
159 #[derive(Deserialize)]
160 #[serde(rename = "Secp256k1PublicKey")]
161 struct PublicKey(serde_utils::CompressedPublicKey);
162 let compact = PublicKey::deserialize(deserializer)?;
163 Ok(Secp256k1PublicKey::from_bytes(&compact.0 .0).map_err(serde::de::Error::custom)?)
164 }
165 }
166}
167
168impl FromStr for Secp256k1PublicKey {
169 type Err = CryptoError;
170
171 fn from_str(s: &str) -> Result<Self, Self::Err> {
172 hex::decode(s)?.as_slice().try_into()
173 }
174}
175
176impl TryFrom<&[u8]> for Secp256k1PublicKey {
177 type Error = CryptoError;
178
179 fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
180 Self::from_bytes(value)
181 }
182}
183
184impl fmt::Display for Secp256k1PublicKey {
185 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
186 let str = hex::encode(self.as_bytes());
187 write!(f, "{}", str)
188 }
189}
190
191impl fmt::Debug for Secp256k1PublicKey {
192 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
193 write!(f, "{}..", hex::encode(&self.as_bytes()[0..9]))
194 }
195}
196
197impl BcsHashable<'_> for Secp256k1PublicKey {}
198
199impl WitType for Secp256k1PublicKey {
200 const SIZE: u32 = <(u64, u64, u64, u64, u8) as WitType>::SIZE;
201 type Layout = <(u64, u64, u64, u64, u8) as WitType>::Layout;
202 type Dependencies = HList![];
203
204 fn wit_type_name() -> Cow<'static, str> {
205 "secp256k1-public-key".into()
206 }
207
208 fn wit_type_declaration() -> Cow<'static, str> {
209 concat!(
210 " record secp256k1-public-key {\n",
211 " part1: u64,\n",
212 " part2: u64,\n",
213 " part3: u64,\n",
214 " part4: u64,\n",
215 " part5: u8\n",
216 " }\n",
217 )
218 .into()
219 }
220}
221
222impl WitLoad for Secp256k1PublicKey {
223 fn load<Instance>(
224 memory: &Memory<'_, Instance>,
225 location: GuestPointer,
226 ) -> Result<Self, RuntimeError>
227 where
228 Instance: InstanceWithMemory,
229 <Instance::Runtime as Runtime>::Memory: RuntimeMemory<Instance>,
230 {
231 let (part1, part2, part3, part4, part5) = WitLoad::load(memory, location)?;
232 Ok(Self::from((part1, part2, part3, part4, part5)))
233 }
234
235 fn lift_from<Instance>(
236 flat_layout: <Self::Layout as Layout>::Flat,
237 memory: &Memory<'_, Instance>,
238 ) -> Result<Self, RuntimeError>
239 where
240 Instance: InstanceWithMemory,
241 <Instance::Runtime as Runtime>::Memory: RuntimeMemory<Instance>,
242 {
243 let (part1, part2, part3, part4, part5) = WitLoad::lift_from(flat_layout, memory)?;
244 Ok(Self::from((part1, part2, part3, part4, part5)))
245 }
246}
247
248impl WitStore for Secp256k1PublicKey {
249 fn store<Instance>(
250 &self,
251 memory: &mut Memory<'_, Instance>,
252 location: GuestPointer,
253 ) -> Result<(), RuntimeError>
254 where
255 Instance: InstanceWithMemory,
256 <Instance::Runtime as Runtime>::Memory: RuntimeMemory<Instance>,
257 {
258 let (part1, part2, part3, part4, part5) = (*self).into();
259 (part1, part2, part3, part4, part5).store(memory, location)
260 }
261
262 fn lower<Instance>(
263 &self,
264 memory: &mut Memory<'_, Instance>,
265 ) -> Result<<Self::Layout as Layout>::Flat, RuntimeError>
266 where
267 Instance: InstanceWithMemory,
268 <Instance::Runtime as Runtime>::Memory: RuntimeMemory<Instance>,
269 {
270 let (part1, part2, part3, part4, part5) = (*self).into();
271 (part1, part2, part3, part4, part5).lower(memory)
272 }
273}
274
275impl From<(u64, u64, u64, u64, u8)> for Secp256k1PublicKey {
276 fn from((part1, part2, part3, part4, part5): (u64, u64, u64, u64, u8)) -> Self {
277 let mut bytes = [0u8; SECP256K1_PUBLIC_KEY_SIZE];
278 bytes[0..8].copy_from_slice(&part1.to_be_bytes());
279 bytes[8..16].copy_from_slice(&part2.to_be_bytes());
280 bytes[16..24].copy_from_slice(&part3.to_be_bytes());
281 bytes[24..32].copy_from_slice(&part4.to_be_bytes());
282 bytes[32] = part5;
283 Self::from_bytes(&bytes).unwrap()
284 }
285}
286
287impl From<Secp256k1PublicKey> for (u64, u64, u64, u64, u8) {
288 fn from(key: Secp256k1PublicKey) -> Self {
289 let bytes = key.as_bytes();
290 let part1 = u64::from_be_bytes(bytes[0..8].try_into().unwrap());
291 let part2 = u64::from_be_bytes(bytes[8..16].try_into().unwrap());
292 let part3 = u64::from_be_bytes(bytes[16..24].try_into().unwrap());
293 let part4 = u64::from_be_bytes(bytes[24..32].try_into().unwrap());
294 let part5 = bytes[32];
295 (part1, part2, part3, part4, part5)
296 }
297}
298
299impl Secp256k1KeyPair {
300 #[cfg(all(with_getrandom, with_testing))]
302 pub fn generate() -> Self {
303 let mut rng = rand::rngs::OsRng;
304 Self::generate_from(&mut rng)
305 }
306
307 #[cfg(with_getrandom)]
309 pub fn generate_from<R: super::CryptoRng>(rng: &mut R) -> Self {
310 let secret_key = Secp256k1SecretKey(SigningKey::random(rng));
311 let public_key = secret_key.public();
312 Secp256k1KeyPair {
313 secret_key,
314 public_key,
315 }
316 }
317}
318
319impl Secp256k1SecretKey {
320 pub fn public(&self) -> Secp256k1PublicKey {
322 Secp256k1PublicKey(*self.0.verifying_key())
323 }
324
325 pub fn copy(&self) -> Self {
330 Self(self.0.clone())
331 }
332
333 #[cfg(all(with_getrandom, with_testing))]
335 pub fn generate() -> Self {
336 let mut rng = rand::rngs::OsRng;
337 Self::generate_from(&mut rng)
338 }
339
340 #[cfg(with_getrandom)]
342 pub fn generate_from<R: super::CryptoRng>(rng: &mut R) -> Self {
343 Secp256k1SecretKey(SigningKey::random(rng))
344 }
345}
346
347impl Secp256k1Signature {
348 pub fn new<'de, T>(value: &T, secret: &Secp256k1SecretKey) -> Self
351 where
352 T: BcsSignable<'de>,
353 {
354 use k256::ecdsa::signature::hazmat::PrehashSigner;
355
356 let prehash = CryptoHash::new(value).as_bytes().0;
357 let (signature, _rid) = secret
358 .0
359 .sign_prehash(&prehash)
360 .expect("Failed to sign prehashed data"); Secp256k1Signature(signature)
362 }
363
364 pub fn check<'de, T>(&self, value: &T, author: &Secp256k1PublicKey) -> Result<(), CryptoError>
366 where
367 T: BcsSignable<'de> + fmt::Debug,
368 {
369 let prehash = CryptoHash::new(value).as_bytes().0;
370 self.verify_inner::<T>(prehash, author)
371 }
372
373 pub fn verify_batch<'a, 'de, T, I>(value: &'a T, votes: I) -> Result<(), CryptoError>
377 where
378 T: BcsSignable<'de> + fmt::Debug,
379 I: IntoIterator<Item = &'a (Secp256k1PublicKey, Secp256k1Signature)>,
380 {
381 let prehash = CryptoHash::new(value).as_bytes().0;
382 for (author, signature) in votes {
383 signature.verify_inner::<T>(prehash, author)?;
384 }
385 Ok(())
386 }
387
388 pub fn as_bytes(&self) -> [u8; SECP256K1_SIGNATURE_SIZE] {
390 self.0.to_bytes().into()
391 }
392
393 fn verify_inner<'de, T>(
394 &self,
395 prehash: [u8; 32],
396 author: &Secp256k1PublicKey,
397 ) -> Result<(), CryptoError>
398 where
399 T: BcsSignable<'de> + fmt::Debug,
400 {
401 use k256::ecdsa::signature::hazmat::PrehashVerifier;
402
403 author
404 .0
405 .verify_prehash(&prehash, &self.0)
406 .map_err(|error| CryptoError::InvalidSignature {
407 error: error.to_string(),
408 type_name: T::type_name().to_string(),
409 })
410 }
411
412 pub fn from_slice<A: AsRef<[u8]>>(bytes: A) -> Result<Self, CryptoError> {
415 let sig = k256::ecdsa::Signature::from_slice(bytes.as_ref())
416 .map_err(CryptoError::Secp256k1Error)?;
417 Ok(Secp256k1Signature(sig))
418 }
419}
420
421impl Serialize for Secp256k1Signature {
422 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
423 where
424 S: serde::ser::Serializer,
425 {
426 if serializer.is_human_readable() {
427 serializer.serialize_str(&hex::encode(self.as_bytes()))
428 } else {
429 let compact = serde_utils::CompactSignature(self.as_bytes());
430 serializer.serialize_newtype_struct("Secp256k1Signature", &compact)
431 }
432 }
433}
434
435impl<'de> Deserialize<'de> for Secp256k1Signature {
436 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
437 where
438 D: serde::de::Deserializer<'de>,
439 {
440 if deserializer.is_human_readable() {
441 let s = String::deserialize(deserializer)?;
442 let value = hex::decode(s).map_err(serde::de::Error::custom)?;
443 Self::from_slice(&value).map_err(serde::de::Error::custom)
444 } else {
445 #[derive(Deserialize)]
446 #[serde(rename = "Secp256k1Signature")]
447 struct Signature(serde_utils::CompactSignature);
448
449 let value = Signature::deserialize(deserializer)?;
450 Self::from_slice(value.0 .0.as_ref()).map_err(serde::de::Error::custom)
451 }
452 }
453}
454
455impl fmt::Display for Secp256k1Signature {
456 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
457 let s = hex::encode(self.as_bytes());
458 write!(f, "{}", s)
459 }
460}
461
462impl fmt::Debug for Secp256k1Signature {
463 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
464 write!(f, "{}..", hex::encode(&self.as_bytes()[0..9]))
465 }
466}
467
468doc_scalar!(Secp256k1Signature, "A secp256k1 signature value");
469doc_scalar!(Secp256k1PublicKey, "A secp256k1 public key value");
470
471mod serde_utils {
472 use serde::{Deserialize, Serialize};
473 use serde_with::serde_as;
474
475 use super::{SECP256K1_PUBLIC_KEY_SIZE, SECP256K1_SIGNATURE_SIZE};
476
477 #[serde_as]
482 #[derive(Serialize, Deserialize)]
483 #[serde(transparent)]
484 pub struct CompactSignature(#[serde_as(as = "[_; 64]")] pub [u8; SECP256K1_SIGNATURE_SIZE]);
485
486 #[serde_as]
487 #[derive(Serialize, Deserialize)]
488 #[serde(transparent)]
489 pub struct CompressedPublicKey(#[serde_as(as = "[_; 33]")] pub [u8; SECP256K1_PUBLIC_KEY_SIZE]);
490}
491
492#[cfg(with_testing)]
493mod tests {
494 #[test]
495 fn test_signatures() {
496 use serde::{Deserialize, Serialize};
497
498 use crate::crypto::{
499 secp256k1::{Secp256k1KeyPair, Secp256k1Signature},
500 BcsSignable, TestString,
501 };
502
503 #[derive(Debug, Serialize, Deserialize)]
504 struct Foo(String);
505
506 impl BcsSignable<'_> for Foo {}
507
508 let keypair1 = Secp256k1KeyPair::generate();
509 let keypair2 = Secp256k1KeyPair::generate();
510
511 let ts = TestString("hello".into());
512 let tsx = TestString("hellox".into());
513 let foo = Foo("hello".into());
514
515 let s = Secp256k1Signature::new(&ts, &keypair1.secret_key);
516 assert!(s.check(&ts, &keypair1.public_key).is_ok());
517 assert!(s.check(&ts, &keypair2.public_key).is_err());
518 assert!(s.check(&tsx, &keypair1.public_key).is_err());
519 assert!(s.check(&foo, &keypair1.public_key).is_err());
520 }
521
522 #[test]
523 fn test_public_key_serialization() {
524 use crate::crypto::secp256k1::Secp256k1PublicKey;
525 let key_in = Secp256k1PublicKey::test_key(0);
526 let s = serde_json::to_string(&key_in).unwrap();
527 let key_out: Secp256k1PublicKey = serde_json::from_str(&s).unwrap();
528 assert_eq!(key_out, key_in);
529
530 let s = bcs::to_bytes(&key_in).unwrap();
531 let key_out: Secp256k1PublicKey = bcs::from_bytes(&s).unwrap();
532 assert_eq!(key_out, key_in);
533 }
534
535 #[test]
536 fn test_secret_key_serialization() {
537 use crate::crypto::secp256k1::{Secp256k1KeyPair, Secp256k1SecretKey};
538 let key_in = Secp256k1KeyPair::generate().secret_key;
539 let s = serde_json::to_string(&key_in).unwrap();
540 let key_out: Secp256k1SecretKey = serde_json::from_str(&s).unwrap();
541 assert_eq!(key_out, key_in);
542 }
543
544 #[test]
545 fn test_signature_serialization() {
546 use crate::crypto::{
547 secp256k1::{Secp256k1KeyPair, Secp256k1Signature},
548 TestString,
549 };
550 let keypair = Secp256k1KeyPair::generate();
551 let sig = Secp256k1Signature::new(&TestString("hello".into()), &keypair.secret_key);
552 let s = serde_json::to_string(&sig).unwrap();
553 let sig2: Secp256k1Signature = serde_json::from_str(&s).unwrap();
554 assert_eq!(sig, sig2);
555
556 let s = bcs::to_bytes(&sig).unwrap();
557 let sig2: Secp256k1Signature = bcs::from_bytes(&s).unwrap();
558 assert_eq!(sig, sig2);
559 }
560
561 #[test]
562 fn public_key_from_str() {
563 use std::str::FromStr;
564
565 use crate::crypto::secp256k1::Secp256k1PublicKey;
566 let key = Secp256k1PublicKey::test_key(0);
567 let s = key.to_string();
568 let key2 = Secp256k1PublicKey::from_str(s.as_str()).unwrap();
569 assert_eq!(key, key2);
570 }
571
572 #[test]
573 fn bytes_repr_compact_public_key() {
574 use crate::crypto::secp256k1::{Secp256k1PublicKey, SECP256K1_PUBLIC_KEY_SIZE};
575 let key_in: Secp256k1PublicKey = Secp256k1PublicKey::test_key(0);
576 let bytes = key_in.as_bytes();
577 assert!(
578 bytes.len() == SECP256K1_PUBLIC_KEY_SIZE,
579 "::to_bytes() should return compressed representation"
580 );
581 let key_out = Secp256k1PublicKey::from_bytes(&bytes).unwrap();
582 assert_eq!(key_in, key_out);
583 }
584
585 #[test]
586 fn human_readable_ser() {
587 use crate::crypto::{
588 secp256k1::{Secp256k1KeyPair, Secp256k1Signature},
589 TestString,
590 };
591 let key_pair = Secp256k1KeyPair::generate();
592 let sig = Secp256k1Signature::new(&TestString("hello".into()), &key_pair.secret_key);
593 let s = serde_json::to_string(&sig).unwrap();
594 let sig2: Secp256k1Signature = serde_json::from_str(&s).unwrap();
595 assert_eq!(sig, sig2);
596 }
597}