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