airbender_crypto/secp256k1/
mod.rs1#![allow(long_running_const_eval)]
2#![allow(clippy::precedence)]
3
4mod context;
5pub mod field;
6pub mod hooks;
7mod points;
8mod recover;
9pub mod scalars;
10
11#[cfg(test)]
12mod test_vectors;
13
14use core::fmt::Debug;
15use core::fmt::Display;
16
17pub use context::ECMultContext;
18pub use recover::recover_with_context;
19pub use recover::recover_with_context_and_hooks;
20
21#[cfg(feature = "secp256k1-static-context")]
22pub use recover::{recover, recover_with_hooks};
23
24#[derive(Debug, PartialEq)]
25pub enum Secp256k1Err {
26 OperationOverflow,
27 InvalidParams,
28 RecoveredInfinity,
29}
30
31pub const SECP256K1N_HALF: [u8; 32] = [
36 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
37 0x5D, 0x57, 0x6E, 0x73, 0x57, 0xA4, 0x50, 0x1D, 0xDF, 0xE9, 0x2F, 0x46, 0x68, 0x1B, 0x20, 0xA0,
38];
39
40pub const SECP256K1N_HALF_U256: ruint::aliases::U256 =
41 ruint::aliases::U256::from_be_bytes(SECP256K1N_HALF);
42
43impl Display for Secp256k1Err {
44 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
45 match self {
46 Self::OperationOverflow => write!(f, "secp256k1: restoring x-coordinate overflowed"),
47 Self::InvalidParams => write!(
48 f,
49 "secp256k1: could not decompress signature to curve point"
50 ),
51 Self::RecoveredInfinity => write!(f, "secp256k1: recovered the point at infinity"),
52 }
53 }
54}
55
56#[cfg(feature = "secp256k1-static-context")]
57pub fn ecrecover_test() {
58 use crate::k256::{
59 ecdsa::{hazmat::bits2field, SigningKey},
60 elliptic_curve::{group::GroupEncoding, ops::Reduce},
61 Scalar,
62 };
63 use crate::sha3::Keccak256;
64 use crate::MiniDigest;
65 let message = "In the beginning the Universe was created.
66 This had made many people very angry and has been widely regarded as a bad move";
67 let private_key = SigningKey::from_bytes(
68 &[
69 136, 84, 181, 46, 13, 86, 203, 113, 63, 17, 137, 177, 95, 211, 104, 70, 112, 232, 200,
70 156, 225, 27, 123, 207, 243, 114, 4, 216, 148, 242, 81, 154,
71 ]
72 .into(),
73 )
74 .unwrap();
75 let digest = {
76 let mut hasher = Keccak256::new();
77 hasher.update(message);
78 let res = hasher.finalize();
79 let mut hash_bytes = [0u8; 32];
80 hash_bytes.copy_from_slice(&res);
81 hash_bytes
82 };
83
84 let public_key = private_key.verifying_key().as_affine();
85
86 let (signature, recovery_id) = private_key.sign_prehash_recoverable(&digest).unwrap();
87 let msg = <Scalar as Reduce<crate::k256::U256>>::reduce_bytes(
88 &bits2field::<crate::k256::Secp256k1>(&digest)
89 .map_err(|_| ())
90 .unwrap(),
91 );
92
93 let recovered_key = recover(&msg, &signature, &recovery_id).unwrap();
94
95 assert_eq!(recovered_key.to_bytes(), public_key.to_bytes());
96}
97
98#[cfg(test)]
99mod test {
100 use super::*;
101
102 #[test]
103 fn run_outside() {
104 ecrecover_test();
105 }
106}