use crate::MultiSignature;
use bn::{arith, pairing_batch, AffineG1, AffineG2, Fq, Fq2, Fr, Group, Gt, G1, G2};
use byteorder::{BigEndian, ByteOrder};
use digest::Digest;
pub mod error;
use error::Error;
pub struct Bn256;
impl Bn256 {
fn arbitrary_string_to_g1(&self, data: &[u8]) -> Result<G1, Error> {
let mut v = vec![0x02];
v.extend(data);
let point = G1::from_compressed(&v)?;
Ok(point)
}
fn hash_to_try_and_increment(&self, message: &[u8]) -> Result<G1, Error> {
let mut c = 0..255;
let mut v = [&message[..], &[0x00]].concat();
let position = v.len() - 1;
let point = c.find_map(|ctr| {
v[position] = ctr;
let attempted_hash = self.calculate_sha256(&v);
self.arbitrary_string_to_g1(&attempted_hash).ok()
});
point.ok_or(Error::HashToPointError)
}
fn to_compressed_g1(&self, point: G1) -> Result<Vec<u8>, Error> {
let affine_coords = AffineG1::from_jacobian(point).ok_or(Error::PointInJacobian)?;
let x = Fq::into_u256(affine_coords.x());
let y = Fq::into_u256(affine_coords.y());
let parity = y.get_bit(0).ok_or(Error::IndexOutOfBounds)?;
let mut s = [0u8; 32];
x.to_big_endian(&mut s)?;
let mut result: Vec<u8> = Vec::new();
result.push(if parity { 3 } else { 2 });
result.append(&mut s.to_vec());
Ok(result)
}
fn calculate_sha256(&self, bytes: &[u8]) -> [u8; 32] {
let mut hasher = sha2::Sha256::new();
hasher.input(&bytes);
let mut hash = [0; 32];
hash.copy_from_slice(&hasher.result());
hash
}
}
pub struct PrivateKey(bn::Fr);
pub struct PublicKey(bn::G2);
impl PrivateKey {
pub fn new(rng: &[u8]) -> Result<PrivateKey, Error> {
let private_key = Fr::from_slice(&rng)?;
Ok(PrivateKey(private_key))
}
pub fn to_bytes(&self) -> Result<Vec<u8>, Error> {
let mut result: [u8; 32] = [0; 32];
self.0.into_u256().to_big_endian(&mut result)?;
Ok(result.to_vec())
}
pub fn derive_public_key(self) -> Result<PublicKey, Error> {
let PrivateKey(sk) = self;
Ok(PublicKey(G2::one() * sk))
}
}
impl PublicKey {
pub fn to_u512(&self, coord: Fq2) -> arith::U512 {
let c0: arith::U256 = (coord.real()).into_u256();
let c1: arith::U256 = (coord.imaginary()).into_u256();
arith::U512::new(&c1, &c0, &Fq::modulus())
}
pub fn from_compressed(bytes: &[u8]) -> Result<Self, Error> {
let uncompressed = G2::from_compressed(&bytes)?;
Ok(PublicKey(uncompressed))
}
pub fn from_uncompressed(bytes: &[u8]) -> Result<Self, Error> {
if bytes.len() != 128 {
return Err(Error::InvalidLength {});
}
let x = Fq2::new(
Fq::from_slice(&bytes[0..32])?,
Fq::from_slice(&bytes[32..64])?,
);
let y = Fq2::new(
Fq::from_slice(&bytes[64..96])?,
Fq::from_slice(&bytes[96..128])?,
);
let pub_key = AffineG2::new(x, y)?;
Ok(PublicKey(pub_key.into()))
}
pub fn to_compressed(&self) -> Result<Vec<u8>, Error> {
let modulus = Fq::modulus();
let affine_coords = AffineG2::from_jacobian(self.0).ok_or(Error::PointInJacobian)?;
let x_real = Fq::into_u256(affine_coords.x().real());
let x_imaginary = Fq::into_u256(affine_coords.x().imaginary());
let y = affine_coords.y();
let y_neg = -y;
let sign: u8 = if self.to_u512(y) > self.to_u512(y_neg) {
0x0b
} else {
0x0a
};
let compressed = arith::U512::new(&x_imaginary, &x_real, &modulus);
let mut buf: [u8; 64] = [0; (4 * 16)];
for (l, i) in (0..4).rev().zip((0..4).map(|i| i * 16)) {
BigEndian::write_u128(&mut buf[i..], compressed.0[l]);
}
let mut result: Vec<u8> = Vec::new();
result.push(sign);
result.append(&mut buf.to_vec());
Ok(result)
}
pub fn to_uncompressed(&self) -> Result<Vec<u8>, Error> {
let affine_coords = AffineG2::from_jacobian(self.0).ok_or(Error::PointInJacobian)?;
let mut result: [u8; 32 * 4] = [0; (4 * 32)];
Fq::into_u256(affine_coords.x().real()).to_big_endian(&mut result[0..32])?;
Fq::into_u256(affine_coords.x().imaginary()).to_big_endian(&mut result[32..64])?;
Fq::into_u256(affine_coords.y().real()).to_big_endian(&mut result[64..96])?;
Fq::into_u256(affine_coords.y().imaginary()).to_big_endian(&mut result[96..128])?;
Ok(result.to_vec())
}
}
impl MultiSignature<&[u8], &[u8], &[u8]> for Bn256 {
type Error = Error;
fn derive_public_key(&mut self, secret_key: &[u8]) -> Result<Vec<u8>, Error> {
let scalar = Fr::from_slice(&secret_key[0..32])?;
let key = PrivateKey(scalar);
let public = key.derive_public_key()?;
public.to_compressed()
}
fn sign(&mut self, secret_key: &[u8], message: &[u8]) -> Result<Vec<u8>, Self::Error> {
let hash_point = self.hash_to_try_and_increment(&message)?;
let sk = Fr::from_slice(&secret_key)?;
let signature = hash_point * sk;
self.to_compressed_g1(signature)
}
fn verify(
&mut self,
signature: &[u8],
message: &[u8],
public_key: &[u8],
) -> Result<(), Self::Error> {
let mut vals = Vec::new();
let hash_point = self.hash_to_try_and_increment(&message)?;
let public_key_point = G2::from_compressed(&public_key)?;
vals.push((hash_point, public_key_point));
let signature_point = G1::from_compressed(&signature)?;
vals.push((signature_point, -G2::one()));
let mul = pairing_batch(&vals);
if mul == Gt::one() {
Ok(())
} else {
Err(Error::VerificationFailed)
}
}
fn aggregate_public_keys(&mut self, public_keys: &[&[u8]]) -> Result<Vec<u8>, Self::Error> {
let agg_public_key: Result<G2, Error> =
public_keys.iter().try_fold(G2::zero(), |acc, &compressed| {
let public_key = PublicKey::from_compressed(&compressed)?;
Ok(acc + public_key.0)
});
PublicKey(agg_public_key?).to_compressed()
}
fn aggregate_signatures(&mut self, signatures: &[&[u8]]) -> Result<Vec<u8>, Self::Error> {
let agg_signatures: Result<G1, Error> =
signatures.iter().try_fold(G1::zero(), |acc, &compressed| {
let signature = G1::from_compressed(&compressed)?;
Ok(acc + signature)
});
self.to_compressed_g1(agg_signatures?)
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_valid_private_key() {
let compressed =
hex::decode("023aed31b5a9e486366ea9988b05dba469c6206e58361d9c065bbea7d928204a")
.unwrap();
let private_key = PrivateKey::new(&compressed.as_slice());
assert_eq!(private_key.is_err(), false);
assert_eq!(private_key.unwrap().to_bytes().unwrap(), compressed);
}
#[test]
fn test_invalid_private_key_1() {
let compressed = hex::decode("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa").unwrap();
let private_key = PrivateKey::new(&compressed.as_slice());
assert_eq!(private_key.is_err(), true);
}
#[test]
fn test_invalid_private_key_2() {
let compressed = hex::decode("aaaa").unwrap();
let private_key = PrivateKey::new(&compressed.as_slice());
assert_eq!(private_key.is_err(), true);
}
#[test]
fn test_compressed_public_key_1() {
let compressed = hex::decode("0a023aed31b5a9e486366ea9988b05dba469c6206e58361d9c065bbea7d928204a761efc6e4fa08ed227650134b52c7f7dd0463963e8a4bf21f4899fe5da7f984a").unwrap();
let public_key = PublicKey::from_compressed(&compressed).unwrap();
let compressed_again = public_key.to_compressed().unwrap();
assert_eq!(compressed, compressed_again);
}
#[test]
fn test_to_public_key_1() {
let secret_key =
hex::decode("1ab1126ff2e37c6e6eddea943ccb3a48f83b380b856424ee552e113595525565")
.unwrap();
let expected = hex::decode(
"28fe26becbdc0384aa67bf734d08ec78ecc2330f0aa02ad9da00f56c37907f78\
2cd080d897822a95a0fb103c54f06e9bf445f82f10fe37efce69ecb59514abc8\
237faeb0351a693a45d5d54aa9759f52a71d76edae2132616d6085a9b2228bf9\
0f46bd1ef47552c3089604c65a3e7154e3976410be01149b60d5a41a6053e6c2",
)
.unwrap();
let mut curve = Bn256 {};
let public_key = curve.derive_public_key(&secret_key).unwrap();
let g2 = G2::from_compressed(&public_key).unwrap();
let expected_g2 = PublicKey::from_uncompressed(&expected).unwrap();
let uncompressed_slice = expected_g2.to_uncompressed().unwrap();
assert_eq!(uncompressed_slice, expected);
assert_eq!(g2, expected_g2.0);
}
#[test]
fn test_to_public_key_2() {
let secret_key =
hex::decode("2009da7287c158b126123c113d1c85241b6e3294dd75c643588630a8bc0f934c")
.unwrap();
let expected = hex::decode(
"1cd5df38ed2f184b9830bfd3c2175d53c1455352307ead8cbd7c6201202f4aa8\
02ce1c4241143cc61d82589c9439c6dd60f81fa6f029625d58bc0f2e25e4ce89\
0ba19ae3b5a298b398b3b9d410c7e48c4c8c63a1d6b95b098289fbe1503d00fb\
2ec596e93402de0abc73ce741f37ed4984a0b59c96e20df8c9ea1c4e6ec04556",
)
.unwrap();
let mut curve = Bn256 {};
let public_key = curve.derive_public_key(&secret_key).unwrap();
let g2 = G2::from_compressed(&public_key).unwrap();
let expected_g2 = PublicKey::from_uncompressed(&expected).unwrap();
let uncompressed_slice = expected_g2.to_uncompressed().unwrap();
assert_eq!(uncompressed_slice, expected);
assert_eq!(g2, expected_g2.0);
}
#[test]
fn test_to_public_key_3() {
let secret_key =
hex::decode("26fb4d661491b0a623637a2c611e34b6641cdea1743bee94c17b67e5ef14a550")
.unwrap();
let expected = hex::decode(
"077dfcf14e940b69bf88fa1ad99b6c7e1a1d6d2cb8813ac53383bf505a17f8ff\
2d1a9b04a2c5674373353b5a25591292e69c37c0b84d9ef1c780a57bb98638e6\
2dc52f109b333c4125bccf55bc3a839ce57676514405656c79e577e231519273\
2410eee842807d9325f22d087fa6bc79d9bbea07f5fa8c345e1e57b28ad54f84",
)
.unwrap();
let public_key = Bn256.derive_public_key(&secret_key).unwrap();
let g2 = G2::from_compressed(&public_key).unwrap();
let expected_g2 = PublicKey::from_uncompressed(&expected).unwrap();
let uncompressed_slice = expected_g2.to_uncompressed().unwrap();
assert_eq!(uncompressed_slice, expected);
assert_eq!(g2, expected_g2.0);
}
#[test]
fn test_to_public_key_4() {
let secret_key =
hex::decode("0f6b8785374476a3b3e4bde2c64dfb12964c81c7930d32367c8e318609387872")
.unwrap();
let public_key = Bn256.derive_public_key(&secret_key).unwrap();
let expected = hex::decode(
"270567a05b56b02e813281d554f46ce0c1b742b622652ef5a41d69afb6eb8338\
1bab5671c5107de67fe06007dde240a84674c8ff13eeac6d64bad0caf2cfe53e\
0142f4e04fc1402e17ae7e624fd9bd15f1eae0a1d8eda4e26ab70fd4cd793338\
02b54a5deaaf86dc7f03d080c8373d62f03b3be06dac42b2d9426a8ebd0caf4a",
)
.unwrap();
let g2 = G2::from_compressed(&public_key).unwrap();
let expected_g2 = PublicKey::from_uncompressed(&expected).unwrap();
let uncompressed_slice = expected_g2.to_uncompressed().unwrap();
assert_eq!(uncompressed_slice, expected);
assert_eq!(g2, expected_g2.0);
}
#[test]
fn test_hash_to_try_and_increment_1() {
let data = hex::decode("73616d706c65").unwrap();
let hash_point = Bn256.hash_to_try_and_increment(&data).unwrap();
let hash_bytes = Bn256.to_compressed_g1(hash_point).unwrap();
let expected_hash = "022f314aad50eb30c15d7e61c0f99874a6aa0d773a5a9f4262b1cda997e3c8da07";
assert_eq!(hex::encode(hash_bytes), expected_hash);
}
#[test]
fn test_sign_1() {
let secret_key =
hex::decode("2009da7287c158b126123c113d1c85241b6e3294dd75c643588630a8bc0f934c")
.unwrap();
let data = hex::decode("73616d706c65").unwrap();
let signature = Bn256.sign(&secret_key, &data).unwrap();
let expected_signature =
"031a2752fd966c0f24ccaa684aa0c303f430e56cf9e0917d8d2841b2a83488cbba";
assert_eq!(hex::encode(signature), expected_signature);
}
#[test]
fn test_verify_signed_msg() {
let secret_key =
hex::decode("2009da7287c158b126123c113d1c85241b6e3294dd75c643588630a8bc0f934c")
.unwrap();
let public_key = Bn256.derive_public_key(&secret_key).unwrap();
let signature =
hex::decode("031a2752fd966c0f24ccaa684aa0c303f430e56cf9e0917d8d2841b2a83488cbba")
.unwrap();
let msg = hex::decode("73616d706c65").unwrap();
assert!(
Bn256.verify(&signature, &msg, &public_key).is_ok(),
"Verification failed"
);
}
#[test]
fn test_aggregate_public_keys_1() {
let public_key_1 = PublicKey(G2::one()).to_compressed().unwrap();
let public_key_2 = PublicKey(G2::one()).to_compressed().unwrap();
let public_keys = [&public_key_1[..], &public_key_2[..]];
let agg_public_key = Bn256.aggregate_public_keys(&public_keys).unwrap();
let expected = hex::decode("0b061848379c6bccd9e821e63ff6932738835b78e1e10079a0866073eba5b8bb444afbb053d16542e2b839477434966e5a9099093b6b3351f84ac19fe28f096548").unwrap();
assert_eq!(agg_public_key, expected);
}
#[test]
fn test_aggregate_signatures_1() {
let sign_1 = Bn256.to_compressed_g1(G1::one()).unwrap();
let sign_2 = Bn256.to_compressed_g1(G1::one()).unwrap();
let signatures = [&sign_1[..], &sign_2[..]];
let agg_signature = Bn256
.aggregate_signatures(&signatures)
.expect("Signature aggregation should not fail if G1 points are valid.");
let expected =
hex::decode("02030644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd3")
.unwrap();
assert_eq!(agg_signature, expected);
}
#[test]
fn test_verify_aggregated_signatures_1() {
let msg = hex::decode("73616d706c65").unwrap();
let secret_key1 =
hex::decode("1ab1126ff2e37c6e6eddea943ccb3a48f83b380b856424ee552e113595525565")
.unwrap();
let public_key1 = Bn256.derive_public_key(&secret_key1).unwrap();
let sign_1 = Bn256.sign(&secret_key1, &msg).unwrap();
let secret_key2 =
hex::decode("2009da7287c158b126123c113d1c85241b6e3294dd75c643588630a8bc0f934c")
.unwrap();
let public_key2 = Bn256.derive_public_key(&secret_key2).unwrap();
let sign_2 = Bn256.sign(&secret_key2, &msg).unwrap();
let agg_public_key = Bn256
.aggregate_public_keys(&[&public_key1, &public_key2])
.unwrap();
let agg_signature = Bn256.aggregate_signatures(&[&sign_1, &sign_2]).unwrap();
assert!(
Bn256.verify(&sign_1, &msg, &public_key1).is_ok(),
"Signature 1 verification failed"
);
assert!(
Bn256.verify(&sign_2, &msg, &public_key2).is_ok(),
"Signature 2 signature verification failed"
);
assert!(
Bn256.verify(&agg_signature, &msg, &agg_public_key).is_ok(),
"Aggregated signature verification failed"
);
}
}