You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

84 lines
2.4 KiB

use plonky2::field::types::{Field, Sample};
use serde::{Deserialize, Serialize};
use crate::curve::curve_msm::msm_parallel;
use crate::curve::curve_types::{base_to_scalar, AffinePoint, Curve, CurveScalar};
#[derive(Copy, Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
pub struct ECDSASignature<C: Curve> {
pub r: C::ScalarField,
pub s: C::ScalarField,
}
#[derive(Copy, Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
pub struct ECDSASecretKey<C: Curve>(pub C::ScalarField);
impl<C: Curve> ECDSASecretKey<C> {
pub fn to_public(&self) -> ECDSAPublicKey<C> {
ECDSAPublicKey((CurveScalar(self.0) * C::GENERATOR_PROJECTIVE).to_affine())
}
}
#[derive(Copy, Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
pub struct ECDSAPublicKey<C: Curve>(pub AffinePoint<C>);
pub fn sign_message<C: Curve>(msg: C::ScalarField, sk: ECDSASecretKey<C>) -> ECDSASignature<C> {
let (k, rr) = {
let mut k = C::ScalarField::rand();
let mut rr = (CurveScalar(k) * C::GENERATOR_PROJECTIVE).to_affine();
while rr.x == C::BaseField::ZERO {
k = C::ScalarField::rand();
rr = (CurveScalar(k) * C::GENERATOR_PROJECTIVE).to_affine();
}
(k, rr)
};
let r = base_to_scalar::<C>(rr.x);
let s = k.inverse() * (msg + r * sk.0);
ECDSASignature { r, s }
}
pub fn verify_message<C: Curve>(
msg: C::ScalarField,
sig: ECDSASignature<C>,
pk: ECDSAPublicKey<C>,
) -> bool {
let ECDSASignature { r, s } = sig;
assert!(pk.0.is_valid());
let c = s.inverse();
let u1 = msg * c;
let u2 = r * c;
let g = C::GENERATOR_PROJECTIVE;
let w = 5; // Experimentally fastest
let point_proj = msm_parallel(&[u1, u2], &[g, pk.0.to_projective()], w);
let point = point_proj.to_affine();
let x = base_to_scalar::<C>(point.x);
r == x
}
#[cfg(test)]
mod tests {
use plonky2::field::secp256k1_scalar::Secp256K1Scalar;
use plonky2::field::types::Sample;
use crate::curve::ecdsa::{sign_message, verify_message, ECDSASecretKey};
use crate::curve::secp256k1::Secp256K1;
#[test]
fn test_ecdsa_native() {
type C = Secp256K1;
let msg = Secp256K1Scalar::rand();
let sk = ECDSASecretKey::<C>(Secp256K1Scalar::rand());
let pk = sk.to_public();
let sig = sign_message(msg, sk);
let result = verify_message(msg, sig, pk);
assert!(result);
}
}