1mod ed25519;
8mod hash;
9#[allow(dead_code)]
10mod secp256k1;
11use std::{fmt::Display, io, num::ParseIntError, str::FromStr};
12
13use alloy_primitives::FixedBytes;
14use custom_debug_derive::Debug;
15pub use ed25519::{Ed25519PublicKey, Ed25519SecretKey, Ed25519Signature};
16pub use hash::*;
17use linera_witty::{WitLoad, WitStore, WitType};
18pub use secp256k1::{
19 evm::{EvmPublicKey, EvmSecretKey, EvmSignature},
20 Secp256k1PublicKey, Secp256k1SecretKey, Secp256k1Signature,
21};
22use serde::{Deserialize, Serialize};
23use thiserror::Error;
24
25pub type ValidatorPublicKey = secp256k1::Secp256k1PublicKey;
27pub type ValidatorSecretKey = secp256k1::Secp256k1SecretKey;
29pub type ValidatorSignature = secp256k1::Secp256k1Signature;
31pub type ValidatorKeypair = secp256k1::Secp256k1KeyPair;
33
34#[derive(Serialize, Deserialize, Debug, Copy, Clone, Eq, PartialEq)]
36pub enum SignatureScheme {
37 Ed25519,
39 Secp256k1,
41 EvmSecp256k1,
43}
44
45#[derive(
49 Serialize,
50 Deserialize,
51 Debug,
52 Eq,
53 PartialEq,
54 Ord,
55 PartialOrd,
56 Copy,
57 Clone,
58 Hash,
59 WitType,
60 WitLoad,
61 WitStore,
62)]
63pub enum AccountPublicKey {
64 Ed25519(ed25519::Ed25519PublicKey),
66 Secp256k1(secp256k1::Secp256k1PublicKey),
68 EvmSecp256k1(secp256k1::evm::EvmPublicKey),
70}
71
72#[derive(Serialize, Deserialize)]
74pub enum AccountSecretKey {
75 Ed25519(ed25519::Ed25519SecretKey),
77 Secp256k1(secp256k1::Secp256k1SecretKey),
79 EvmSecp256k1(secp256k1::evm::EvmSecretKey),
81}
82
83#[derive(Eq, PartialEq, Copy, Clone, Debug, Serialize, Deserialize)]
85pub enum AccountSignature {
86 Ed25519(ed25519::Ed25519Signature),
88 Secp256k1(secp256k1::Secp256k1Signature),
90 EvmSecp256k1(secp256k1::evm::EvmSignature),
92}
93
94impl AccountSecretKey {
95 pub fn public(&self) -> AccountPublicKey {
97 match self {
98 AccountSecretKey::Ed25519(secret) => AccountPublicKey::Ed25519(secret.public()),
99 AccountSecretKey::Secp256k1(secret) => AccountPublicKey::Secp256k1(secret.public()),
100 AccountSecretKey::EvmSecp256k1(secret) => {
101 AccountPublicKey::EvmSecp256k1(secret.public())
102 }
103 }
104 }
105
106 pub fn copy(&self) -> Self {
108 match self {
109 AccountSecretKey::Ed25519(secret) => AccountSecretKey::Ed25519(secret.copy()),
110 AccountSecretKey::Secp256k1(secret) => AccountSecretKey::Secp256k1(secret.copy()),
111 AccountSecretKey::EvmSecp256k1(secret) => AccountSecretKey::EvmSecp256k1(secret.copy()),
112 }
113 }
114
115 pub fn sign<'de, T>(&self, value: &T) -> AccountSignature
117 where
118 T: BcsSignable<'de>,
119 {
120 match self {
121 AccountSecretKey::Ed25519(secret) => {
122 let signature = Ed25519Signature::new(value, secret);
123 AccountSignature::Ed25519(signature)
124 }
125 AccountSecretKey::Secp256k1(secret) => {
126 let signature = secp256k1::Secp256k1Signature::new(value, secret);
127 AccountSignature::Secp256k1(signature)
128 }
129 AccountSecretKey::EvmSecp256k1(secret) => {
130 let signature = secp256k1::evm::EvmSignature::new(value, secret);
131 AccountSignature::EvmSecp256k1(signature)
132 }
133 }
134 }
135
136 #[cfg(all(with_testing, with_getrandom))]
137 pub fn generate() -> Self {
139 AccountSecretKey::Ed25519(Ed25519SecretKey::generate())
140 }
141}
142
143impl AccountPublicKey {
144 pub fn scheme(&self) -> SignatureScheme {
146 match self {
147 AccountPublicKey::Ed25519(_) => SignatureScheme::Ed25519,
148 AccountPublicKey::Secp256k1(_) => SignatureScheme::Secp256k1,
149 AccountPublicKey::EvmSecp256k1(_) => SignatureScheme::EvmSecp256k1,
150 }
151 }
152
153 pub fn as_bytes(&self) -> Vec<u8> {
155 bcs::to_bytes(&self).expect("serialization to bytes should not fail")
156 }
157
158 pub fn from_slice(bytes: &[u8]) -> Result<Self, CryptoError> {
162 bcs::from_bytes(bytes).map_err(CryptoError::PublicKeyParseError)
163 }
164
165 #[cfg(with_testing)]
167 pub fn test_key(name: u8) -> Self {
168 AccountPublicKey::Ed25519(Ed25519PublicKey::test_key(name))
169 }
170}
171
172impl AccountSignature {
173 pub fn verify<'de, T>(&self, value: &T, author: AccountPublicKey) -> Result<(), CryptoError>
175 where
176 T: BcsSignable<'de> + std::fmt::Debug,
177 {
178 match (self, author) {
179 (AccountSignature::Ed25519(signature), AccountPublicKey::Ed25519(public_key)) => {
180 signature.check(value, public_key)
181 }
182 (AccountSignature::Secp256k1(signature), AccountPublicKey::Secp256k1(public_key)) => {
183 signature.check(value, &public_key)
184 }
185 (
186 AccountSignature::EvmSecp256k1(signature),
187 AccountPublicKey::EvmSecp256k1(public_key),
188 ) => signature.check(value, &public_key),
189 (AccountSignature::Ed25519(_), _) => {
190 let type_name = std::any::type_name::<T>();
191 Err(CryptoError::InvalidSignature {
192 error: "invalid signature scheme. Expected Ed25519 signature.".to_string(),
193 type_name: type_name.to_string(),
194 })
195 }
196 (AccountSignature::Secp256k1(_), _) => {
197 let type_name = std::any::type_name::<T>();
198 Err(CryptoError::InvalidSignature {
199 error: "invalid signature scheme. Expected secp256k1 signature.".to_string(),
200 type_name: type_name.to_string(),
201 })
202 }
203 (AccountSignature::EvmSecp256k1(_), _) => {
204 let type_name = std::any::type_name::<T>();
205 Err(CryptoError::InvalidSignature {
206 error: "invalid signature scheme. Expected EvmSecp256k1 signature.".to_string(),
207 type_name: type_name.to_string(),
208 })
209 }
210 }
211 }
212
213 pub fn to_bytes(&self) -> Vec<u8> {
215 bcs::to_bytes(&self).expect("serialization to bytes should not fail")
216 }
217
218 pub fn from_slice(bytes: &[u8]) -> Result<Self, CryptoError> {
220 bcs::from_bytes(bytes).map_err(CryptoError::SignatureParseError)
221 }
222}
223
224impl FromStr for AccountPublicKey {
225 type Err = CryptoError;
226
227 fn from_str(s: &str) -> Result<Self, Self::Err> {
228 let value = hex::decode(s)?;
229 AccountPublicKey::from_slice(value.as_slice())
230 }
231}
232
233impl Display for AccountPublicKey {
234 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
235 write!(f, "{}", hex::encode(self.as_bytes()))
236 }
237}
238
239impl TryFrom<&[u8]> for AccountSignature {
240 type Error = CryptoError;
241
242 fn try_from(bytes: &[u8]) -> Result<Self, Self::Error> {
243 AccountSignature::from_slice(bytes)
244 }
245}
246
247#[derive(Error, Debug)]
249#[allow(missing_docs)]
250pub enum CryptoError {
251 #[error("Signature for object {type_name} is not valid: {error}")]
252 InvalidSignature { error: String, type_name: String },
253 #[error("Signature from validator is missing")]
254 MissingValidatorSignature,
255 #[error(transparent)]
256 NonHexDigits(#[from] hex::FromHexError),
257 #[error(
258 "Byte slice has length {0} but a `CryptoHash` requires exactly {expected} bytes",
259 expected = FixedBytes::<32>::len_bytes(),
260 )]
261 IncorrectHashSize(usize),
262 #[error(
263 "Byte slice has length {len} but a {scheme} `PublicKey` requires exactly {expected} bytes"
264 )]
265 IncorrectPublicKeySize {
266 scheme: &'static str,
267 len: usize,
268 expected: usize,
269 },
270 #[error(
271 "byte slice has length {len} but a {scheme} `Signature` requires exactly {expected} bytes"
272 )]
273 IncorrectSignatureBytes {
274 scheme: &'static str,
275 len: usize,
276 expected: usize,
277 },
278 #[error("Could not parse integer: {0}")]
279 ParseIntError(#[from] ParseIntError),
280 #[error("secp256k1 error: {0}")]
281 Secp256k1Error(k256::ecdsa::Error),
282 #[error("could not parse public key: {0}: point at infinity")]
283 Secp256k1PointAtInfinity(String),
284 #[error("could not parse public key: {0}")]
285 PublicKeyParseError(bcs::Error),
286 #[error("could not parse signature: {0}")]
287 SignatureParseError(bcs::Error),
288}
289
290#[cfg(with_getrandom)]
291pub trait CryptoRng: rand::CryptoRng + rand::RngCore + Send + Sync {}
293
294#[cfg(with_getrandom)]
295impl<T: rand::CryptoRng + rand::RngCore + Send + Sync> CryptoRng for T {}
296
297#[cfg(with_getrandom)]
298impl From<Option<u64>> for Box<dyn CryptoRng> {
299 fn from(seed: Option<u64>) -> Self {
300 use rand::SeedableRng;
301
302 match seed {
303 Some(seed) => Box::new(rand::rngs::StdRng::seed_from_u64(seed)),
304 None => Box::new(rand::rngs::OsRng),
305 }
306 }
307}
308
309pub trait Hashable<Hasher> {
311 fn write(&self, hasher: &mut Hasher);
313}
314
315pub trait HasTypeName {
317 fn type_name() -> &'static str;
319}
320
321pub trait BcsHashable<'de>: Serialize + Deserialize<'de> {}
325
326pub trait BcsSignable<'de>: Serialize + Deserialize<'de> {}
330
331impl<'de, T: BcsSignable<'de>> BcsHashable<'de> for T {}
332
333impl<'de, T, Hasher> Hashable<Hasher> for T
334where
335 T: BcsHashable<'de>,
336 Hasher: io::Write,
337{
338 fn write(&self, hasher: &mut Hasher) {
339 let name = <Self as HasTypeName>::type_name();
340 write!(hasher, "{}::", name).expect("Hasher should not fail");
342 bcs::serialize_into(hasher, &self).expect("Message serialization should not fail");
343 }
344}
345
346impl<Hasher> Hashable<Hasher> for [u8]
347where
348 Hasher: io::Write,
349{
350 fn write(&self, hasher: &mut Hasher) {
351 hasher.write_all(self).expect("Hasher should not fail");
352 }
353}
354
355impl<'de, T> HasTypeName for T
356where
357 T: BcsHashable<'de>,
358{
359 fn type_name() -> &'static str {
360 serde_name::trace_name::<Self>().expect("Self must be a struct or an enum")
361 }
362}
363
364#[cfg(with_testing)]
366#[derive(Debug, Serialize, Deserialize)]
367pub struct TestString(pub String);
368
369#[cfg(with_testing)]
370impl TestString {
371 pub fn new(s: impl Into<String>) -> Self {
373 Self(s.into())
374 }
375}
376
377#[cfg(with_testing)]
378impl BcsSignable<'_> for TestString {}
379
380pub(crate) fn le_bytes_to_u64_array(bytes: &[u8]) -> [u64; 4] {
382 let mut integers = [0u64; 4];
383
384 integers[0] = u64::from_le_bytes(bytes[0..8].try_into().expect("incorrect indices"));
385 integers[1] = u64::from_le_bytes(bytes[8..16].try_into().expect("incorrect indices"));
386 integers[2] = u64::from_le_bytes(bytes[16..24].try_into().expect("incorrect indices"));
387 integers[3] = u64::from_le_bytes(bytes[24..32].try_into().expect("incorrect indices"));
388
389 integers
390}
391
392pub(crate) fn be_bytes_to_u64_array(bytes: &[u8]) -> [u64; 4] {
394 let mut integers = [0u64; 4];
395
396 integers[0] = u64::from_be_bytes(bytes[0..8].try_into().expect("incorrect indices"));
397 integers[1] = u64::from_be_bytes(bytes[8..16].try_into().expect("incorrect indices"));
398 integers[2] = u64::from_be_bytes(bytes[16..24].try_into().expect("incorrect indices"));
399 integers[3] = u64::from_be_bytes(bytes[24..32].try_into().expect("incorrect indices"));
400
401 integers
402}
403
404pub(crate) fn u64_array_to_le_bytes(integers: [u64; 4]) -> [u8; 32] {
406 let mut bytes = [0u8; 32];
407
408 bytes[0..8].copy_from_slice(&integers[0].to_le_bytes());
409 bytes[8..16].copy_from_slice(&integers[1].to_le_bytes());
410 bytes[16..24].copy_from_slice(&integers[2].to_le_bytes());
411 bytes[24..32].copy_from_slice(&integers[3].to_le_bytes());
412
413 bytes
414}
415
416pub(crate) fn u64_array_to_be_bytes(integers: [u64; 4]) -> [u8; 32] {
418 let mut bytes = [0u8; 32];
419
420 bytes[0..8].copy_from_slice(&integers[0].to_be_bytes());
421 bytes[8..16].copy_from_slice(&integers[1].to_be_bytes());
422 bytes[16..24].copy_from_slice(&integers[2].to_be_bytes());
423 bytes[24..32].copy_from_slice(&integers[3].to_be_bytes());
424
425 bytes
426}
427
428#[cfg(test)]
429mod tests {
430 use super::*;
431 use crate::crypto::{ed25519::Ed25519SecretKey, secp256k1::Secp256k1KeyPair};
432
433 #[test]
434 fn test_u64_array_to_be_bytes() {
435 let input = [
436 0x0123456789ABCDEF,
437 0xFEDCBA9876543210,
438 0x0011223344556677,
439 0x8899AABBCCDDEEFF,
440 ];
441 let expected_output = [
442 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54,
443 0x32, 0x10, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB,
444 0xCC, 0xDD, 0xEE, 0xFF,
445 ];
446
447 let output = u64_array_to_be_bytes(input);
448 assert_eq!(output, expected_output);
449 assert_eq!(input, be_bytes_to_u64_array(&u64_array_to_be_bytes(input)));
450 }
451
452 #[test]
453 fn test_u64_array_to_le_bytes() {
454 let input = [
455 0x0123456789ABCDEF,
456 0xFEDCBA9876543210,
457 0x0011223344556677,
458 0x8899AABBCCDDEEFF,
459 ];
460 let expected_output = [
461 0xEF, 0xCD, 0xAB, 0x89, 0x67, 0x45, 0x23, 0x01, 0x10, 0x32, 0x54, 0x76, 0x98, 0xBA,
462 0xDC, 0xFE, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, 0x00, 0xFF, 0xEE, 0xDD, 0xCC,
463 0xBB, 0xAA, 0x99, 0x88,
464 ];
465
466 let output = u64_array_to_le_bytes(input);
467 assert_eq!(output, expected_output);
468 assert_eq!(input, le_bytes_to_u64_array(&u64_array_to_le_bytes(input)));
469 }
470
471 #[test]
472 fn roundtrip_account_pk_bytes_repr() {
473 fn roundtrip_test(secret: AccountSecretKey) {
474 let public = secret.public();
475 let bytes = public.as_bytes();
476 let parsed = AccountPublicKey::from_slice(&bytes).unwrap();
477 assert_eq!(public, parsed);
478 }
479 roundtrip_test(AccountSecretKey::Ed25519(Ed25519SecretKey::generate()));
480 roundtrip_test(AccountSecretKey::Secp256k1(
481 Secp256k1KeyPair::generate().secret_key,
482 ));
483 }
484
485 #[test]
486 fn roundtrip_signature_bytes_repr() {
487 fn roundtrip_test(secret: AccountSecretKey) {
488 let test_string = TestString::new("test");
489 let signature = secret.sign(&test_string);
490 let bytes = signature.to_bytes();
491 let parsed = AccountSignature::from_slice(&bytes).unwrap();
492 assert_eq!(signature, parsed);
493 }
494 roundtrip_test(AccountSecretKey::Ed25519(Ed25519SecretKey::generate()));
495 roundtrip_test(AccountSecretKey::Secp256k1(
496 Secp256k1KeyPair::generate().secret_key,
497 ));
498 }
499
500 #[test]
501 fn roundtrip_display_from_str_pk() {
502 fn test(secret: AccountSecretKey) {
503 let public = secret.public();
504 let display = public.to_string();
505 let parsed = AccountPublicKey::from_str(&display).unwrap();
506 assert_eq!(public, parsed);
507 }
508 test(AccountSecretKey::Ed25519(Ed25519SecretKey::generate()));
509 test(AccountSecretKey::Secp256k1(
510 Secp256k1KeyPair::generate().secret_key,
511 ));
512 }
513}