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