1mod ed25519;
8mod hash;
9#[allow(dead_code)]
10mod secp256k1;
11pub mod signer;
12use std::{fmt::Display, io, num::ParseIntError, str::FromStr};
13
14use allocative::Allocative;
15use alloy_primitives::FixedBytes;
16use custom_debug_derive::Debug;
17pub use ed25519::{Ed25519PublicKey, Ed25519SecretKey, Ed25519Signature};
18pub use hash::*;
19use linera_witty::{WitLoad, WitStore, WitType};
20pub use secp256k1::{
21 evm::{EvmPublicKey, EvmSecretKey, EvmSignature},
22 Secp256k1PublicKey, Secp256k1SecretKey, Secp256k1Signature,
23};
24use serde::{Deserialize, Serialize};
25pub use signer::*;
26use thiserror::Error;
27
28use crate::{hex_debug, identifiers::AccountOwner, visit_allocative_simple};
29
30pub type ValidatorPublicKey = secp256k1::Secp256k1PublicKey;
32pub type ValidatorSecretKey = secp256k1::Secp256k1SecretKey;
34pub type ValidatorSignature = secp256k1::Secp256k1Signature;
36pub type ValidatorKeypair = secp256k1::Secp256k1KeyPair;
38
39#[derive(Serialize, Deserialize, Debug, Copy, Clone, Eq, PartialEq)]
41pub enum SignatureScheme {
42 Ed25519,
44 Secp256k1,
46 EvmSecp256k1,
48}
49
50#[derive(
54 Serialize,
55 Deserialize,
56 Debug,
57 Eq,
58 PartialEq,
59 Ord,
60 PartialOrd,
61 Copy,
62 Clone,
63 Hash,
64 WitType,
65 WitLoad,
66 WitStore,
67 Allocative,
68)]
69pub enum AccountPublicKey {
70 Ed25519(#[allocative(visit = visit_allocative_simple)] ed25519::Ed25519PublicKey),
72 Secp256k1(#[allocative(visit = visit_allocative_simple)] secp256k1::Secp256k1PublicKey),
74 EvmSecp256k1(#[allocative(visit = visit_allocative_simple)] secp256k1::evm::EvmPublicKey),
76}
77
78#[derive(Serialize, Deserialize)]
80pub enum AccountSecretKey {
81 Ed25519(ed25519::Ed25519SecretKey),
83 Secp256k1(secp256k1::Secp256k1SecretKey),
85 EvmSecp256k1(secp256k1::evm::EvmSecretKey),
87}
88
89#[derive(Eq, PartialEq, Copy, Clone, Debug, Serialize, Deserialize, Allocative)]
91pub enum AccountSignature {
92 Ed25519 {
94 #[allocative(visit = visit_allocative_simple)]
96 signature: ed25519::Ed25519Signature,
97 #[allocative(visit = visit_allocative_simple)]
99 public_key: ed25519::Ed25519PublicKey,
100 },
101 Secp256k1 {
103 #[allocative(visit = visit_allocative_simple)]
105 signature: secp256k1::Secp256k1Signature,
106 #[allocative(visit = visit_allocative_simple)]
108 public_key: secp256k1::Secp256k1PublicKey,
109 },
110 EvmSecp256k1 {
112 #[allocative(visit = visit_allocative_simple)]
114 signature: secp256k1::evm::EvmSignature,
115 #[debug(with = "hex_debug")]
117 #[allocative(visit = visit_allocative_simple)]
118 address: [u8; 20],
119 },
120}
121
122impl AccountSecretKey {
123 pub fn public(&self) -> AccountPublicKey {
125 match self {
126 AccountSecretKey::Ed25519(secret) => AccountPublicKey::Ed25519(secret.public()),
127 AccountSecretKey::Secp256k1(secret) => AccountPublicKey::Secp256k1(secret.public()),
128 AccountSecretKey::EvmSecp256k1(secret) => {
129 AccountPublicKey::EvmSecp256k1(secret.public())
130 }
131 }
132 }
133
134 pub fn copy(&self) -> Self {
136 match self {
137 AccountSecretKey::Ed25519(secret) => AccountSecretKey::Ed25519(secret.copy()),
138 AccountSecretKey::Secp256k1(secret) => AccountSecretKey::Secp256k1(secret.copy()),
139 AccountSecretKey::EvmSecp256k1(secret) => AccountSecretKey::EvmSecp256k1(secret.copy()),
140 }
141 }
142
143 pub fn sign<'de, T>(&self, value: &T) -> AccountSignature
145 where
146 T: BcsSignable<'de>,
147 {
148 match self {
149 AccountSecretKey::Ed25519(secret) => {
150 let signature = Ed25519Signature::new(value, secret);
151 let public_key = secret.public();
152 AccountSignature::Ed25519 {
153 signature,
154 public_key,
155 }
156 }
157 AccountSecretKey::Secp256k1(secret) => {
158 let signature = secp256k1::Secp256k1Signature::new(value, secret);
159 let public_key = secret.public();
160 AccountSignature::Secp256k1 {
161 signature,
162 public_key,
163 }
164 }
165 AccountSecretKey::EvmSecp256k1(secret) => {
166 let signature = secp256k1::evm::EvmSignature::new(CryptoHash::new(value), secret);
167 let address: [u8; 20] = secret.address().into();
168 AccountSignature::EvmSecp256k1 { signature, address }
169 }
170 }
171 }
172
173 pub fn sign_prehash(&self, value: CryptoHash) -> AccountSignature {
175 match self {
176 AccountSecretKey::Ed25519(secret) => {
177 let signature = Ed25519Signature::sign_prehash(secret, value);
178 let public_key = secret.public();
179 AccountSignature::Ed25519 {
180 signature,
181 public_key,
182 }
183 }
184 AccountSecretKey::Secp256k1(secret) => {
185 let signature = secp256k1::Secp256k1Signature::sign_prehash(secret, value);
186 let public_key = secret.public();
187 AccountSignature::Secp256k1 {
188 signature,
189 public_key,
190 }
191 }
192 AccountSecretKey::EvmSecp256k1(secret) => {
193 let signature = secp256k1::evm::EvmSignature::sign_prehash(secret, value);
194 let address: [u8; 20] = secret.address().into();
195 AccountSignature::EvmSecp256k1 { signature, address }
196 }
197 }
198 }
199
200 #[cfg(all(with_testing, with_getrandom))]
201 pub fn generate() -> Self {
203 AccountSecretKey::Ed25519(Ed25519SecretKey::generate())
204 }
205
206 #[cfg(all(with_getrandom, not(feature = "revm")))]
207 pub fn generate_from<R: CryptoRng>(rng: &mut R) -> Self {
209 AccountSecretKey::Ed25519(Ed25519SecretKey::generate_from(rng))
210 }
211
212 #[cfg(all(with_getrandom, feature = "revm"))]
213 pub fn generate_from<R: CryptoRng>(rng: &mut R) -> Self {
215 AccountSecretKey::EvmSecp256k1(EvmSecretKey::generate_from(rng))
216 }
217}
218
219impl AccountPublicKey {
220 pub fn scheme(&self) -> SignatureScheme {
222 match self {
223 AccountPublicKey::Ed25519(_) => SignatureScheme::Ed25519,
224 AccountPublicKey::Secp256k1(_) => SignatureScheme::Secp256k1,
225 AccountPublicKey::EvmSecp256k1(_) => SignatureScheme::EvmSecp256k1,
226 }
227 }
228
229 pub fn as_bytes(&self) -> Vec<u8> {
231 bcs::to_bytes(&self).expect("serialization to bytes should not fail")
232 }
233
234 pub fn from_slice(bytes: &[u8]) -> Result<Self, CryptoError> {
238 bcs::from_bytes(bytes).map_err(CryptoError::PublicKeyParseError)
239 }
240
241 #[cfg(with_testing)]
243 pub fn test_key(name: u8) -> Self {
244 AccountPublicKey::Ed25519(Ed25519PublicKey::test_key(name))
245 }
246}
247
248impl AccountSignature {
249 pub fn verify<'de, T>(&self, value: &T) -> Result<(), CryptoError>
251 where
252 T: BcsSignable<'de> + std::fmt::Debug,
253 {
254 match self {
255 AccountSignature::Ed25519 {
256 signature,
257 public_key,
258 } => signature.check(value, *public_key),
259 AccountSignature::Secp256k1 {
260 signature,
261 public_key,
262 } => signature.check(value, *public_key),
263 AccountSignature::EvmSecp256k1 {
264 signature,
265 address: sender_address,
266 } => {
267 signature.check_with_recover(value, *sender_address)?;
268 Ok(())
269 }
270 }
271 }
272
273 pub fn to_bytes(&self) -> Vec<u8> {
275 bcs::to_bytes(&self).expect("serialization to bytes should not fail")
276 }
277
278 pub fn from_slice(bytes: &[u8]) -> Result<Self, CryptoError> {
280 bcs::from_bytes(bytes).map_err(CryptoError::SignatureParseError)
281 }
282
283 pub fn owner(&self) -> AccountOwner {
285 match self {
286 AccountSignature::Ed25519 { public_key, .. } => AccountOwner::from(*public_key),
287 AccountSignature::Secp256k1 { public_key, .. } => AccountOwner::from(*public_key),
288 AccountSignature::EvmSecp256k1 { address, .. } => AccountOwner::Address20(*address),
289 }
290 }
291}
292
293impl FromStr for AccountPublicKey {
294 type Err = CryptoError;
295
296 fn from_str(s: &str) -> Result<Self, Self::Err> {
297 let value = hex::decode(s)?;
298 AccountPublicKey::from_slice(value.as_slice())
299 }
300}
301
302impl Display for AccountPublicKey {
303 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
304 write!(f, "{}", hex::encode(self.as_bytes()))
305 }
306}
307
308impl TryFrom<&[u8]> for AccountSignature {
309 type Error = CryptoError;
310
311 fn try_from(bytes: &[u8]) -> Result<Self, Self::Error> {
312 AccountSignature::from_slice(bytes)
313 }
314}
315
316#[derive(Error, Debug)]
318#[allow(missing_docs)]
319pub enum CryptoError {
320 #[error("Signature for object {type_name} is not valid: {error}")]
321 InvalidSignature { error: String, type_name: String },
322 #[error("Signature from validator is missing")]
323 MissingValidatorSignature,
324 #[error(transparent)]
325 NonHexDigits(#[from] hex::FromHexError),
326 #[error(
327 "Byte slice has length {0} but a `CryptoHash` requires exactly {expected} bytes",
328 expected = FixedBytes::<32>::len_bytes(),
329 )]
330 IncorrectHashSize(usize),
331 #[error(
332 "Byte slice has length {len} but a {scheme} `PublicKey` requires exactly {expected} bytes"
333 )]
334 IncorrectPublicKeySize {
335 scheme: &'static str,
336 len: usize,
337 expected: usize,
338 },
339 #[error(
340 "byte slice has length {len} but a {scheme} `Signature` requires exactly {expected} bytes"
341 )]
342 IncorrectSignatureBytes {
343 scheme: &'static str,
344 len: usize,
345 expected: usize,
346 },
347 #[error("Could not parse integer: {0}")]
348 ParseIntError(#[from] ParseIntError),
349 #[error("secp256k1 error: {0}")]
350 Secp256k1Error(k256::ecdsa::Error),
351 #[error("could not parse public key: {0}: point at infinity")]
352 Secp256k1PointAtInfinity(String),
353 #[error("could not parse public key: {0}")]
354 PublicKeyParseError(bcs::Error),
355 #[error("could not parse signature: {0}")]
356 SignatureParseError(bcs::Error),
357}
358
359#[cfg(with_getrandom)]
360pub trait CryptoRng: rand::CryptoRng + rand::RngCore + Send + Sync {}
362
363#[cfg(with_getrandom)]
364impl<T: rand::CryptoRng + rand::RngCore + Send + Sync> CryptoRng for T {}
365
366#[cfg(with_getrandom)]
367impl From<Option<u64>> for Box<dyn CryptoRng> {
368 fn from(seed: Option<u64>) -> Self {
369 use rand::SeedableRng;
370
371 match seed {
372 Some(seed) => Box::new(rand::rngs::StdRng::seed_from_u64(seed)),
373 None => Box::new(rand::rngs::OsRng),
374 }
375 }
376}
377
378pub trait Hashable<Hasher> {
380 fn write(&self, hasher: &mut Hasher);
382}
383
384pub trait HasTypeName {
386 fn type_name() -> &'static str;
388}
389
390pub trait BcsHashable<'de>: Serialize + Deserialize<'de> {}
394
395pub trait BcsSignable<'de>: Serialize + Deserialize<'de> {}
399
400impl<'de, T: BcsSignable<'de>> BcsHashable<'de> for T {}
401
402impl<'de, T, Hasher> Hashable<Hasher> for T
403where
404 T: BcsHashable<'de>,
405 Hasher: io::Write,
406{
407 fn write(&self, hasher: &mut Hasher) {
408 let name = <Self as HasTypeName>::type_name();
409 write!(hasher, "{}::", name).expect("Hasher should not fail");
411 bcs::serialize_into(hasher, &self).expect("Message serialization should not fail");
412 }
413}
414
415impl<Hasher> Hashable<Hasher> for [u8]
416where
417 Hasher: io::Write,
418{
419 fn write(&self, hasher: &mut Hasher) {
420 hasher.write_all(self).expect("Hasher should not fail");
421 }
422}
423
424impl<'de, T> HasTypeName for T
425where
426 T: BcsHashable<'de>,
427{
428 fn type_name() -> &'static str {
429 serde_name::trace_name::<Self>().expect("Self must be a struct or an enum")
430 }
431}
432
433#[cfg(with_testing)]
435#[derive(Debug, Serialize, Deserialize)]
436pub struct TestString(pub String);
437
438#[cfg(with_testing)]
439impl TestString {
440 pub fn new(s: impl Into<String>) -> Self {
442 Self(s.into())
443 }
444}
445
446#[cfg(with_testing)]
447impl BcsSignable<'_> for TestString {}
448
449pub(crate) fn le_bytes_to_u64_array(bytes: &[u8]) -> [u64; 4] {
451 let mut integers = [0u64; 4];
452
453 integers[0] = u64::from_le_bytes(bytes[0..8].try_into().expect("incorrect indices"));
454 integers[1] = u64::from_le_bytes(bytes[8..16].try_into().expect("incorrect indices"));
455 integers[2] = u64::from_le_bytes(bytes[16..24].try_into().expect("incorrect indices"));
456 integers[3] = u64::from_le_bytes(bytes[24..32].try_into().expect("incorrect indices"));
457
458 integers
459}
460
461pub(crate) fn be_bytes_to_u64_array(bytes: &[u8]) -> [u64; 4] {
463 let mut integers = [0u64; 4];
464
465 integers[0] = u64::from_be_bytes(bytes[0..8].try_into().expect("incorrect indices"));
466 integers[1] = u64::from_be_bytes(bytes[8..16].try_into().expect("incorrect indices"));
467 integers[2] = u64::from_be_bytes(bytes[16..24].try_into().expect("incorrect indices"));
468 integers[3] = u64::from_be_bytes(bytes[24..32].try_into().expect("incorrect indices"));
469
470 integers
471}
472
473pub(crate) fn u64_array_to_le_bytes(integers: [u64; 4]) -> [u8; 32] {
475 let mut bytes = [0u8; 32];
476
477 bytes[0..8].copy_from_slice(&integers[0].to_le_bytes());
478 bytes[8..16].copy_from_slice(&integers[1].to_le_bytes());
479 bytes[16..24].copy_from_slice(&integers[2].to_le_bytes());
480 bytes[24..32].copy_from_slice(&integers[3].to_le_bytes());
481
482 bytes
483}
484
485pub fn u64_array_to_be_bytes(integers: [u64; 4]) -> [u8; 32] {
487 let mut bytes = [0u8; 32];
488
489 bytes[0..8].copy_from_slice(&integers[0].to_be_bytes());
490 bytes[8..16].copy_from_slice(&integers[1].to_be_bytes());
491 bytes[16..24].copy_from_slice(&integers[2].to_be_bytes());
492 bytes[24..32].copy_from_slice(&integers[3].to_be_bytes());
493
494 bytes
495}
496
497#[cfg(test)]
498mod tests {
499 use super::*;
500 use crate::crypto::{ed25519::Ed25519SecretKey, secp256k1::Secp256k1KeyPair};
501
502 #[test]
503 fn test_u64_array_to_be_bytes() {
504 let input = [
505 0x0123456789ABCDEF,
506 0xFEDCBA9876543210,
507 0x0011223344556677,
508 0x8899AABBCCDDEEFF,
509 ];
510 let expected_output = [
511 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54,
512 0x32, 0x10, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB,
513 0xCC, 0xDD, 0xEE, 0xFF,
514 ];
515
516 let output = u64_array_to_be_bytes(input);
517 assert_eq!(output, expected_output);
518 assert_eq!(input, be_bytes_to_u64_array(&u64_array_to_be_bytes(input)));
519 }
520
521 #[test]
522 fn test_u64_array_to_le_bytes() {
523 let input = [
524 0x0123456789ABCDEF,
525 0xFEDCBA9876543210,
526 0x0011223344556677,
527 0x8899AABBCCDDEEFF,
528 ];
529 let expected_output = [
530 0xEF, 0xCD, 0xAB, 0x89, 0x67, 0x45, 0x23, 0x01, 0x10, 0x32, 0x54, 0x76, 0x98, 0xBA,
531 0xDC, 0xFE, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, 0x00, 0xFF, 0xEE, 0xDD, 0xCC,
532 0xBB, 0xAA, 0x99, 0x88,
533 ];
534
535 let output = u64_array_to_le_bytes(input);
536 assert_eq!(output, expected_output);
537 assert_eq!(input, le_bytes_to_u64_array(&u64_array_to_le_bytes(input)));
538 }
539
540 #[test]
541 fn roundtrip_account_pk_bytes_repr() {
542 fn roundtrip_test(secret: AccountSecretKey) {
543 let public = secret.public();
544 let bytes = public.as_bytes();
545 let parsed = AccountPublicKey::from_slice(&bytes).unwrap();
546 assert_eq!(public, parsed);
547 }
548 roundtrip_test(AccountSecretKey::Ed25519(Ed25519SecretKey::generate()));
549 roundtrip_test(AccountSecretKey::Secp256k1(
550 Secp256k1KeyPair::generate().secret_key,
551 ));
552 }
553
554 #[test]
555 fn roundtrip_signature_bytes_repr() {
556 fn roundtrip_test(secret: AccountSecretKey) {
557 let test_string = TestString::new("test");
558 let signature = secret.sign(&test_string);
559 let bytes = signature.to_bytes();
560 let parsed = AccountSignature::from_slice(&bytes).unwrap();
561 assert_eq!(signature, parsed);
562 }
563 roundtrip_test(AccountSecretKey::Ed25519(Ed25519SecretKey::generate()));
564 roundtrip_test(AccountSecretKey::Secp256k1(
565 Secp256k1KeyPair::generate().secret_key,
566 ));
567 roundtrip_test(AccountSecretKey::EvmSecp256k1(EvmSecretKey::generate()));
568 }
569
570 #[test]
571 fn roundtrip_display_from_str_pk() {
572 fn test(secret: AccountSecretKey) {
573 let public = secret.public();
574 let display = public.to_string();
575 let parsed = AccountPublicKey::from_str(&display).unwrap();
576 assert_eq!(public, parsed);
577 }
578 test(AccountSecretKey::Ed25519(Ed25519SecretKey::generate()));
579 test(AccountSecretKey::Secp256k1(
580 Secp256k1KeyPair::generate().secret_key,
581 ));
582 }
583}