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