Expand tests for ethereum-schnorr-contract

This commit is contained in:
Luke Parker
2024-10-28 18:08:31 -04:00
parent 0b61a75afc
commit ce1689b325
9 changed files with 205 additions and 51 deletions

View File

@@ -12,7 +12,7 @@ use k256::{
use alloy_core::primitives::Address;
use crate::{PublicKey, Signature};
use crate::{Signature, tests::test_key};
// The ecrecover opcode, yet with if the y is odd replacing v
fn ecrecover(message: Scalar, odd_y: bool, r: Scalar, s: Scalar) -> Option<[u8; 20]> {
@@ -64,12 +64,7 @@ fn test_ecrecover() {
// of efficiently verifying Schnorr signatures in an Ethereum contract
#[test]
fn nonce_recovery_via_ecrecover() {
let (key, public_key) = loop {
let key = Scalar::random(&mut OsRng);
if let Some(public_key) = PublicKey::new(ProjectivePoint::GENERATOR * key) {
break (key, public_key);
}
};
let (key, public_key) = test_key();
let nonce = Scalar::random(&mut OsRng);
let R = ProjectivePoint::GENERATOR * nonce;
@@ -81,26 +76,28 @@ fn nonce_recovery_via_ecrecover() {
let s = nonce + (c * key);
/*
An ECDSA signature is `(r, s)` with `s = (H(m) + rx) / k`, where:
- `m` is the message
An ECDSA signature is `(r, s)` with `s = (m + (r * x)) / k`, where:
- `m` is the hash of the message
- `r` is the x-coordinate of the nonce, reduced into a scalar
- `x` is the private key
- `k` is the nonce
We fix the recovery ID to be for the even key with an x-coordinate < the order. Accordingly,
`kG = Point::from(Even, r)`. This enables recovering the public key via
`((s Point::from(Even, r)) - H(m)G) / r`.
`k * G = Point::from(Even, r)`. This enables recovering the public key via
`((s * Point::from(Even, r)) - (m * G)) / r`.
We want to calculate `R` from `(c, s)` where `s = r + cx`. That means we need to calculate
`sG - cX`.
`(s * G) - (c * X)`.
We can calculate `sG - cX` with `((s Point::from(Even, r)) - H(m)G) / r` if:
- Latter `r` = `X.x`
- Latter `s` = `c`
- `H(m)` = former `s`
This gets us to `(cX - sG) / X.x`. If we additionally scale the latter's `s, H(m)` values (the
former's `c, s` values) by `X.x`, we get `cX - sG`. This just requires negating each to achieve
`sG - cX`.
We can calculate `(s * G) - (c * X)` with `((s * Point::from(Even, r)) - (m * G)) / r` if:
- ECDSA `r` = `X.x`, the x-coordinate of the Schnorr public key
- ECDSA `s` = `c`, the Schnorr signature's challenge
- ECDSA `m` = Schnorr `s`
This gets us to `((c * X) - (s * G)) / X.x`. If we additionally scale the ECDSA `s, m` values
(the Schnorr `c, s` values) by `X.x`, we get `(c * X) - (s * G)`. This just requires negating
to achieve `(s * G) - (c * X)`.
With `R`, we can recalculate and compare the challenges to confirm the signature is valid.
*/
let x_scalar = <Scalar as Reduce<U256>>::reduce_bytes(&public_key.point().to_affine().x());
let sa = -(s * x_scalar);