Skip to content

Commit

Permalink
Fix BLS signature (#174)
Browse files Browse the repository at this point in the history
This PR changes the signature of `sign_message` to:
``` rust
pub fn sign_message(&self, message: &[u8; 32]) -> Signature
```

and fixes the implementation of map_to_curve. There was a minor bug in
the parsing of the input (endianness mismatch).
  • Loading branch information
pablodeymo authored Dec 11, 2024
1 parent 475a852 commit d716fc0
Show file tree
Hide file tree
Showing 6 changed files with 64 additions and 16 deletions.
2 changes: 1 addition & 1 deletion 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 crates/crypto/bls/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@ ark-std = { version = "0.4.0", default-features = false }
serde.workspace = true
eigen-crypto-bn254.workspace = true
eigen-utils.workspace = true

[dev-dependencies]
eigen-testing-utils.workspace = true
rand = "0.8.4"
tokio = { workspace = true, features = ["full"] }
serde_json.workspace = true
52 changes: 51 additions & 1 deletion crates/crypto/bls/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ impl BlsKeyPair {
Signature::new(r.into_affine())
}

pub fn sign_message(&self, message: &[u8]) -> Signature {
pub fn sign_message(&self, message: &[u8; 32]) -> Signature {
let g1 = map_to_curve(message);
let sk_int: BigInteger256 = self.priv_key.into();
let r = g1.mul_bigint(sk_int);
Expand Down Expand Up @@ -375,6 +375,8 @@ mod tests {
use super::*;
use ark_bn254::Fq2;
use eigen_crypto_bn254::utils::verify_message;
use eigen_testing_utils::test_data::TestData;
type Fp = ark_ff::Fp<ark_ff::MontBackend<ark_bn254::FqConfig, 4>, 4>;

#[test]
fn test_convert_to_g1_point() {
Expand Down Expand Up @@ -677,4 +679,52 @@ mod tests {
"The deserialized point does not match the original"
);
}

#[test]
fn test_bls_signature() {
#[derive(Deserialize, Debug)]
struct Input {
message_bytes: String,
bls_priv_key: String,
}

let test_data = TestData::new(Input {
message_bytes: "Hello, world!Hello, world!123456".to_string(),
bls_priv_key:
"12248929636257230549931416853095037629726205319386239410403476017439825112537"
.to_string(),
});

let message_bytes: &[u8; 32] = test_data.input.message_bytes.as_bytes().try_into().unwrap();
let bls_priv_key = test_data.input.bls_priv_key;
let bls_key_pair = BlsKeyPair::new(bls_priv_key).unwrap();
let signature = bls_key_pair.sign_message(message_bytes);

let g1_point = signature.g1_point().g1();
let x = g1_point.x().unwrap();
let y = g1_point.y().unwrap();

// assert x and y with the values obtained in Go SDK
assert_eq!(
x,
Fp::from_bigint(
BigInt::from_str(
"15790168376429033610067099039091292283117017641532256477437243974517959682102",
)
.unwrap()
)
.unwrap()
);

assert_eq!(
y,
Fp::from_bigint(
BigInt::from_str(
"4960450323239587206117776989095741074887370703941588742100855592356200866613",
)
.unwrap()
)
.unwrap()
);
}
}
1 change: 0 additions & 1 deletion crates/crypto/bn254/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ license-file.workspace = true
ark-bn254.workspace = true
ark-ec.workspace = true
ark-ff.workspace = true
num-bigint.workspace = true
rust-bls-bn254.workspace = true


Expand Down
15 changes: 3 additions & 12 deletions crates/crypto/bn254/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,27 +4,18 @@ use ark_ff::{
fields::{Field, PrimeField},
One,
};
use num_bigint::BigUint;
use rust_bls_bn254::pairing;

/// MapToCurve implements the simple hash-and-check (also sometimes try-and-increment) algorithm
/// see https://hackmd.io/@benjaminion/bls12-381#Hash-and-check
/// Note that this function needs to be the same as the one used in the contract:
/// https://github.com/Layr-Labs/eigenlayer-middleware/blob/1feb6ae7e12f33ce8eefb361edb69ee26c118b5d/src/libraries/BN254.sol#L292
/// we don't use the newer constant time hash-to-curve algorithms as they are gas-expensive to compute onchain
pub fn map_to_curve(digest: &[u8]) -> G1Affine {
pub fn map_to_curve(bytes: &[u8; 32]) -> G1Affine {
let one = Fq::one();
let three = Fq::from(3u64);
let big_int = BigUint::from_bytes_be(digest);
let mut bytes = [0u8; 32];
big_int
.to_bytes_be()
.iter()
.rev()
.enumerate()
.for_each(|(i, &b)| bytes[i] = b);

let mut x = Fq::from_le_bytes_mod_order(&bytes);
let mut x = Fq::from_be_bytes_mod_order(bytes);

loop {
// y = x^3 + 3
Expand All @@ -44,7 +35,7 @@ pub fn map_to_curve(digest: &[u8]) -> G1Affine {
}

/// Verifies message on G2
pub fn verify_message(public_key: G2Affine, message: &[u8], signature: G1Affine) -> bool {
pub fn verify_message(public_key: G2Affine, message: &[u8; 32], signature: G1Affine) -> bool {
if !signature.is_in_correct_subgroup_assuming_on_curve() || !signature.is_on_curve() {
return false;
}
Expand Down
8 changes: 7 additions & 1 deletion crates/services/bls_aggregation/src/bls_agg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -636,9 +636,15 @@ impl<A: AvsRegistryService + Send + Sync + Clone + 'static> BlsAggregatorService
return Err(SignatureVerificationError::OperatorPublicKeyNotFound);
};

let message = signed_task_response_digest
.task_response_digest
.as_slice()
.try_into()
.map_err(|_| SignatureVerificationError::IncorrectSignature)?;

verify_message(
pub_keys.g2_pub_key.g2(),
signed_task_response_digest.task_response_digest.as_slice(),
message,
signed_task_response_digest.bls_signature.g1_point().g1(),
)
.then_some(())
Expand Down

0 comments on commit d716fc0

Please sign in to comment.