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 Self::sign_prehash(secret, CryptoHash::new(value))
355 }
356
357 pub fn sign_prehash(secret: &Secp256k1SecretKey, prehash: CryptoHash) -> Self {
359 use k256::ecdsa::signature::hazmat::PrehashSigner;
360
361 let (signature, _rid) = secret
362 .0
363 .sign_prehash(&prehash.as_bytes().0)
364 .expect("Failed to sign prehashed data"); Secp256k1Signature(signature)
366 }
367
368 pub fn check<'de, T>(&self, value: &T, author: &Secp256k1PublicKey) -> Result<(), CryptoError>
370 where
371 T: BcsSignable<'de> + fmt::Debug,
372 {
373 let prehash = CryptoHash::new(value).as_bytes().0;
374 self.verify_inner::<T>(prehash, author)
375 }
376
377 pub fn verify_batch<'a, 'de, T, I>(value: &'a T, votes: I) -> Result<(), CryptoError>
381 where
382 T: BcsSignable<'de> + fmt::Debug,
383 I: IntoIterator<Item = &'a (Secp256k1PublicKey, Secp256k1Signature)>,
384 {
385 let prehash = CryptoHash::new(value).as_bytes().0;
386 for (author, signature) in votes {
387 signature.verify_inner::<T>(prehash, author)?;
388 }
389 Ok(())
390 }
391
392 pub fn as_bytes(&self) -> [u8; SECP256K1_SIGNATURE_SIZE] {
394 self.0.to_bytes().into()
395 }
396
397 fn verify_inner<'de, T>(
398 &self,
399 prehash: [u8; 32],
400 author: &Secp256k1PublicKey,
401 ) -> Result<(), CryptoError>
402 where
403 T: BcsSignable<'de> + fmt::Debug,
404 {
405 use k256::ecdsa::signature::hazmat::PrehashVerifier;
406
407 author
408 .0
409 .verify_prehash(&prehash, &self.0)
410 .map_err(|error| CryptoError::InvalidSignature {
411 error: error.to_string(),
412 type_name: T::type_name().to_string(),
413 })
414 }
415
416 pub fn from_slice<A: AsRef<[u8]>>(bytes: A) -> Result<Self, CryptoError> {
419 let sig = k256::ecdsa::Signature::from_slice(bytes.as_ref())
420 .map_err(CryptoError::Secp256k1Error)?;
421 Ok(Secp256k1Signature(sig))
422 }
423}
424
425impl Serialize for Secp256k1Signature {
426 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
427 where
428 S: serde::ser::Serializer,
429 {
430 if serializer.is_human_readable() {
431 serializer.serialize_str(&hex::encode(self.as_bytes()))
432 } else {
433 let compact = serde_utils::CompactSignature(self.as_bytes());
434 serializer.serialize_newtype_struct("Secp256k1Signature", &compact)
435 }
436 }
437}
438
439impl<'de> Deserialize<'de> for Secp256k1Signature {
440 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
441 where
442 D: serde::de::Deserializer<'de>,
443 {
444 if deserializer.is_human_readable() {
445 let s = String::deserialize(deserializer)?;
446 let value = hex::decode(s).map_err(serde::de::Error::custom)?;
447 Self::from_slice(&value).map_err(serde::de::Error::custom)
448 } else {
449 #[derive(Deserialize)]
450 #[serde(rename = "Secp256k1Signature")]
451 struct Signature(serde_utils::CompactSignature);
452
453 let value = Signature::deserialize(deserializer)?;
454 Self::from_slice(value.0 .0.as_ref()).map_err(serde::de::Error::custom)
455 }
456 }
457}
458
459impl fmt::Display for Secp256k1Signature {
460 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
461 let s = hex::encode(self.as_bytes());
462 write!(f, "{}", s)
463 }
464}
465
466impl fmt::Debug for Secp256k1Signature {
467 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
468 write!(f, "{}..", hex::encode(&self.as_bytes()[0..9]))
469 }
470}
471
472doc_scalar!(Secp256k1Signature, "A secp256k1 signature value");
473doc_scalar!(Secp256k1PublicKey, "A secp256k1 public key value");
474
475mod serde_utils {
476 use serde::{Deserialize, Serialize};
477 use serde_with::serde_as;
478
479 use super::{SECP256K1_PUBLIC_KEY_SIZE, SECP256K1_SIGNATURE_SIZE};
480
481 #[serde_as]
486 #[derive(Serialize, Deserialize)]
487 #[serde(transparent)]
488 pub struct CompactSignature(#[serde_as(as = "[_; 64]")] pub [u8; SECP256K1_SIGNATURE_SIZE]);
489
490 #[serde_as]
491 #[derive(Serialize, Deserialize)]
492 #[serde(transparent)]
493 pub struct CompressedPublicKey(#[serde_as(as = "[_; 33]")] pub [u8; SECP256K1_PUBLIC_KEY_SIZE]);
494}
495
496#[cfg(with_testing)]
497mod tests {
498 #[test]
499 fn test_signatures() {
500 use serde::{Deserialize, Serialize};
501
502 use crate::crypto::{
503 secp256k1::{Secp256k1KeyPair, Secp256k1Signature},
504 BcsSignable, TestString,
505 };
506
507 #[derive(Debug, Serialize, Deserialize)]
508 struct Foo(String);
509
510 impl BcsSignable<'_> for Foo {}
511
512 let keypair1 = Secp256k1KeyPair::generate();
513 let keypair2 = Secp256k1KeyPair::generate();
514
515 let ts = TestString("hello".into());
516 let tsx = TestString("hellox".into());
517 let foo = Foo("hello".into());
518
519 let s = Secp256k1Signature::new(&ts, &keypair1.secret_key);
520 assert!(s.check(&ts, &keypair1.public_key).is_ok());
521 assert!(s.check(&ts, &keypair2.public_key).is_err());
522 assert!(s.check(&tsx, &keypair1.public_key).is_err());
523 assert!(s.check(&foo, &keypair1.public_key).is_err());
524 }
525
526 #[test]
527 fn test_public_key_serialization() {
528 use crate::crypto::secp256k1::Secp256k1PublicKey;
529 let key_in = Secp256k1PublicKey::test_key(0);
530 let s = serde_json::to_string(&key_in).unwrap();
531 let key_out: Secp256k1PublicKey = serde_json::from_str(&s).unwrap();
532 assert_eq!(key_out, key_in);
533
534 let s = bcs::to_bytes(&key_in).unwrap();
535 let key_out: Secp256k1PublicKey = bcs::from_bytes(&s).unwrap();
536 assert_eq!(key_out, key_in);
537 }
538
539 #[test]
540 fn test_secret_key_serialization() {
541 use crate::crypto::secp256k1::{Secp256k1KeyPair, Secp256k1SecretKey};
542 let key_in = Secp256k1KeyPair::generate().secret_key;
543 let s = serde_json::to_string(&key_in).unwrap();
544 let key_out: Secp256k1SecretKey = serde_json::from_str(&s).unwrap();
545 assert_eq!(key_out, key_in);
546 }
547
548 #[test]
549 fn test_signature_serialization() {
550 use crate::crypto::{
551 secp256k1::{Secp256k1KeyPair, Secp256k1Signature},
552 TestString,
553 };
554 let keypair = Secp256k1KeyPair::generate();
555 let sig = Secp256k1Signature::new(&TestString("hello".into()), &keypair.secret_key);
556 let s = serde_json::to_string(&sig).unwrap();
557 let sig2: Secp256k1Signature = serde_json::from_str(&s).unwrap();
558 assert_eq!(sig, sig2);
559
560 let s = bcs::to_bytes(&sig).unwrap();
561 let sig2: Secp256k1Signature = bcs::from_bytes(&s).unwrap();
562 assert_eq!(sig, sig2);
563 }
564
565 #[test]
566 fn public_key_from_str() {
567 use std::str::FromStr;
568
569 use crate::crypto::secp256k1::Secp256k1PublicKey;
570 let key = Secp256k1PublicKey::test_key(0);
571 let s = key.to_string();
572 let key2 = Secp256k1PublicKey::from_str(s.as_str()).unwrap();
573 assert_eq!(key, key2);
574 }
575
576 #[test]
577 fn bytes_repr_compact_public_key() {
578 use crate::crypto::secp256k1::{Secp256k1PublicKey, SECP256K1_PUBLIC_KEY_SIZE};
579 let key_in: Secp256k1PublicKey = Secp256k1PublicKey::test_key(0);
580 let bytes = key_in.as_bytes();
581 assert!(
582 bytes.len() == SECP256K1_PUBLIC_KEY_SIZE,
583 "::to_bytes() should return compressed representation"
584 );
585 let key_out = Secp256k1PublicKey::from_bytes(&bytes).unwrap();
586 assert_eq!(key_in, key_out);
587 }
588
589 #[test]
590 fn human_readable_ser() {
591 use crate::crypto::{
592 secp256k1::{Secp256k1KeyPair, Secp256k1Signature},
593 TestString,
594 };
595 let key_pair = Secp256k1KeyPair::generate();
596 let sig = Secp256k1Signature::new(&TestString("hello".into()), &key_pair.secret_key);
597 let s = serde_json::to_string(&sig).unwrap();
598 let sig2: Secp256k1Signature = serde_json::from_str(&s).unwrap();
599 assert_eq!(sig, sig2);
600 }
601}