Add nonce_generate test with test vectors (#149)

* add TestVectors struct

* add nonce_generate test
This commit is contained in:
Conrado Gouvea 2022-10-25 14:24:45 -03:00 committed by GitHub
parent d50cb30d23
commit 5e25bf52eb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 70 additions and 26 deletions

View File

@ -31,12 +31,21 @@ where
where
R: CryptoRng + RngCore,
{
let mut k_enc = [0; 32];
rng.fill_bytes(&mut k_enc[..]);
let mut random_bytes = [0; 32];
rng.fill_bytes(&mut random_bytes[..]);
Self::nonce_generate_from_random_bytes(secret, random_bytes)
}
/// Generates a nonce from the given random bytes.
/// This function allows testing and MUST NOT be made public.
pub(crate) fn nonce_generate_from_random_bytes(
secret: &SigningShare<C>,
random_bytes: [u8; 32],
) -> Self {
let secret_enc = <<C::Group as Group>::Field as Field>::serialize(&secret.0);
let input: Vec<u8> = k_enc
let input: Vec<u8> = random_bytes
.iter()
.chain(secret_enc.as_ref().iter())
.cloned()

View File

@ -10,23 +10,26 @@ use crate::{
Ciphersuite, Field, Group, Scalar, VerifyingKey,
};
/// Test vectors for a ciphersuite.
pub struct TestVectors<C: Ciphersuite> {
secret_key: SharedSecret<C>,
group_public: VerifyingKey<C>,
key_packages: HashMap<Identifier<C>, KeyPackage<C>>,
message_bytes: Vec<u8>,
share_polynomial_coefficients: Vec<Scalar<C>>,
hiding_nonces_randomness: HashMap<Identifier<C>, Vec<u8>>,
binding_nonces_randomness: HashMap<Identifier<C>, Vec<u8>>,
signer_nonces: HashMap<Identifier<C>, SigningNonces<C>>,
signer_commitments: HashMap<Identifier<C>, SigningCommitments<C>>,
binding_factor_inputs: HashMap<Identifier<C>, Vec<u8>>,
binding_factors: HashMap<Identifier<C>, Rho<C>>,
signature_shares: HashMap<Identifier<C>, SignatureShare<C>>,
signature_bytes: Vec<u8>,
}
/// Parse test vectors for a given ciphersuite.
#[allow(clippy::type_complexity)]
pub fn parse_test_vectors<C: Ciphersuite>(
json_vectors: &Value,
) -> (
SharedSecret<C>,
VerifyingKey<C>,
HashMap<Identifier<C>, KeyPackage<C>>,
Vec<u8>,
Vec<Scalar<C>>,
HashMap<Identifier<C>, SigningNonces<C>>,
HashMap<Identifier<C>, SigningCommitments<C>>,
HashMap<Identifier<C>, Vec<u8>>,
HashMap<Identifier<C>, Rho<C>>,
HashMap<Identifier<C>, SignatureShare<C>>,
Vec<u8>, // Signature<C>,
) {
pub fn parse_test_vectors<C: Ciphersuite>(json_vectors: &Value) -> TestVectors<C> {
let inputs = &json_vectors["inputs"];
let secret_key_str = inputs["group_secret_key"].as_str().unwrap();
@ -78,6 +81,8 @@ pub fn parse_test_vectors<C: Ciphersuite>(
let round_one_outputs = &json_vectors["round_one_outputs"];
let mut hiding_nonces_randomness: HashMap<Identifier<C>, Vec<u8>> = HashMap::new();
let mut binding_nonces_randomness: HashMap<Identifier<C>, Vec<u8>> = HashMap::new();
let mut signer_nonces: HashMap<Identifier<C>, SigningNonces<C>> = HashMap::new();
let mut signer_commitments: HashMap<Identifier<C>, SigningCommitments<C>> = HashMap::new();
let mut binding_factor_inputs: HashMap<Identifier<C>, Vec<u8>> = HashMap::new();
@ -90,6 +95,14 @@ pub fn parse_test_vectors<C: Ciphersuite>(
{
let identifier = u16::from_str(i).unwrap().try_into().unwrap();
let hiding_nonce_randomness =
hex::decode(signer["hiding_nonce_randomness"].as_str().unwrap()).unwrap();
hiding_nonces_randomness.insert(identifier, hiding_nonce_randomness);
let binding_nonce_randomness =
hex::decode(signer["binding_nonce_randomness"].as_str().unwrap()).unwrap();
binding_nonces_randomness.insert(identifier, binding_nonce_randomness);
let signing_nonces = SigningNonces::<C> {
hiding: Nonce::<C>::from_hex(signer["hiding_nonce"].as_str().unwrap()).unwrap(),
binding: Nonce::<C>::from_hex(signer["binding_nonce"].as_str().unwrap()).unwrap(),
@ -155,48 +168,52 @@ pub fn parse_test_vectors<C: Ciphersuite>(
let signature_bytes = FromHex::from_hex(final_output["sig"].as_str().unwrap()).unwrap();
(
TestVectors {
secret_key,
group_public,
key_packages,
message_bytes,
share_polynomial_coefficients,
hiding_nonces_randomness,
binding_nonces_randomness,
signer_nonces,
signer_commitments,
binding_factor_inputs,
binding_factors,
signature_shares,
signature_bytes,
)
}
}
/// Test with the given test vectors for a ciphersuite.
pub fn check_sign_with_test_vectors<C: Ciphersuite>(json_vectors: &Value) {
let (
let TestVectors {
secret_key,
group_public,
key_packages,
message_bytes,
share_polynomials_coefficients,
share_polynomial_coefficients,
hiding_nonces_randomness,
binding_nonces_randomness,
signer_nonces,
signer_commitments,
binding_factor_inputs,
binding_factors,
signature_shares,
signature_bytes,
) = parse_test_vectors(json_vectors);
} = parse_test_vectors(json_vectors);
////////////////////////////////////////////////////////////////////////////
// Key generation
////////////////////////////////////////////////////////////////////////////
let numshares = key_packages.len();
let threshold = share_polynomials_coefficients.len() + 1;
let threshold = share_polynomial_coefficients.len() + 1;
let secret_shares = generate_secret_shares(
&secret_key,
numshares as u8,
threshold as u8,
share_polynomials_coefficients,
share_polynomial_coefficients,
)
.unwrap();
let secret_shares: HashMap<_, _> = secret_shares
@ -220,8 +237,26 @@ pub fn check_sign_with_test_vectors<C: Ciphersuite>(json_vectors: &Value) {
/////////////////////////////////////////////////////////////////////////////
for (i, _) in signer_commitments.clone() {
// compute nonce commitments from nonces
let nonces = signer_nonces.get(&i).unwrap();
// compute nonces from secret and randomness
let secret = secret_shares[&i].secret();
let hiding_nonce_randomness = &hiding_nonces_randomness[&i];
let hiding_nonce = Nonce::nonce_generate_from_random_bytes(
secret,
hiding_nonce_randomness.as_slice().try_into().unwrap(),
);
assert!(nonces.hiding() == &hiding_nonce);
let binding_nonce_randomness = &binding_nonces_randomness[&i];
let binding_nonce = Nonce::nonce_generate_from_random_bytes(
secret,
binding_nonce_randomness.as_slice().try_into().unwrap(),
);
assert!(nonces.binding() == &binding_nonce);
// compute nonce commitments from nonces
let nonce_commitments = signer_commitments.get(&i).unwrap();
assert_eq!(