Skip to content

Commit

Permalink
Change hash_to_point algorithm
Browse files Browse the repository at this point in the history
  • Loading branch information
moshababo committed Mar 24, 2024
1 parent 16a87e7 commit f19333c
Show file tree
Hide file tree
Showing 5 changed files with 47 additions and 19 deletions.
2 changes: 2 additions & 0 deletions node/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions node/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,8 @@ kube = { version = "0.88.1", features = ["runtime", "derive"] }
k8s-openapi = { version = "0.21.0", features = ["latest"] }
jsonrpsee = { version = "0.21.0", features = ["server", "http-client"] }
tower = { version = "0.4.13" }
num-bigint = "0.4.4"
num-traits = "0.2.18"

# Note that "bench" profile inherits from "release" profile and
# "test" profile inherits from "dev" profile.
Expand Down
2 changes: 2 additions & 0 deletions node/libs/crypto/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ rand04.workspace = true
thiserror.workspace = true
tracing.workspace = true
ff_ce.workspace = true
num-bigint.workspace = true
num-traits.workspace = true

[dev-dependencies]
criterion.workspace = true
Expand Down
49 changes: 35 additions & 14 deletions node/libs/crypto/src/bn254/hash.rs
Original file line number Diff line number Diff line change
@@ -1,27 +1,48 @@
//! Hash operations.

use ff_ce::{Field, PrimeField, SqrtField};
use num_bigint::BigUint;
use num_traits::Num;
use pairing::{
bn256::{G1Affine, G1Compressed},
EncodedPoint,
bn256::{fq, Fq, FqRepr, Fr, G1Affine},
CurveAffine,
};
use sha3::Digest as _;

/// Hashes an arbitrary message and maps it to an elliptic curve point in G1.
pub(crate) fn hash_to_g1(msg: &[u8]) -> G1Affine {
for i in 0..256 {
// Hash the message with the index as suffix.
let bytes: [u8; 32] = sha3::Keccak256::new()
.chain_update(msg)
.chain_update((i as u32).to_be_bytes())
.finalize()
.into();
pub(crate) fn hash_to_point(msg: &[u8]) -> (G1Affine, u8) {
let hash: [u8; 32] = sha3::Keccak256::new().chain_update(msg).finalize().into();

// Try to get a G1 point from the hash. The probability that this works is around 1/8.
let p = G1Compressed::from_fixed_bytes(bytes).into_affine();
if let Ok(p) = p {
return p;
let hash_num = BigUint::from_bytes_be(&hash);
let prime_field_modulus = BigUint::from_str_radix(
"30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47",
16,
)
.unwrap();
let x_num = hash_num % prime_field_modulus;

let mut arr = [0u64; 4];
arr.copy_from_slice(x_num.to_u64_digits().as_slice());
let mut x = Fq::from_repr(FqRepr(arr)).unwrap();

for i in 0..255 {
let p = get_point_from_x(x);
if let Some(p) = p {
return (p, i);
}
x.add_assign(&Fq::one());
}

// It should be statistically infeasible to finish the loop without finding a point.
unreachable!()
}

fn get_point_from_x(mut x: Fq) -> Option<G1Affine> {
// Compute x^3 + b.
let mut x3b = x;
x3b.square();
x3b.mul_assign(&x);
x3b.add_assign(&fq::B_COEFF);
// Try find the square root.
x3b.sqrt().map(|y| G1Affine::from_xy_unchecked(x, y))
}
11 changes: 6 additions & 5 deletions node/libs/crypto/src/bn254/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@ impl SecretKey {

/// Produces a signature using this [`SecretKey`]
pub fn sign(&self, msg: &[u8]) -> Signature {
let hash_point = hash::hash_to_g1(msg);
let sig = hash_point.mul(self.0);
let (msg_point, _) = hash::hash_to_point(msg);
let sig = msg_point.mul(self.0);
Signature(sig)
}
}
Expand Down Expand Up @@ -130,10 +130,10 @@ impl Signature {
/// This optimization is needed for ensuring that tests can run within a reasonable time frame.
#[inline(never)]
pub fn verify(&self, msg: &[u8], pk: &PublicKey) -> Result<(), Error> {
let hash_point = hash::hash_to_g1(msg);
let (msg_point, _) = hash::hash_to_point(msg);

// First pair: e(H(m): G1, pk: G2)
let a = Bn256::pairing(hash_point, pk.0);
let a = Bn256::pairing(msg_point, pk.0);
// Second pair: e(sig: G1, generator: G2)
let b = Bn256::pairing(self.0, G2Affine::one());

Expand Down Expand Up @@ -203,7 +203,8 @@ impl AggregateSignature {
// Second pair: e(H(m1): G1, pk1: G2) * ... * e(H(m1000): G1, pk1000: G2)
let mut b = Fq12::one();
for (msg, pk) in pairs {
b.mul_assign(&Bn256::pairing(hash::hash_to_g1(msg), pk.0))
let (msg_point, _) = hash::hash_to_point(msg);
b.mul_assign(&Bn256::pairing(msg_point, pk.0))
}

if a == b {
Expand Down

0 comments on commit f19333c

Please sign in to comment.