diff --git a/README.md b/README.md index 78b0708..534d587 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ If you would like to get a grant to create PLUME applications or help to fix bug ## Contributions -If you'd like to contribute, we offer $50 bounties in Eth/DAI for resolving any of the bugs in our issues! Each of them is quite small. That includes [#28](https://github.com/plume-sig/zk-nullifier-sig/issues/28), [#24](https://github.com/plume-sig/zk-nullifier-sig/issues/24), [#23](https://github.com/plume-sig/zk-nullifier-sig/issues/23), [#22](https://github.com/plume-sig/zk-nullifier-sig/issues/22), [#20](https://github.com/plume-sig/zk-nullifier-sig/issues/20), [#19](https://github.com/plume-sig/zk-nullifier-sig/issues/19), [#18](https://github.com/plume-sig/zk-nullifier-sig/issues/18), [#17](https://github.com/plume-sig/zk-nullifier-sig/issues/17), [#16](https://github.com/plume-sig/zk-nullifier-sig/issues/16), [#15](https://github.com/plume-sig/zk-nullifier-sig/issues/15), [#14](https://github.com/plume-sig/zk-nullifier-sig/issues/14),and [#13](https://github.com/plume-sig/zk-nullifier-sig/issues/13). +If you'd like to contribute, we offer $50 bounties in Eth/DAI for resolving any of the bugs in our issues! Each of them is quite small. That includes [#28](https://github.com/plume-sig/zk-nullifier-sig/issues/28), [#24](https://github.com/plume-sig/zk-nullifier-sig/issues/24), [#22](https://github.com/plume-sig/zk-nullifier-sig/issues/22), [#20](https://github.com/plume-sig/zk-nullifier-sig/issues/20), [#19](https://github.com/plume-sig/zk-nullifier-sig/issues/19), [#18](https://github.com/plume-sig/zk-nullifier-sig/issues/18), [#17](https://github.com/plume-sig/zk-nullifier-sig/issues/17), [#16](https://github.com/plume-sig/zk-nullifier-sig/issues/16), [#15](https://github.com/plume-sig/zk-nullifier-sig/issues/15), [#14](https://github.com/plume-sig/zk-nullifier-sig/issues/14),and [#13](https://github.com/plume-sig/zk-nullifier-sig/issues/13). ## Implementations diff --git a/rust-arkworks/src/lib.rs b/rust-arkworks/src/lib.rs index bbf8246..15f32dd 100644 --- a/rust-arkworks/src/lib.rs +++ b/rust-arkworks/src/lib.rs @@ -48,6 +48,7 @@ pub mod sig { Ok(hash_to_curve::hash_to_curve::(message, pk)) } + // TODO [replace SHA-512](https://github.com/plume-sig/zk-nullifier-sig/issues/39#issuecomment-1732497672) fn compute_c_v1( g: &GroupAffine

, pk: &GroupAffine

, @@ -55,7 +56,8 @@ pub mod sig { nul: &GroupAffine

, g_r: &GroupAffine

, z: &GroupAffine

, - ) -> P::ScalarField { + // should be `Output` when tests are fixed + ) -> Vec { // Compute c = sha512([g, pk, h, nul, g^r, z]) let g_bytes = affine_to_bytes::

(g); let pk_bytes = affine_to_bytes::

(pk); @@ -68,26 +70,16 @@ pub mod sig { let mut sha512_hasher = Sha512::new(); sha512_hasher.update(c_preimage_vec.as_slice()); - let sha512_hasher_result = sha512_hasher.finalize(); - - // Take the first 32 bytes - let mut first_32 = Vec::::with_capacity(32); - for i in 0..32 { - first_32.push(sha512_hasher_result[i]); - } - - // Convert digest bytes to a scalar - let c = first_32.as_slice(); - let c_be = P::ScalarField::from_be_bytes_mod_order(c); - - P::ScalarField::from(c_be) + sha512_hasher.finalize()[0..32].to_owned() } + // TODO [replace SHA-512](https://github.com/plume-sig/zk-nullifier-sig/issues/39#issuecomment-1732497672) fn compute_c_v2( nul: &GroupAffine

, g_r: &GroupAffine

, z: &GroupAffine

, - ) -> P::ScalarField { + // should be `Output` when tests are fixed + ) -> Vec { // Compute c = sha512([nul, g^r, z]) let nul_bytes = affine_to_bytes::

(nul); let g_r_bytes = affine_to_bytes::

(g_r); @@ -97,19 +89,7 @@ pub mod sig { let mut sha512_hasher = Sha512::new(); sha512_hasher.update(c_preimage_vec.as_slice()); - let sha512_hasher_result = sha512_hasher.finalize(); - - // Take the first 32 bytes - let mut first_32 = Vec::::with_capacity(32); - for i in 0..32 { - first_32.push(sha512_hasher_result[i]); - } - - // Convert digest bytes to a scalar - let c = first_32.as_slice(); - let c_be = P::ScalarField::from_be_bytes_mod_order(c); - - P::ScalarField::from(c_be) + sha512_hasher.finalize()[0..32].to_owned() } pub trait VerifiableUnpredictableFunction { @@ -214,10 +194,11 @@ pub mod sig { let nul = h.mul(*keypair.1).into_affine(); // Compute c = sha512([g, pk, h, nul, g^r, z]) - let c_scalar: P::ScalarField = match version { + let c = match version { PlumeVersion::V1 => compute_c_v1::

(&g, keypair.0, &h, &nul, &g_r, &z), PlumeVersion::V2 => compute_c_v2(&nul, &g_r, &z), }; + let c_scalar = P::ScalarField::from_be_bytes_mod_order(c.as_ref()); // Compute s = r + sk ⋅ c let sk_c = keypair.1.into_repr().into() * c_scalar.into_repr().into(); let s = r.into_repr().into() + sk_c; @@ -257,12 +238,14 @@ pub mod sig { // Compute h = htc([m, pk]) let h = compute_h::(pk, message).unwrap(); + // TODO [replace SHA-512](https://github.com/plume-sig/zk-nullifier-sig/issues/39#issuecomment-1732497672) // Compute c' = sha512([g, pk, h, nul, g^r, z]) for v1 // c' = sha512([nul, g^r, z]) for v2 - let c_scalar: P::ScalarField = match version { + let c = match version { PlumeVersion::V1 => compute_c_v1::

(&pp.g, pk, &h, &sig.nul, &sig.g_r, &sig.z), PlumeVersion::V2 => compute_c_v2(&sig.nul, &sig.g_r, &sig.z), }; + let c_scalar = P::ScalarField::from_be_bytes_mod_order(c.as_ref()); // Reject if g^s ⋅ pk^{-c} != g^r let g_s = pp.g.mul(sig.s); diff --git a/rust-k256/src/lib.rs b/rust-k256/src/lib.rs index c3ed26e..8988224 100644 --- a/rust-k256/src/lib.rs +++ b/rust-k256/src/lib.rs @@ -3,9 +3,13 @@ // #![feature(generic_const_expr)] // #![allow(incomplete_features)] +use digest::Output; +use elliptic_curve::bigint::ArrayEncoding; use elliptic_curve::hash2curve::{ExpandMsgXmd, GroupDigest}; +use elliptic_curve::ops::Reduce; use elliptic_curve::sec1::ToEncodedPoint; use hex_literal::hex; +use k256::U256; use k256::{ // ecdsa::{signature::Signer, Signature, SigningKey}, elliptic_curve::group::ff::PrimeField, @@ -47,7 +51,7 @@ fn gen_test_scalar_r() -> Scalar { .unwrap() } -fn sha256hash_vec_signal(values: &[ProjectivePoint]) -> Scalar { +fn sha256hash_vec_signal(values: &[ProjectivePoint]) -> Output { let preimage_vec = values .iter() .map(|value| encode_pt(*value).unwrap()) @@ -55,10 +59,7 @@ fn sha256hash_vec_signal(values: &[ProjectivePoint]) -> Scalar { .concat(); let mut sha256_hasher = Sha256::new(); sha256_hasher.update(preimage_vec.as_slice()); - let sha512_hasher_result = sha256_hasher.finalize(); //256 bit hash - - let bytes = FieldBytes::from_iter(sha512_hasher_result.iter().copied()); - Scalar::from_repr(bytes).unwrap() + sha256_hasher.finalize() //256 bit hash } fn sha256hash6signals( @@ -123,7 +124,7 @@ fn verify_signals( m: &[u8], pk: &ProjectivePoint, nullifier: &ProjectivePoint, - c: &Scalar, + c: &Output, r_sk_c: &Scalar, g_r_option: &Option, hash_m_pk_pow_r_option: &Option, @@ -139,27 +140,29 @@ fn verify_signals( // Check whether g^r equals g^s * pk^{-c} let g_r: ProjectivePoint; + // TODO should we use non-zero `Scalar`? + let c_scalar = &Scalar::from_uint_reduced(U256::from_be_byte_array(*c)); match *g_r_option { Some(_g_r_value) => { - if (g * r_sk_c - pk * c) != _g_r_value { + if (g * r_sk_c - pk * c_scalar) != _g_r_value { verified = false; } } None => println!("g^r not provided, check skipped"), } - g_r = g * r_sk_c - pk * c; + g_r = g * r_sk_c - pk * c_scalar; // Check whether h^r equals h^{r + sk * c} * nullifier^{-c} let hash_m_pk_pow_r: ProjectivePoint; match *hash_m_pk_pow_r_option { Some(_hash_m_pk_pow_r_value) => { - if (hash_m_pk * r_sk_c - nullifier * c) != _hash_m_pk_pow_r_value { + if (hash_m_pk * r_sk_c - nullifier * c_scalar) != _hash_m_pk_pow_r_value { verified = false; } } None => println!("hash_m_pk_pow_r not provided, check skipped"), } - hash_m_pk_pow_r = hash_m_pk * r_sk_c - nullifier * c; + hash_m_pk_pow_r = hash_m_pk * r_sk_c - nullifier * c_scalar; // Check if the given hash matches match version { @@ -221,7 +224,7 @@ mod tests { ) -> ( ProjectivePoint, ProjectivePoint, - Scalar, + Output, Scalar, Option, Option, @@ -286,8 +289,10 @@ mod tests { } PlumeVersion::V2 => sha256hash_vec_signal(&[nullifier, g_r, hash_m_pk_pow_r]), }; + + let c_scalar = &Scalar::from_uint_reduced(U256::from_be_byte_array(c.clone())); // This value is part of the discrete log equivalence (DLEQ) proof. - let r_sk_c = r + sk * c; + let r_sk_c = r + sk * c_scalar; // Return the signature. (pk, nullifier, c, r_sk_c, Some(g_r), Some(hash_m_pk_pow_r)) @@ -337,7 +342,7 @@ mod tests { ); // Print c - println!("c: {:?}", hex::encode(&c.to_bytes())); + println!("c: {:?}", hex::encode(&c)); // Print r_sk_c println!("r_sk_c: {:?}", hex::encode(r_sk_c.to_bytes())); @@ -396,8 +401,7 @@ mod tests { ); // Test byte_array_to_scalar() - let bytes_to_convert = c.to_bytes(); - let scalar = byte_array_to_scalar(&bytes_to_convert); + let scalar = byte_array_to_scalar(&c); // TODO this `fn` looks suspicious as in reproducing const time ops assert_eq!( hex::encode(scalar.to_bytes()), "c6a7fc2c926ddbaf20731a479fb6566f2daa5514baae5223fe3b32edbce83254"