Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Skalman pok new interface #29

Merged
merged 37 commits into from
Feb 9, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
fa93daf
Initial signing implementation stuck at pairing upgrade kerfuffle
drskalman Sep 24, 2020
ba6a26f
Moving from paired to zexe/algebra-core as the pairing provider
drskalman Sep 25, 2020
82ef141
Introduced PublicKeyPrepared and SignaturePrepared types.
drskalman Sep 29, 2020
db8147f
Publickey/SignaturePrepared types added to the engine. Still needs
drskalman Oct 22, 2020
54f9808
Reintroducing Base fields to EngineBLS.
drskalman Oct 22, 2020
ec0106c
commented out single and verification etc just to make engine to compile
drskalman Oct 29, 2020
42b6e23
Simplifying EngineBLS functions due to change in miller loop args type
drskalman Nov 12, 2020
5f193aa
Resolve From not implemented in single.rs and other errors
drskalman Nov 12, 2020
cf94ee1
*_assign
burdges Nov 15, 2020
8d44845
single.rs upgraded to use zexe and compiles.
drskalman Nov 17, 2020
3839aa6
re-include verifier.rs and replace old affine prepared called
drskalman Nov 23, 2020
881516f
`verify_with_distinct_messages` migrated
drskalman Nov 23, 2020
78b6b2b
verifier.rs now compiles depending on zexe
drskalman Nov 24, 2020
c004245
`bit.rs`, `pop.rs` and `distinct.rs` moved to zexe backend
drskalman Nov 24, 2020
6356a8b
port `delinear.rs` successfully to zexe backend and the whole library…
drskalman Nov 30, 2020
44ebfab
Move 'TinyBLS' to zexe backend
drskalman Nov 30, 2020
684df14
Add macro which implement de/serialization for Signature and PublicKe…
drskalman Dec 4, 2020
da4ce55
Move zbls macros to new serialization paradaigm, `cargo test` compiles
drskalman Dec 7, 2020
acc3b73
Fix the bug for over-allocating the serialization vector in signle
drskalman Dec 10, 2020
a482de8
Merge branch 'skalman-zexe-unprepared-serialized' into skalman-schnor…
drskalman Dec 10, 2020
3821a36
Fix wrong constant hash to curve function
drskalman Dec 10, 2020
2004a0d
Merge branch 'skalman-zexe-unprepared-serialized' into skalman-schnor…
drskalman Dec 11, 2020
ed5223d
Resolved all errors for sign_pok with test except for 1
drskalman Dec 11, 2020
e07e15a
Resolve type specification error (courtesy of @lamafab )
drskalman Dec 11, 2020
7e2aaa3
Change BLSSchnoorProof structure and implement test_verify_pok
drskalman Dec 28, 2020
d54a09f
Fix pok signing error by zeroing high bits of randomness
drskalman Jan 2, 2021
2281381
break PoK operation in to two traits
drskalman Jan 2, 2021
a8761d8
pass schnorr PoP verification test
drskalman Jan 4, 2021
628c61e
break PoK operation in to two traits
drskalman Jan 2, 2021
76873f5
Adapt `bls_pop` to new model and make tests pass
drskalman Jan 8, 2021
f4d137c
Merge branch 'skalman-pok-new-interface' of https://github.com/w3f/bl…
drskalman Jan 8, 2021
b6ba31d
add the ability of using arbitary message to produce the PoP of a
drskalman Jan 11, 2021
5460394
add message for when countsig fails
drskalman Jan 22, 2021
5db35d3
clean Cargo.toml and replace double with double_in_place in bit.rs in
drskalman Feb 1, 2021
e90d26e
Moving from Zexe to Arkwork, there is still problem with serialization
drskalman Feb 4, 2021
8b319e3
- Resolve error due to dependacy moved from Zexe to Arkworks
drskalman Feb 5, 2021
2713cd1
Get rid of all warnings!
drskalman Feb 8, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 27 additions & 16 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,37 +1,48 @@
[package]
authors = ["Jack Grigg <[email protected]>", "Jeff Burdges <[email protected]>"]
authors = ["Jack Grigg <[email protected]>", "Jeff Burdges <[email protected]>", "Syed Hosseini <[email protected]>"]
description = "Aggregate BLS-like signatures"
documentation = "https://docs.rs/bls-like"
homepage = "https://github.com/w3f/bls"
license = "MIT/Apache-2.0"
name = "bls-like"
repository = "https://github.com/w3f/bls"
version = "0.1.0"
edition = "2018"

[dependencies]
arrayref = "0.3"
rand = "0.4"
ff = { version = "0.4", features = ["derive"] }
rand = "0.7"
rand_core = "0.5"
rand_chacha = "0.2"
sha3 = "0.8"
sha2 = "0.9.2"
digest = "0.9.0"

# [dependencies.merlin]
# version = "1.1.0"
## features = ["debug-transcript"]
#arkwork dependencies
ark-ff = { git = "https://github.com/arkworks-rs/algebra", default-features = false }
ark-ec = { git = "https://github.com/arkworks-rs/algebra", default-features = false }
ark-serialize-derive = { package = "ark-serialize-derive", git = "https://github.com/arkworks-rs/algebra" }
ark-serialize = { git = "https://github.com/arkworks-rs/algebra", default-features = false, features = [ "derive" ] }
ark-bls12-381 = { git = "https://github.com/arkworks-rs/curves", default-features = false, features = [ "curve" ] }

[dependencies.paired]
version = "0.15"
# git = "https://github.com/filecoin-project/pairing"

# [dependencies.pairing]
# git = "https://github.com/burdges/pairing"
# branch = "master-hashing-derives_borrows_etc0"
## historical:
## branch = "derives_borrows_etc0"
## git = "https://github.com/mmaker/pairing"
## branch = "master"
# algebra-core = { git = "https://github.com/scipr-lab/zexe" }
# algebra-serialize-derive = { package = "ark-serialize-derive", git = "https://github.com/arkworks-rs/algebra" }
# algebra = { git = "https://github.com/scipr-lab/zexe", features = ["bls12_381"] }

#for cleaning up secret keys
[dependencies.zeroize]
version = "1.0.0"
default-features = false
features = ["zeroize_derive"]

[dependencies.serde]
version = "^1.0"
default-features = false
optional = true

[dev-dependencies]
rand= "0.7.3"

[dependencies.thiserror]
version = "1.0.10"
28 changes: 16 additions & 12 deletions src/bit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@


use std::borrow::{Borrow,BorrowMut};
use std::iter::{once}; // FromIterator
use std::iter::{once};

use pairing::{CurveProjective}; // CurveAffine, Engine
use ark_ff::{Zero};
use ark_ec::ProjectiveCurve;

use super::*;
use super::single::SignedMessage;
Expand Down Expand Up @@ -208,7 +209,7 @@ where
debug_assert!(false, "Incorrect SignerTable implementation with duplicate publickeys" );
continue;
}
publickey.add_assign(&pop_pk.0);
publickey += &pop_pk.0;
}
}
once((self.message.clone(), PublicKey(publickey)))
Expand Down Expand Up @@ -247,7 +248,7 @@ where
let s = &mut self.signers.borrow_mut()[i / 8];
if *s & b != 0 { return Err(SignerTableError::RepeatedSigners); }
*s |= b;
self.signature.0.add_assign(&signature.0);
self.signature.0 += &signature.0;
Ok(())
}

Expand Down Expand Up @@ -279,7 +280,7 @@ where
for (x,y) in self.signers.borrow_mut().iter_mut().zip(other.signers.borrow()) {
*x |= y;
}
self.signature.0.add_assign(&other.signature.0);
self.signature.0 += &other.signature.0;
Ok(())
}
}
Expand Down Expand Up @@ -338,7 +339,7 @@ where
fn messages_and_publickeys(self) -> Self::PKnM {
let mut publickey = E::PublicKeyGroup::zero();
for signers in self.signers.iter().rev().map(|signers| signers.borrow()) {
publickey.double();
publickey.double_in_place();
for i in 0..8*signers.len() {
if signers[i / 8] & (1 << (i % 8)) != 0 {
let pop_pk = self.proofs_of_possession.lookup(i).unwrap();
Expand All @@ -347,7 +348,7 @@ where
debug_assert!(false, "Incorrect SignerTable implementation with duplicate publickeys" );
continue;
}
publickey.add_assign(&pop_pk.0);
publickey += &pop_pk.0;
}
}
}
Expand Down Expand Up @@ -397,11 +398,14 @@ where
}
}

/*
commented out to rid of unused warning
TODO: add test coverage to trim and uncomment
fn trim(&mut self) {
let empty = |s: &POP::Signers| s.borrow().iter().all(|b| *b == 0u8);
let c = self.signers.len() - self.signers.iter().rev().take_while(|s| empty(&*s)).count();
self.signers.truncate(c)
}
}*/

fn test_count(&self, count: usize) -> Result<(),SignerTableError> {
if count >= self.max_duplicates || count >= usize::max_value() {
Expand Down Expand Up @@ -446,7 +450,7 @@ where
let count = self.get_count(i) + 1;
self.test_count(count) ?;
self.set_count(i,count);
self.signature.0.add_assign(&signature.0);
self.signature.0 += &signature.0;
Ok(())
}

Expand Down Expand Up @@ -485,7 +489,7 @@ where
let count = self.get_count(index);
if os[index / 8] & (1 << (index % 8)) != 0 { self.set_count(index,count+1); }
}
self.signature.0.add_assign(&other.signature.0);
self.signature.0 += &other.signature.0;
Ok(())
}

Expand All @@ -512,7 +516,7 @@ where
for index in 0..8*self.signers[0].borrow().len() {
self.set_count(index, self.get_count(index) + other.get_count(index));
}
self.signature.0.add_assign(&other.signature.0);
self.signature.0 += &other.signature.0;
Ok(())
}
}
Expand Down Expand Up @@ -595,7 +599,7 @@ mod tests {
assert!( countsig.verify() );
for (i,sig) in sigs1.iter().enumerate().take(3) {
assert!( countsig.add(sig).is_ok() == (i<4));
assert!( countsig.verify() ); // verifiers::verify_with_distinct_messages(&dms,true)
assert!( countsig.verify(), "countsig failed at sig {}",i ); // verifiers::verify_with_distinct_messages(&dms,true)
}
assert!( countsig.add_bitsig(&bitsig1a).is_ok() );
assert!( countsig.add_bitsig(&bitsig1a).is_ok() );
Expand Down
155 changes: 155 additions & 0 deletions src/bls_pop.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
//! ## Implementation of ProofofPossion trait for BLS keys using schnorr sginature
//! ## TODO: I assume this can also moved to pop.rs but for now I put it separately to help reviews
use crate::engine::{EngineBLS};
use crate::pop::{ProofOfPossessionGenerator, ProofOfPossessionVerifier, SchnorrProof};

use crate::single::{SecretKey,PublicKey};

use digest::{Digest};

use ark_serialize::{CanonicalSerialize};
use ark_ec::ProjectiveCurve;

use ark_ff::bytes::{FromBytes, ToBytes};

use super::Message;

// TODO: Delete after migration to secret key model
// pub struct BLSSchnorrProof<E: EngineBLS> : trait B: {
// pub public_key : PublicKey<E>,
// pub proof_of_possession : SchnorrProof<E>,
// }

/// Generate Schnorr Signature for an arbitrary message using a key ment to use in BLS scheme
trait BLSSchnorrPoPGenerator<E: EngineBLS, H: Digest> : ProofOfPossessionGenerator<E,H> {
/// Produce a secret witness scalar `k`, aka nonce, from hash of
/// H( H(s) | H(public_key)) because our key does not have the
/// randomness redundacy exists in EdDSA secret key.
fn witness_scalar(&self) -> <<E as EngineBLS>::PublicKeyGroup as ProjectiveCurve>::ScalarField;
}

impl<E: EngineBLS, H: Digest> BLSSchnorrPoPGenerator<E,H> for SecretKey<E>
{
/// TODO: BROKEN NOW Switch to https://github.com/arkworks-rs/algebra/pull/164/files
fn witness_scalar(&self) -> <<E as EngineBLS>::PublicKeyGroup as ProjectiveCurve>::ScalarField {
let mut secret_key_as_bytes = vec![0; self.into_vartime().0.serialized_size()];

let affine_public_key = self.into_public().0.into_affine();
let mut public_key_as_bytes = vec![0; affine_public_key.serialized_size()];

self.into_vartime().0.serialize(&mut secret_key_as_bytes[..]).unwrap();
affine_public_key.serialize(&mut public_key_as_bytes[..]).unwrap();

let secret_key_hash = <H as Digest>::new().chain(secret_key_as_bytes);
let public_key_hash = <H as Digest>::new().chain(public_key_as_bytes);

let mut scalar_bytes = <H as Digest>::new().chain(secret_key_hash.finalize()).chain(public_key_hash.finalize()).finalize();
let random_scalar : &mut [u8] = scalar_bytes.as_mut_slice();
random_scalar[31] &= 31; // BROKEN HACK DO BOT DEPLOY
<<<E as EngineBLS>::PublicKeyGroup as ProjectiveCurve>::ScalarField as FromBytes>::read(&*random_scalar).unwrap()
}

}

impl<E: EngineBLS, H: Digest> ProofOfPossessionGenerator<E,H> for SecretKey<E> {

fn generate_pok(&self, message: Message) -> SchnorrProof<E> {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm tempted to use a transcript abstraction instead of Message like in schnorrkel, ring-vrf, and now the apk crate. Message made sense for BLS signatures message. And maybe still does. I do not see much point in a schnorr proof.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should maybe make this PoK do both G1 and G2 if we're going that route, no? I guess that's a seperate thing that depends upon only Engine. Ugh.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Made issues #30 and #31 to follow up with these.

//First we should figure out the base point in E, I think the secret key trait/struct knows about it.

//choose random scaler k
//For now we don't we just use a trick similar to Ed25519
//we use hash of concatination of hash the secret key and the public key

//schnorr equations

//R = rG.
//k = H(R|M)
//s = k*private_key + r
// publishing (s, R) verifying that (s*G = H(R|M)*Publickey + R
// instead we actually doing H(s*G - H(R|M)*Publickey|M) == H(R|M) == k
// avoiding one curve addition in expense of a hash.
let mut r = <dyn BLSSchnorrPoPGenerator<E,H>>::witness_scalar(self);

let mut r_point = <<E as EngineBLS>::PublicKeyGroup as ProjectiveCurve>::prime_subgroup_generator();
r_point *= r; //todo perhaps we need to mandate E to have a hard coded point

let mut r_point_as_bytes = Vec::<u8>::new();
r_point.into_affine().write(&mut r_point_as_bytes).unwrap();

let mut k_as_hash = <H as Digest>::new().chain(r_point_as_bytes).chain(message.0).finalize();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

one should include the public key here.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

M was public key before but I thought we decided to replace with any arbitary message which can be public key as well. You want public key to be a mandatory part of the message?

let random_scalar : &mut [u8] = k_as_hash.as_mut_slice();
random_scalar[31] &= 31; // BROKEN HACK DO BOT DEPLOY
Copy link
Collaborator

@burdges burdges Feb 9, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

right this part.. what is the group order again? they just added hash to field, right?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes they did. It wasn't merged at the time, but I think it should have made it to the master/main now: #32 .


let k = <<<E as EngineBLS>::PublicKeyGroup as ProjectiveCurve>::ScalarField as FromBytes>::read(&*random_scalar).unwrap();
let s = (k * self.into_vartime().0) + r;

::zeroize::Zeroize::zeroize(&mut r); //clear secret key from memory

(s,k)
}
}

impl<E: EngineBLS, H: Digest> ProofOfPossessionVerifier<E,H> for PublicKey<E> {
/// verify the validity of schnoor proof for a given publick key by
/// making sure this is equal to zero
/// H(+s G - k Publkey|M) == k
fn verify_pok(&self, message: Message, schnorr_proof: SchnorrProof<E>) -> bool {
let mut schnorr_point = <<E as EngineBLS>::PublicKeyGroup as ProjectiveCurve>::prime_subgroup_generator();
schnorr_point *= schnorr_proof.0;
let mut k_public_key = self.0;
k_public_key *= -schnorr_proof.1;
schnorr_point += k_public_key;

let mut schnorr_point_as_bytes = Vec::<u8>::new();
schnorr_point.into_affine().write(&mut schnorr_point_as_bytes).unwrap();

let mut scalar_bytes = <H as Digest>::new().chain(schnorr_point_as_bytes).chain(message.0).finalize();
let random_scalar = scalar_bytes.as_mut_slice();
random_scalar[31] &= 31; // BROKEN HACK DO BOT DEPLOY

let witness_scaler = schnorr_proof.1;

<<<E as EngineBLS>::PublicKeyGroup as ProjectiveCurve>::ScalarField as FromBytes>::read(&*random_scalar).unwrap() == witness_scaler

}

}

#[cfg(test)]

mod tests {
#[test]
fn bls_pop_sign() {
use crate::pop::{ProofOfPossessionGenerator};
use crate::single::{Keypair};
use crate::engine::{ZBLS};
use crate::Message;
use rand::{thread_rng};
use sha2::Sha512;

let challenge_message = Message::new(b"ctx",b"sign this message, if you really have the secret key");
let keypair = Keypair::<ZBLS>::generate(thread_rng());
<dyn ProofOfPossessionGenerator<ZBLS, Sha512>>::generate_pok(&keypair.secret, challenge_message);
}

#[test]
fn bls_pop_sign_and_verify()
{
use rand::{thread_rng};
use sha2::Sha512;

use crate::single::{Keypair};
use crate::engine::{ZBLS};
use crate::Message;
use crate::pop::{ProofOfPossessionGenerator, ProofOfPossessionVerifier};


let challenge_message = Message::new(b"ctx",b"sign this message, if you really have the secret key");
let keypair = Keypair::<ZBLS>::generate(thread_rng());
let secret_key = keypair.secret;
let proof_pair = <dyn ProofOfPossessionGenerator<ZBLS, Sha512>>::generate_pok(&secret_key, challenge_message);
assert!(<dyn ProofOfPossessionVerifier<ZBLS, Sha512>>::verify_pok(&keypair.public, challenge_message, proof_pair), "valid pok does not verify")

}

}
Loading