plonky2-ecdsa/src/curve/ecdsa.rs
src/curve/ecdsa.rsRaw
1use plonky2::field::types::{Field, Sample};
2use serde::{Deserialize, Serialize};
3
4use crate::curve::curve_msm::msm_parallel;
5use crate::curve::curve_types::{base_to_scalar, AffinePoint, Curve, CurveScalar};
6
7#[derive(Copy, Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
8pub struct ECDSASignature<C: Curve> {
9 pub r: C::ScalarField,
10 pub s: C::ScalarField,
11}
12
13#[derive(Copy, Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
14pub struct ECDSASecretKey<C: Curve>(pub C::ScalarField);
15
16impl<C: Curve> ECDSASecretKey<C> {
17 pub fn to_public(&self) -> ECDSAPublicKey<C> {
18 ECDSAPublicKey((CurveScalar(self.0) * C::GENERATOR_PROJECTIVE).to_affine())
19 }
20}
21
22#[derive(Copy, Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
23pub struct ECDSAPublicKey<C: Curve>(pub AffinePoint<C>);
24
25pub fn sign_message<C: Curve>(msg: C::ScalarField, sk: ECDSASecretKey<C>) -> ECDSASignature<C> {
26 let (k, rr) = {
27 let mut k = C::ScalarField::rand();
28 let mut rr = (CurveScalar(k) * C::GENERATOR_PROJECTIVE).to_affine();
29 while rr.x == C::BaseField::ZERO {
30 k = C::ScalarField::rand();
31 rr = (CurveScalar(k) * C::GENERATOR_PROJECTIVE).to_affine();
32 }
33 (k, rr)
34 };
35 let r = base_to_scalar::<C>(rr.x);
36
37 let s = k.inverse() * (msg + r * sk.0);
38
39 ECDSASignature { r, s }
40}
41
42pub fn verify_message<C: Curve>(
43 msg: C::ScalarField,
44 sig: ECDSASignature<C>,
45 pk: ECDSAPublicKey<C>,
46) -> bool {
47 let ECDSASignature { r, s } = sig;
48
49 assert!(pk.0.is_valid());
50
51 let c = s.inverse();
52 let u1 = msg * c;
53 let u2 = r * c;
54
55 let g = C::GENERATOR_PROJECTIVE;
56 let w = 5; // Experimentally fastest
57 let point_proj = msm_parallel(&[u1, u2], &[g, pk.0.to_projective()], w);
58 let point = point_proj.to_affine();
59
60 let x = base_to_scalar::<C>(point.x);
61 r == x
62}
63
64#[cfg(test)]
65mod tests {
66 use plonky2::field::secp256k1_scalar::Secp256K1Scalar;
67 use plonky2::field::types::Sample;
68
69 use crate::curve::ecdsa::{sign_message, verify_message, ECDSASecretKey};
70 use crate::curve::secp256k1::Secp256K1;
71
72 #[test]
73 fn test_ecdsa_native() {
74 type C = Secp256K1;
75
76 let msg = Secp256K1Scalar::rand();
77 let sk = ECDSASecretKey::<C>(Secp256K1Scalar::rand());
78 let pk = sk.to_public();
79
80 let sig = sign_message(msg, sk);
81 let result = verify_message(msg, sig, pk);
82 assert!(result);
83 }
84}