arnaucube
arnaucube/plonky2-ecdsaPublic Self-hosted repository
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}