2021-09-09 01:56:54 -07:00
|
|
|
// Copyright (c) Facebook, Inc. and its affiliates.
|
|
|
|
|
//
|
2021-09-27 18:53:06 -07:00
|
|
|
// This source code is licensed under both the MIT license found in the
|
|
|
|
|
// LICENSE-MIT file in the root directory of this source tree and the Apache
|
|
|
|
|
// License, Version 2.0 found in the LICENSE-APACHE file in the root directory
|
|
|
|
|
// of this source tree.
|
2021-09-09 01:56:54 -07:00
|
|
|
|
2021-09-15 17:49:31 -07:00
|
|
|
use crate::{
|
|
|
|
|
ciphersuite::CipherSuite,
|
|
|
|
|
errors::InternalError,
|
|
|
|
|
group::Group,
|
|
|
|
|
tests::{mock_rng::CycleRng, parser::*},
|
|
|
|
|
voprf::{
|
2021-09-20 00:17:53 -07:00
|
|
|
BatchFinalizeInput, BlindedElement, EvaluationElement, Metadata, NonVerifiableClient,
|
|
|
|
|
NonVerifiableServer, Proof, VerifiableClient, VerifiableServer,
|
2021-09-15 17:49:31 -07:00
|
|
|
},
|
2021-09-15 11:38:13 -07:00
|
|
|
};
|
2021-09-09 01:56:54 -07:00
|
|
|
use alloc::string::ToString;
|
|
|
|
|
use alloc::vec::Vec;
|
|
|
|
|
use generic_array::GenericArray;
|
2021-09-13 16:02:09 -07:00
|
|
|
use json::JsonValue;
|
2021-09-09 01:56:54 -07:00
|
|
|
|
2021-09-13 16:02:09 -07:00
|
|
|
#[derive(Debug)]
|
2021-09-09 01:56:54 -07:00
|
|
|
struct VOPRFTestVectorParameters {
|
2021-09-13 16:02:09 -07:00
|
|
|
seed: Vec<u8>,
|
2021-09-09 01:56:54 -07:00
|
|
|
sksm: Vec<u8>,
|
2021-09-15 11:38:13 -07:00
|
|
|
pksm: Vec<u8>,
|
2021-09-13 16:02:09 -07:00
|
|
|
input: Vec<Vec<u8>>,
|
|
|
|
|
info: Vec<u8>,
|
|
|
|
|
blind: Vec<Vec<u8>>,
|
|
|
|
|
blinded_element: Vec<Vec<u8>>,
|
|
|
|
|
evaluation_element: Vec<Vec<u8>>,
|
2021-09-15 11:38:13 -07:00
|
|
|
proof: Vec<u8>,
|
|
|
|
|
proof_random_scalar: Vec<u8>,
|
2021-09-13 16:02:09 -07:00
|
|
|
output: Vec<Vec<u8>>,
|
2021-09-09 01:56:54 -07:00
|
|
|
}
|
|
|
|
|
|
2021-09-15 17:49:31 -07:00
|
|
|
fn populate_test_vectors(values: &JsonValue) -> VOPRFTestVectorParameters {
|
|
|
|
|
VOPRFTestVectorParameters {
|
|
|
|
|
seed: decode(values, "seed"),
|
|
|
|
|
sksm: decode(values, "skSm"),
|
|
|
|
|
pksm: decode(values, "pkSm"),
|
2021-10-06 00:19:20 +02:00
|
|
|
input: decode_vec(values, "Input"),
|
2021-09-15 17:49:31 -07:00
|
|
|
info: decode(values, "Info"),
|
2021-10-06 00:19:20 +02:00
|
|
|
blind: decode_vec(values, "Blind"),
|
|
|
|
|
blinded_element: decode_vec(values, "BlindedElement"),
|
|
|
|
|
evaluation_element: decode_vec(values, "EvaluationElement"),
|
2021-09-15 17:49:31 -07:00
|
|
|
proof: decode(values, "Proof"),
|
|
|
|
|
proof_random_scalar: decode(values, "ProofRandomScalar"),
|
2021-10-06 00:19:20 +02:00
|
|
|
output: decode_vec(values, "Output"),
|
2021-09-15 17:49:31 -07:00
|
|
|
}
|
2021-09-13 16:02:09 -07:00
|
|
|
}
|
|
|
|
|
|
2021-09-15 17:49:31 -07:00
|
|
|
fn decode(values: &JsonValue, key: &str) -> Vec<u8> {
|
2021-09-09 01:56:54 -07:00
|
|
|
values[key]
|
|
|
|
|
.as_str()
|
|
|
|
|
.and_then(|s| hex::decode(&s.to_string()).ok())
|
2021-10-06 00:19:20 +02:00
|
|
|
.unwrap_or_default()
|
2021-09-09 01:56:54 -07:00
|
|
|
}
|
|
|
|
|
|
2021-09-15 17:49:31 -07:00
|
|
|
fn decode_vec(values: &JsonValue, key: &str) -> Vec<Vec<u8>> {
|
2021-09-13 16:02:09 -07:00
|
|
|
let s = values[key].as_str().unwrap();
|
2021-09-15 17:49:31 -07:00
|
|
|
let res = match s.contains(',') {
|
2021-09-13 16:02:09 -07:00
|
|
|
true => Some(
|
|
|
|
|
s.split(',')
|
|
|
|
|
.map(|x| hex::decode(&x.to_string()).unwrap())
|
|
|
|
|
.collect(),
|
|
|
|
|
),
|
|
|
|
|
false => Some(vec![hex::decode(&s.to_string()).unwrap()]),
|
2021-09-15 17:49:31 -07:00
|
|
|
};
|
|
|
|
|
res.unwrap()
|
2021-09-13 16:02:09 -07:00
|
|
|
}
|
|
|
|
|
|
2021-09-15 17:49:31 -07:00
|
|
|
macro_rules! json_to_test_vectors {
|
|
|
|
|
( $v:ident, $cs:expr, $mode:expr ) => {
|
|
|
|
|
$v[$cs][$mode]
|
|
|
|
|
.members()
|
|
|
|
|
.map(|x| populate_test_vectors(&x))
|
|
|
|
|
.collect::<Vec<VOPRFTestVectorParameters>>()
|
|
|
|
|
};
|
2021-09-09 01:56:54 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
2021-09-15 17:49:31 -07:00
|
|
|
fn test_vectors() -> Result<(), InternalError> {
|
|
|
|
|
let rfc = json::parse(rfc_to_json(super::voprf_vectors::VECTORS).as_str())
|
|
|
|
|
.expect("Could not parse json");
|
2021-09-13 16:02:09 -07:00
|
|
|
|
2021-09-27 18:29:08 -07:00
|
|
|
use crate::tests::Ristretto255Sha512;
|
|
|
|
|
|
2021-09-13 16:02:09 -07:00
|
|
|
let ristretto_base_tvs = json_to_test_vectors!(
|
|
|
|
|
rfc,
|
|
|
|
|
String::from("ristretto255, SHA-512"),
|
|
|
|
|
String::from("Base")
|
|
|
|
|
);
|
|
|
|
|
|
2021-09-15 11:38:13 -07:00
|
|
|
let ristretto_verifiable_tvs = json_to_test_vectors!(
|
|
|
|
|
rfc,
|
|
|
|
|
String::from("ristretto255, SHA-512"),
|
|
|
|
|
String::from("Verifiable")
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
test_base_seed_to_key::<Ristretto255Sha512>(&ristretto_base_tvs)?;
|
|
|
|
|
test_base_blind::<Ristretto255Sha512>(&ristretto_base_tvs)?;
|
|
|
|
|
test_base_evaluate::<Ristretto255Sha512>(&ristretto_base_tvs)?;
|
|
|
|
|
test_base_finalize::<Ristretto255Sha512>(&ristretto_base_tvs)?;
|
|
|
|
|
|
|
|
|
|
test_verifiable_seed_to_key::<Ristretto255Sha512>(&ristretto_verifiable_tvs)?;
|
|
|
|
|
test_verifiable_blind::<Ristretto255Sha512>(&ristretto_verifiable_tvs)?;
|
|
|
|
|
test_verifiable_evaluate::<Ristretto255Sha512>(&ristretto_verifiable_tvs)?;
|
|
|
|
|
test_verifiable_finalize::<Ristretto255Sha512>(&ristretto_verifiable_tvs)?;
|
2021-09-09 01:56:54 -07:00
|
|
|
|
|
|
|
|
#[cfg(feature = "p256")]
|
|
|
|
|
{
|
2021-09-27 18:29:08 -07:00
|
|
|
use crate::tests::P256Sha256;
|
2021-09-09 01:56:54 -07:00
|
|
|
|
2021-09-13 16:02:09 -07:00
|
|
|
let p256_base_tvs =
|
|
|
|
|
json_to_test_vectors!(rfc, String::from("P-256, SHA-256"), String::from("Base"));
|
|
|
|
|
|
2021-09-15 11:38:13 -07:00
|
|
|
let p256_verifiable_tvs = json_to_test_vectors!(
|
|
|
|
|
rfc,
|
|
|
|
|
String::from("P-256, SHA-256"),
|
|
|
|
|
String::from("Verifiable")
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
test_base_seed_to_key::<P256Sha256>(&p256_base_tvs)?;
|
|
|
|
|
test_base_blind::<P256Sha256>(&p256_base_tvs)?;
|
|
|
|
|
test_base_evaluate::<P256Sha256>(&p256_base_tvs)?;
|
|
|
|
|
test_base_finalize::<P256Sha256>(&p256_base_tvs)?;
|
|
|
|
|
|
|
|
|
|
test_verifiable_seed_to_key::<P256Sha256>(&p256_verifiable_tvs)?;
|
|
|
|
|
test_verifiable_blind::<P256Sha256>(&p256_verifiable_tvs)?;
|
|
|
|
|
test_verifiable_evaluate::<P256Sha256>(&p256_verifiable_tvs)?;
|
|
|
|
|
test_verifiable_finalize::<P256Sha256>(&p256_verifiable_tvs)?;
|
2021-09-09 01:56:54 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-15 11:38:13 -07:00
|
|
|
fn test_base_seed_to_key<CS: CipherSuite>(
|
|
|
|
|
tvs: &[VOPRFTestVectorParameters],
|
|
|
|
|
) -> Result<(), InternalError> {
|
2021-09-13 16:02:09 -07:00
|
|
|
for parameters in tvs {
|
2021-09-15 11:38:13 -07:00
|
|
|
let server = NonVerifiableServer::<CS>::new_from_seed(¶meters.seed)?;
|
2021-09-09 01:56:54 -07:00
|
|
|
|
|
|
|
|
assert_eq!(
|
2021-09-15 11:38:13 -07:00
|
|
|
¶meters.sksm,
|
|
|
|
|
&CS::Group::scalar_as_bytes(server.get_private_key()).to_vec()
|
2021-09-09 01:56:54 -07:00
|
|
|
);
|
2021-09-15 11:38:13 -07:00
|
|
|
}
|
|
|
|
|
Ok(())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn test_verifiable_seed_to_key<CS: CipherSuite>(
|
|
|
|
|
tvs: &[VOPRFTestVectorParameters],
|
|
|
|
|
) -> Result<(), InternalError> {
|
|
|
|
|
for parameters in tvs {
|
|
|
|
|
let server = VerifiableServer::<CS>::new_from_seed(¶meters.seed)?;
|
|
|
|
|
|
2021-09-09 01:56:54 -07:00
|
|
|
assert_eq!(
|
2021-09-15 11:38:13 -07:00
|
|
|
¶meters.sksm,
|
|
|
|
|
&CS::Group::scalar_as_bytes(server.get_private_key()).to_vec()
|
2021-09-09 01:56:54 -07:00
|
|
|
);
|
2021-09-15 11:38:13 -07:00
|
|
|
assert_eq!(¶meters.pksm, &server.get_public_key().to_arr().to_vec());
|
|
|
|
|
}
|
|
|
|
|
Ok(())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Tests input -> blind, blinded_element
|
|
|
|
|
fn test_base_blind<CS: CipherSuite>(
|
|
|
|
|
tvs: &[VOPRFTestVectorParameters],
|
|
|
|
|
) -> Result<(), InternalError> {
|
|
|
|
|
for parameters in tvs {
|
|
|
|
|
for i in 0..parameters.input.len() {
|
|
|
|
|
let mut rng = CycleRng::new(parameters.blind[i].to_vec());
|
2021-09-20 00:17:53 -07:00
|
|
|
let client_result = NonVerifiableClient::<CS>::blind(¶meters.input[i], &mut rng)?;
|
2021-09-15 11:38:13 -07:00
|
|
|
|
|
|
|
|
assert_eq!(
|
|
|
|
|
¶meters.blind[i],
|
2021-09-20 00:17:53 -07:00
|
|
|
&CS::Group::scalar_as_bytes(client_result.state.get_blind()).to_vec()
|
|
|
|
|
);
|
|
|
|
|
assert_eq!(
|
|
|
|
|
¶meters.blinded_element[i],
|
|
|
|
|
&client_result.message.serialize()
|
2021-09-15 11:38:13 -07:00
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
Ok(())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Tests input -> blind, blinded_element
|
|
|
|
|
fn test_verifiable_blind<CS: CipherSuite>(
|
|
|
|
|
tvs: &[VOPRFTestVectorParameters],
|
|
|
|
|
) -> Result<(), InternalError> {
|
|
|
|
|
for parameters in tvs {
|
|
|
|
|
for i in 0..parameters.input.len() {
|
|
|
|
|
let mut rng = CycleRng::new(parameters.blind[i].to_vec());
|
2021-09-20 00:17:53 -07:00
|
|
|
let client_blind_result =
|
2021-09-15 11:38:13 -07:00
|
|
|
VerifiableClient::<CS>::blind(¶meters.input[i], &mut rng)?;
|
|
|
|
|
|
|
|
|
|
assert_eq!(
|
|
|
|
|
¶meters.blind[i],
|
2021-09-20 00:17:53 -07:00
|
|
|
&CS::Group::scalar_as_bytes(client_blind_result.state.get_blind()).to_vec()
|
|
|
|
|
);
|
|
|
|
|
assert_eq!(
|
|
|
|
|
¶meters.blinded_element[i],
|
|
|
|
|
&client_blind_result.message.serialize()
|
2021-09-15 11:38:13 -07:00
|
|
|
);
|
|
|
|
|
}
|
2021-09-09 01:56:54 -07:00
|
|
|
}
|
|
|
|
|
Ok(())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Tests sksm, blinded_element -> evaluation_element
|
2021-09-15 11:38:13 -07:00
|
|
|
fn test_base_evaluate<CS: CipherSuite>(
|
|
|
|
|
tvs: &[VOPRFTestVectorParameters],
|
|
|
|
|
) -> Result<(), InternalError> {
|
2021-09-13 16:02:09 -07:00
|
|
|
for parameters in tvs {
|
2021-09-15 11:38:13 -07:00
|
|
|
for i in 0..parameters.input.len() {
|
2021-09-15 17:49:31 -07:00
|
|
|
let server = NonVerifiableServer::<CS>::new_with_key(¶meters.sksm)?;
|
2021-09-20 00:17:53 -07:00
|
|
|
let server_result = server.evaluate(
|
2021-09-15 17:49:31 -07:00
|
|
|
BlindedElement::deserialize(¶meters.blinded_element[i])?,
|
2021-09-20 00:17:53 -07:00
|
|
|
&Metadata(parameters.info.clone()),
|
2021-09-15 11:38:13 -07:00
|
|
|
)?;
|
|
|
|
|
|
|
|
|
|
assert_eq!(
|
|
|
|
|
¶meters.evaluation_element[i],
|
2021-09-20 00:17:53 -07:00
|
|
|
&server_result.message.serialize()
|
2021-09-15 11:38:13 -07:00
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
Ok(())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn test_verifiable_evaluate<CS: CipherSuite>(
|
|
|
|
|
tvs: &[VOPRFTestVectorParameters],
|
|
|
|
|
) -> Result<(), InternalError> {
|
|
|
|
|
for parameters in tvs {
|
|
|
|
|
let mut rng = CycleRng::new(parameters.proof_random_scalar.clone());
|
2021-09-15 17:49:31 -07:00
|
|
|
let server = VerifiableServer::<CS>::new_with_key(¶meters.sksm)?;
|
|
|
|
|
|
|
|
|
|
let mut blinded_elements = vec![];
|
|
|
|
|
for blinded_element_bytes in ¶meters.blinded_element {
|
2021-10-06 00:19:20 +02:00
|
|
|
blinded_elements.push(BlindedElement::deserialize(blinded_element_bytes)?);
|
2021-09-15 17:49:31 -07:00
|
|
|
}
|
|
|
|
|
|
2021-09-20 00:17:53 -07:00
|
|
|
let batch_evaluate_result = server.batch_evaluate(
|
|
|
|
|
&mut rng,
|
|
|
|
|
&blinded_elements,
|
|
|
|
|
&Metadata(parameters.info.clone()),
|
|
|
|
|
)?;
|
2021-09-09 01:56:54 -07:00
|
|
|
|
2021-09-15 11:38:13 -07:00
|
|
|
for i in 0..parameters.evaluation_element.len() {
|
|
|
|
|
assert_eq!(
|
|
|
|
|
¶meters.evaluation_element[i],
|
2021-09-20 00:17:53 -07:00
|
|
|
&batch_evaluate_result.messages[i].serialize(),
|
2021-09-15 11:38:13 -07:00
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-20 00:17:53 -07:00
|
|
|
assert_eq!(¶meters.proof, &batch_evaluate_result.proof.serialize());
|
2021-09-09 01:56:54 -07:00
|
|
|
}
|
|
|
|
|
Ok(())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Tests input, blind, evaluation_element -> output
|
2021-09-15 11:38:13 -07:00
|
|
|
fn test_base_finalize<CS: CipherSuite>(
|
|
|
|
|
tvs: &[VOPRFTestVectorParameters],
|
|
|
|
|
) -> Result<(), InternalError> {
|
2021-09-13 16:02:09 -07:00
|
|
|
for parameters in tvs {
|
2021-09-15 11:38:13 -07:00
|
|
|
for i in 0..parameters.input.len() {
|
|
|
|
|
let client = NonVerifiableClient::<CS>::from_data_and_blind(
|
|
|
|
|
¶meters.input[i],
|
2021-10-06 00:19:20 +02:00
|
|
|
<CS::Group as Group>::from_scalar_slice(&GenericArray::clone_from_slice(
|
2021-09-15 11:38:13 -07:00
|
|
|
¶meters.blind[i],
|
2021-09-15 17:49:31 -07:00
|
|
|
))?,
|
2021-09-15 11:38:13 -07:00
|
|
|
);
|
|
|
|
|
|
2021-09-20 00:17:53 -07:00
|
|
|
let client_finalize_result = client.finalize(
|
2021-09-15 17:49:31 -07:00
|
|
|
EvaluationElement::deserialize(¶meters.evaluation_element[i])?,
|
2021-09-20 00:17:53 -07:00
|
|
|
&Metadata(parameters.info.clone()),
|
2021-09-15 11:38:13 -07:00
|
|
|
)?;
|
|
|
|
|
|
2021-09-20 00:17:53 -07:00
|
|
|
assert_eq!(
|
|
|
|
|
¶meters.output[i],
|
|
|
|
|
&client_finalize_result.output.to_vec()
|
|
|
|
|
);
|
2021-09-15 11:38:13 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
Ok(())
|
|
|
|
|
}
|
2021-09-09 01:56:54 -07:00
|
|
|
|
2021-09-15 11:38:13 -07:00
|
|
|
fn test_verifiable_finalize<CS: CipherSuite>(
|
|
|
|
|
tvs: &[VOPRFTestVectorParameters],
|
|
|
|
|
) -> Result<(), InternalError> {
|
|
|
|
|
for parameters in tvs {
|
|
|
|
|
let mut clients = vec![];
|
|
|
|
|
for i in 0..parameters.input.len() {
|
|
|
|
|
let client = VerifiableClient::<CS>::from_data_and_blind(
|
|
|
|
|
¶meters.input[i],
|
2021-10-06 00:19:20 +02:00
|
|
|
<CS::Group as Group>::from_scalar_slice(&GenericArray::clone_from_slice(
|
2021-09-15 11:38:13 -07:00
|
|
|
¶meters.blind[i],
|
|
|
|
|
))?,
|
2021-10-06 00:19:20 +02:00
|
|
|
<CS::Group as Group>::from_element_slice(&GenericArray::clone_from_slice(
|
2021-09-15 11:38:13 -07:00
|
|
|
¶meters.blinded_element[i],
|
|
|
|
|
))?,
|
|
|
|
|
);
|
|
|
|
|
clients.push(client.clone());
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-20 00:17:53 -07:00
|
|
|
let batch_finalize_input = BatchFinalizeInput::new(
|
|
|
|
|
clients,
|
|
|
|
|
parameters
|
|
|
|
|
.evaluation_element
|
|
|
|
|
.iter()
|
|
|
|
|
.map(|x| EvaluationElement::deserialize(x).unwrap())
|
|
|
|
|
.collect(),
|
|
|
|
|
);
|
2021-09-15 11:38:13 -07:00
|
|
|
|
2021-09-20 00:17:53 -07:00
|
|
|
let batch_result = VerifiableClient::batch_finalize(
|
|
|
|
|
batch_finalize_input,
|
2021-09-15 11:38:13 -07:00
|
|
|
Proof::deserialize(¶meters.proof)?,
|
|
|
|
|
CS::Group::from_element_slice(GenericArray::from_slice(¶meters.pksm))?,
|
2021-09-20 00:17:53 -07:00
|
|
|
&Metadata(parameters.info.clone()),
|
2021-09-13 16:02:09 -07:00
|
|
|
)?;
|
2021-09-09 01:56:54 -07:00
|
|
|
|
2021-09-15 11:38:13 -07:00
|
|
|
assert_eq!(
|
|
|
|
|
parameters.output,
|
2021-09-20 00:17:53 -07:00
|
|
|
batch_result
|
|
|
|
|
.outputs
|
2021-09-15 11:38:13 -07:00
|
|
|
.iter()
|
|
|
|
|
.map(|arr| arr.to_vec())
|
|
|
|
|
.collect::<Vec<Vec<u8>>>()
|
|
|
|
|
);
|
2021-09-09 01:56:54 -07:00
|
|
|
}
|
|
|
|
|
Ok(())
|
|
|
|
|
}
|