Files
opaque-vx/src/tests/full_test.rs
T

713 lines
29 KiB
Rust
Raw Normal View History

2020-06-05 09:35:14 -07:00
// Copyright (c) Facebook, Inc. and its affiliates.
//
// This source code is licensed under the MIT license found in the
// LICENSE file in the root directory of this source tree.
use crate::{
ciphersuite::CipherSuite,
2020-06-05 09:35:14 -07:00
errors::*,
group::Group,
key_exchange::tripledh::{NonceLen, TripleDH},
2021-01-25 13:20:36 -08:00
keypair::Key,
2020-06-05 09:35:14 -07:00
opaque::*,
slow_hash::NoOpHash,
2020-06-05 09:35:14 -07:00
tests::mock_rng::CycleRng,
2020-11-16 14:05:43 -08:00
*,
2020-06-05 09:35:14 -07:00
};
2021-01-25 13:20:36 -08:00
use curve25519_dalek::ristretto::RistrettoPoint;
use generic_array::typenum::Unsigned;
2020-11-03 21:44:00 +00:00
use generic_bytes::SizedBytes;
2021-02-11 18:10:48 -08:00
use rand::{rngs::OsRng, RngCore};
2020-06-05 09:35:14 -07:00
use serde_json::Value;
use std::convert::TryFrom;
// Tests
// =====
2021-01-25 13:20:36 -08:00
struct RistrettoSha5123dhNoSlowHash;
impl CipherSuite for RistrettoSha5123dhNoSlowHash {
type Group = RistrettoPoint;
2020-07-13 15:23:29 -07:00
type KeyExchange = TripleDH;
2021-01-25 13:20:36 -08:00
type Hash = sha2::Sha512;
type SlowHash = NoOpHash;
}
2020-06-05 09:35:14 -07:00
pub struct TestVectorParameters {
pub client_s_pk: Vec<u8>,
pub client_s_sk: Vec<u8>,
pub client_e_pk: Vec<u8>,
pub client_e_sk: Vec<u8>,
pub server_s_pk: Vec<u8>,
pub server_s_sk: Vec<u8>,
pub server_e_pk: Vec<u8>,
pub server_e_sk: Vec<u8>,
2020-11-02 13:51:43 -08:00
pub id_u: Vec<u8>,
pub id_s: Vec<u8>,
2020-06-05 09:35:14 -07:00
pub password: Vec<u8>,
pub blinding_factor: Vec<u8>,
pub oprf_key: Vec<u8>,
pub envelope_nonce: Vec<u8>,
pub client_nonce: Vec<u8>,
pub server_nonce: Vec<u8>,
pub info1: Vec<u8>,
pub einfo2: Vec<u8>,
2020-12-12 21:53:33 -08:00
pub registration_request: Vec<u8>,
pub registration_response: Vec<u8>,
pub registration_upload: Vec<u8>,
2020-12-12 21:53:33 -08:00
pub credential_request: Vec<u8>,
pub credential_response: Vec<u8>,
pub credential_finalization: Vec<u8>,
2020-06-05 09:35:14 -07:00
client_registration_state: Vec<u8>,
server_registration_state: Vec<u8>,
client_login_state: Vec<u8>,
server_login_state: Vec<u8>,
pub password_file: Vec<u8>,
pub export_key: Vec<u8>,
pub session_key: Vec<u8>,
2020-06-05 09:35:14 -07:00
}
static TEST_VECTOR: &str = r#"
{
"client_s_pk": "c83bbe77d4bae020134fa3e75eb8e21f52bbcab7149d0d921af52c6a3edc6706",
"client_s_sk": "e0f252dc3506125ac25b9cf57c0f5104070e3990f432a319c801d47c25eff209",
"client_e_pk": "1a28a68246a6149c429e8ebe57dccbb764d9ff7a6b094727dbd863ec3b553b3a",
"client_e_sk": "3eb9867c6b0d0031f2fcab920598be82d526df916fab71d81842ced65a800008",
"server_s_pk": "b0240feaab8cefa1ed162c0f175243893681bae36a7a67a73881d3ae2345b811",
"server_s_sk": "37c93770d27945246edcb124c47d5fae83a9cd9e47c72cf681460ccc8cd4d70b",
"server_e_pk": "2a442437b58a4ed0a39a954d8f775e08d8d94f9554fe35618fa703d2fef7a66f",
"server_e_sk": "79ff8259a71fabb27d0c267677639bec741e7dbe72240c54eb70513eca5a8306",
2020-11-02 13:51:43 -08:00
"id_u": "696455",
"id_s": "696453",
2020-06-05 09:35:14 -07:00
"password": "70617373776f7264",
"blinding_factor": "3912c0df0f2b3b659da47803bdd94492084e5aa9b6f75d2966ed69aff57db001",
"oprf_key": "14a29db285876949dc997d4257a85ff53f9676a40c5c5428e20cd2e5b2ce9105",
"envelope_nonce": "08c8ea116a059f708b598cfba38664423bf00ecae224c22b2c4fe9d7c04f69f1",
"client_nonce": "e44552fcf7e2b872e80d9c0213adeba9e41c43c668f73e08aaa43f4fa7747e0e",
"server_nonce": "03bfe3d1ba36d894fda7fcdf02da7dd16b043e1a08d82b662a9cdcd65a621336",
"info1": "696e666f31",
"einfo2": "65696e666f32",
"registration_request": "d6ebc1daf688bf812ca6ab0cbb797ba165aa2670c285f531ef7cd438c7b10f49",
"registration_response": "8c7c3b570fcfb533ce06b36e428be0b7504cbeda53ef17abda7149efdf6fa51bb0240feaab8cefa1ed162c0f175243893681bae36a7a67a73881d3ae2345b811",
"registration_upload": "c83bbe77d4bae020134fa3e75eb8e21f52bbcab7149d0d921af52c6a3edc67060208c8ea116a059f708b598cfba38664423bf00ecae224c22b2c4fe9d7c04f69f10020c87927d29c345906f2017ee54d959c2859cd49a2017ed0213d10ef42189de3ba17c334967d8f41e7f1b7f0bb2bfaa478a741f8c3395edde2154f04b415e64b36cc2d21aacdf2d9e25dd63073476537d3bff44b93d7c0e239062610c457ab2298",
"credential_request": "d6ebc1daf688bf812ca6ab0cbb797ba165aa2670c285f531ef7cd438c7b10f49e44552fcf7e2b872e80d9c0213adeba9e41c43c668f73e08aaa43f4fa7747e0e0005696e666f311a28a68246a6149c429e8ebe57dccbb764d9ff7a6b094727dbd863ec3b553b3a",
"credential_response": "8c7c3b570fcfb533ce06b36e428be0b7504cbeda53ef17abda7149efdf6fa51bb0240feaab8cefa1ed162c0f175243893681bae36a7a67a73881d3ae2345b8110208c8ea116a059f708b598cfba38664423bf00ecae224c22b2c4fe9d7c04f69f10020c87927d29c345906f2017ee54d959c2859cd49a2017ed0213d10ef42189de3ba17c334967d8f41e7f1b7f0bb2bfaa478a741f8c3395edde2154f04b415e64b36cc2d21aacdf2d9e25dd63073476537d3bff44b93d7c0e239062610c457ab229803bfe3d1ba36d894fda7fcdf02da7dd16b043e1a08d82b662a9cdcd65a6213362a442437b58a4ed0a39a954d8f775e08d8d94f9554fe35618fa703d2fef7a66f00064901d7e2dd4e743653346e3f049210c1353005640e5eec45b1123519b0601fa378b2cd74ea81a7d92e62298c80517db7f5deee19d7558004b6566c50264f6665cdae5dcc7913",
"credential_finalization": "9b2c7dc06e635a6f121df9e1781ddca3551757e181ed0585494a20f71b098b26faafa4943c931b7af582d28fd791934026d69583255a604a08f3913436dddec9",
"client_registration_state": "3912c0df0f2b3b659da47803bdd94492084e5aa9b6f75d2966ed69aff57db00170617373776f7264",
"client_login_state": "3912c0df0f2b3b659da47803bdd94492084e5aa9b6f75d2966ed69aff57db0010067d6ebc1daf688bf812ca6ab0cbb797ba165aa2670c285f531ef7cd438c7b10f49e44552fcf7e2b872e80d9c0213adeba9e41c43c668f73e08aaa43f4fa7747e0e0005696e666f311a28a68246a6149c429e8ebe57dccbb764d9ff7a6b094727dbd863ec3b553b3a00403eb9867c6b0d0031f2fcab920598be82d526df916fab71d81842ced65a800008e44552fcf7e2b872e80d9c0213adeba9e41c43c668f73e08aaa43f4fa7747e0e70617373776f7264",
"server_registration_state": "14a29db285876949dc997d4257a85ff53f9676a40c5c5428e20cd2e5b2ce9105",
"server_login_state": "cee1e837a695fc63287e3896a1305455ba06c553bb2253dce4295dacd25a2a6e7c6da523db352db9c3fafa6dd753ed5b060c9650176650ede7ecd85c52c4c6c63dae7f5c960b0e87f57fee3604ae36664bb514ca3a0e861f96124f12bf30002a3818ee21fe38e800c8a694dcbd0158a6a47496297b062fa1a4ce3c4971a00b042cbb870c351ba904f64d183f1cdc755bcab82ed00cf090bd73c1862423503cb1b66dda9fb369d22ac2fdc76b578db8b25e84a45bfe030702d704d354f8efaa27",
"password_file": "14a29db285876949dc997d4257a85ff53f9676a40c5c5428e20cd2e5b2ce9105c83bbe77d4bae020134fa3e75eb8e21f52bbcab7149d0d921af52c6a3edc67060208c8ea116a059f708b598cfba38664423bf00ecae224c22b2c4fe9d7c04f69f10020c87927d29c345906f2017ee54d959c2859cd49a2017ed0213d10ef42189de3ba17c334967d8f41e7f1b7f0bb2bfaa478a741f8c3395edde2154f04b415e64b36cc2d21aacdf2d9e25dd63073476537d3bff44b93d7c0e239062610c457ab2298",
"export_key": "dec7b035715f5a7cc3cc205d190a2fce6ce81a6c643e644689a6516aed5b35c7fa31babe78edb1845d6ab092784feeae7ed11919dfcd90077b15e43e69a878ea",
"session_key": "2cbb870c351ba904f64d183f1cdc755bcab82ed00cf090bd73c1862423503cb1b66dda9fb369d22ac2fdc76b578db8b25e84a45bfe030702d704d354f8efaa27"
2020-06-05 09:35:14 -07:00
}
"#;
fn decode(values: &Value, key: &str) -> Option<Vec<u8>> {
values[key]
.as_str()
.and_then(|s| hex::decode(&s.to_string()).ok())
}
fn populate_test_vectors(values: &Value) -> TestVectorParameters {
TestVectorParameters {
client_s_pk: decode(&values, "client_s_pk").unwrap(),
client_s_sk: decode(&values, "client_s_sk").unwrap(),
client_e_pk: decode(&values, "client_e_pk").unwrap(),
client_e_sk: decode(&values, "client_e_sk").unwrap(),
server_s_pk: decode(&values, "server_s_pk").unwrap(),
server_s_sk: decode(&values, "server_s_sk").unwrap(),
server_e_pk: decode(&values, "server_e_pk").unwrap(),
server_e_sk: decode(&values, "server_e_sk").unwrap(),
2020-11-02 13:51:43 -08:00
id_u: decode(&values, "id_u").unwrap(),
id_s: decode(&values, "id_s").unwrap(),
2020-06-05 09:35:14 -07:00
password: decode(&values, "password").unwrap(),
blinding_factor: decode(&values, "blinding_factor").unwrap(),
oprf_key: decode(&values, "oprf_key").unwrap(),
envelope_nonce: decode(&values, "envelope_nonce").unwrap(),
client_nonce: decode(&values, "client_nonce").unwrap(),
server_nonce: decode(&values, "server_nonce").unwrap(),
info1: decode(&values, "info1").unwrap(),
einfo2: decode(&values, "einfo2").unwrap(),
2020-12-12 21:53:33 -08:00
registration_request: decode(&values, "registration_request").unwrap(),
registration_response: decode(&values, "registration_response").unwrap(),
registration_upload: decode(&values, "registration_upload").unwrap(),
2020-12-12 21:53:33 -08:00
credential_request: decode(&values, "credential_request").unwrap(),
credential_response: decode(&values, "credential_response").unwrap(),
credential_finalization: decode(&values, "credential_finalization").unwrap(),
2020-06-05 09:35:14 -07:00
client_registration_state: decode(&values, "client_registration_state").unwrap(),
client_login_state: decode(&values, "client_login_state").unwrap(),
server_registration_state: decode(&values, "server_registration_state").unwrap(),
server_login_state: decode(&values, "server_login_state").unwrap(),
password_file: decode(&values, "password_file").unwrap(),
export_key: decode(&values, "export_key").unwrap(),
session_key: decode(&values, "session_key").unwrap(),
2020-06-05 09:35:14 -07:00
}
}
fn stringify_test_vectors(p: &TestVectorParameters) -> String {
let mut s = String::new();
s.push_str("{\n");
s.push_str(format!("\"client_s_pk\": \"{}\",\n", hex::encode(&p.client_s_pk)).as_str());
s.push_str(format!("\"client_s_sk\": \"{}\",\n", hex::encode(&p.client_s_sk)).as_str());
s.push_str(format!("\"client_e_pk\": \"{}\",\n", hex::encode(&p.client_e_pk)).as_str());
s.push_str(format!("\"client_e_sk\": \"{}\",\n", hex::encode(&p.client_e_sk)).as_str());
s.push_str(format!("\"server_s_pk\": \"{}\",\n", hex::encode(&p.server_s_pk)).as_str());
s.push_str(format!("\"server_s_sk\": \"{}\",\n", hex::encode(&p.server_s_sk)).as_str());
s.push_str(format!("\"server_e_pk\": \"{}\",\n", hex::encode(&p.server_e_pk)).as_str());
s.push_str(format!("\"server_e_sk\": \"{}\",\n", hex::encode(&p.server_e_sk)).as_str());
2020-11-02 13:51:43 -08:00
s.push_str(format!("\"id_u\": \"{}\",\n", hex::encode(&p.id_u)).as_str());
s.push_str(format!("\"id_s\": \"{}\",\n", hex::encode(&p.id_s)).as_str());
2020-06-05 09:35:14 -07:00
s.push_str(format!("\"password\": \"{}\",\n", hex::encode(&p.password)).as_str());
s.push_str(
format!(
"\"blinding_factor\": \"{}\",\n",
hex::encode(&p.blinding_factor)
)
.as_str(),
);
s.push_str(format!("\"oprf_key\": \"{}\",\n", hex::encode(&p.oprf_key)).as_str());
s.push_str(
format!(
"\"envelope_nonce\": \"{}\",\n",
hex::encode(&p.envelope_nonce)
)
.as_str(),
);
s.push_str(format!("\"client_nonce\": \"{}\",\n", hex::encode(&p.client_nonce)).as_str());
s.push_str(format!("\"server_nonce\": \"{}\",\n", hex::encode(&p.server_nonce)).as_str());
s.push_str(format!("\"info1\": \"{}\",\n", hex::encode(&p.info1)).as_str());
s.push_str(format!("\"einfo2\": \"{}\",\n", hex::encode(&p.einfo2)).as_str());
2020-12-12 21:53:33 -08:00
s.push_str(
format!(
"\"registration_request\": \"{}\",\n",
hex::encode(&p.registration_request)
)
.as_str(),
);
s.push_str(
format!(
"\"registration_response\": \"{}\",\n",
hex::encode(&p.registration_response)
)
.as_str(),
);
s.push_str(
format!(
"\"registration_upload\": \"{}\",\n",
hex::encode(&p.registration_upload)
)
.as_str(),
);
2020-12-12 21:53:33 -08:00
s.push_str(
format!(
"\"credential_request\": \"{}\",\n",
hex::encode(&p.credential_request)
)
.as_str(),
);
s.push_str(
format!(
"\"credential_response\": \"{}\",\n",
hex::encode(&p.credential_response)
)
.as_str(),
);
s.push_str(
format!(
"\"credential_finalization\": \"{}\",\n",
hex::encode(&p.credential_finalization)
)
.as_str(),
);
2020-06-05 09:35:14 -07:00
s.push_str(
format!(
"\"client_registration_state\": \"{}\",\n",
hex::encode(&p.client_registration_state)
)
.as_str(),
);
s.push_str(
format!(
"\"client_login_state\": \"{}\",\n",
hex::encode(&p.client_login_state)
)
.as_str(),
);
s.push_str(
format!(
"\"server_registration_state\": \"{}\",\n",
hex::encode(&p.server_registration_state)
)
.as_str(),
);
s.push_str(
format!(
"\"server_login_state\": \"{}\",\n",
hex::encode(&p.server_login_state)
)
.as_str(),
);
s.push_str(
format!(
"\"password_file\": \"{}\",\n",
hex::encode(&p.password_file)
)
.as_str(),
);
s.push_str(format!("\"export_key\": \"{}\",\n", hex::encode(&p.export_key)).as_str());
s.push_str(format!("\"session_key\": \"{}\"\n", hex::encode(&p.session_key)).as_str());
2020-06-05 09:35:14 -07:00
s.push_str("}\n");
s
}
2021-01-25 13:20:36 -08:00
fn generate_parameters<CS: CipherSuite>() -> TestVectorParameters {
2020-06-05 09:35:14 -07:00
let mut rng = OsRng;
// Inputs
2021-01-25 13:20:36 -08:00
let server_s_kp = CS::generate_random_keypair(&mut rng);
let server_e_kp = CS::generate_random_keypair(&mut rng);
let client_s_kp = CS::generate_random_keypair(&mut rng);
let client_e_kp = CS::generate_random_keypair(&mut rng);
2020-11-02 13:51:43 -08:00
let id_u = b"idU";
let id_s = b"idS";
2020-06-05 09:35:14 -07:00
let password = b"password";
let mut oprf_key_raw = [0u8; 32];
rng.fill_bytes(&mut oprf_key_raw);
let mut envelope_nonce = [0u8; 32];
2020-06-05 09:35:14 -07:00
rng.fill_bytes(&mut envelope_nonce);
let mut client_nonce = vec![0u8; NonceLen::to_usize()];
2020-06-05 09:35:14 -07:00
rng.fill_bytes(&mut client_nonce);
let mut server_nonce = vec![0u8; NonceLen::to_usize()];
2020-06-05 09:35:14 -07:00
rng.fill_bytes(&mut server_nonce);
2021-01-25 13:20:36 -08:00
let blinding_factor = CS::Group::random_scalar(&mut rng);
let blinding_factor_bytes = CS::Group::scalar_as_bytes(&blinding_factor).clone();
let info1 = b"info1";
let einfo2 = b"einfo2";
2021-01-25 13:20:36 -08:00
let mut blinding_factor_registration_rng = CycleRng::new(blinding_factor_bytes.to_vec());
let client_registration_start_result =
ClientRegistration::<CS>::start(&mut blinding_factor_registration_rng, password).unwrap();
let blinding_factor_bytes_returned =
CS::Group::scalar_as_bytes(&client_registration_start_result.state.token.blind).clone();
assert_eq!(
hex::encode(&blinding_factor_bytes),
hex::encode(&blinding_factor_bytes_returned)
);
2020-12-12 21:53:33 -08:00
let registration_request_bytes = client_registration_start_result
.message
.serialize()
.to_vec();
let client_registration_state = client_registration_start_result.state.serialize().to_vec();
2020-06-05 09:35:14 -07:00
let mut oprf_key_rng = CycleRng::new(oprf_key_raw.to_vec());
2020-12-12 21:53:33 -08:00
let server_registration_start_result = ServerRegistration::<CS>::start(
&mut oprf_key_rng,
client_registration_start_result.message,
server_s_kp.public(),
)
.unwrap();
let registration_response_bytes = server_registration_start_result
.message
.serialize()
.to_vec();
let oprf_key_bytes =
CS::Group::scalar_as_bytes(&server_registration_start_result.state.oprf_key).clone();
let server_registration_state = server_registration_start_result.state.serialize().to_vec();
2020-06-05 09:35:14 -07:00
let mut client_s_sk_and_nonce: Vec<u8> = Vec::new();
2020-09-22 08:50:39 -04:00
client_s_sk_and_nonce.extend_from_slice(&client_s_kp.private().to_arr());
2020-06-05 09:35:14 -07:00
client_s_sk_and_nonce.extend_from_slice(&envelope_nonce);
let mut finish_registration_rng = CycleRng::new(client_s_sk_and_nonce);
2020-12-12 21:53:33 -08:00
let client_registration_finish_result = client_registration_start_result
.state
.finish(
&mut finish_registration_rng,
server_registration_start_result.message,
ClientRegistrationFinishParameters::WithIdentifiers(id_u.to_vec(), id_s.to_vec()),
2020-12-12 21:53:33 -08:00
)
2020-06-05 09:35:14 -07:00
.unwrap();
let registration_upload_bytes = client_registration_finish_result
2020-12-12 21:53:33 -08:00
.message
.serialize()
.to_vec();
2020-06-05 09:35:14 -07:00
2020-12-12 21:53:33 -08:00
let password_file = server_registration_start_result
.state
.finish(client_registration_finish_result.message)
.unwrap();
let password_file_bytes = password_file.serialize();
2020-06-05 09:35:14 -07:00
let mut client_login_start: Vec<u8> = Vec::new();
2021-01-25 13:20:36 -08:00
client_login_start.extend_from_slice(&blinding_factor_bytes);
2020-09-22 08:50:39 -04:00
client_login_start.extend_from_slice(&client_e_kp.private().to_arr());
2020-06-05 09:35:14 -07:00
client_login_start.extend_from_slice(&client_nonce);
let mut client_login_start_rng = CycleRng::new(client_login_start);
2020-11-16 14:05:43 -08:00
let client_login_start_result = ClientLogin::<CS>::start(
2020-11-02 13:51:43 -08:00
&mut client_login_start_rng,
2020-12-12 21:53:33 -08:00
password,
ClientLoginStartParameters::WithInfo(info1.to_vec()),
2020-11-02 13:51:43 -08:00
)
.unwrap();
2020-12-12 21:53:33 -08:00
let credential_request_bytes = client_login_start_result.message.serialize().to_vec();
let client_login_state = client_login_start_result.state.serialize().to_vec();
2020-06-05 09:35:14 -07:00
let mut server_e_sk_and_nonce_rng = CycleRng::new(
[
server_e_kp.private().to_arr().to_vec(),
server_nonce.to_vec(),
]
.concat(),
);
2020-11-16 14:05:43 -08:00
let server_login_start_result = ServerLogin::<CS>::start(
&mut server_e_sk_and_nonce_rng,
2020-06-05 09:35:14 -07:00
password_file,
server_s_kp.private(),
2020-12-12 21:53:33 -08:00
client_login_start_result.message,
ServerLoginStartParameters::WithInfoAndIdentifiers(
einfo2.to_vec(),
id_u.to_vec(),
id_s.to_vec(),
),
2020-06-05 09:35:14 -07:00
)
.unwrap();
2020-12-12 21:53:33 -08:00
let credential_response_bytes = server_login_start_result.message.serialize().to_vec();
let server_login_state = server_login_start_result.state.serialize().to_vec();
2020-11-16 14:05:43 -08:00
let client_login_finish_result = client_login_start_result
2020-12-12 21:53:33 -08:00
.state
2020-11-16 14:05:43 -08:00
.finish(
2020-12-12 21:53:33 -08:00
server_login_start_result.message,
ClientLoginFinishParameters::WithIdentifiers(id_u.to_vec(), id_s.to_vec()),
2020-11-16 14:05:43 -08:00
)
2020-06-05 09:35:14 -07:00
.unwrap();
let credential_finalization_bytes = client_login_finish_result.message.serialize();
2020-06-05 09:35:14 -07:00
TestVectorParameters {
2020-09-22 08:50:39 -04:00
client_s_pk: client_s_kp.public().to_arr().to_vec(),
client_s_sk: client_s_kp.private().to_arr().to_vec(),
client_e_pk: client_e_kp.public().to_arr().to_vec(),
client_e_sk: client_e_kp.private().to_arr().to_vec(),
server_s_pk: server_s_kp.public().to_arr().to_vec(),
server_s_sk: server_s_kp.private().to_arr().to_vec(),
server_e_pk: server_e_kp.public().to_arr().to_vec(),
server_e_sk: server_e_kp.private().to_arr().to_vec(),
2020-11-02 13:51:43 -08:00
id_u: id_u.to_vec(),
id_s: id_s.to_vec(),
2020-06-05 09:35:14 -07:00
password: password.to_vec(),
blinding_factor: blinding_factor_bytes.to_vec(),
oprf_key: oprf_key_bytes.to_vec(),
envelope_nonce: envelope_nonce.to_vec(),
client_nonce: client_nonce.to_vec(),
server_nonce: server_nonce.to_vec(),
info1: info1.to_vec(),
einfo2: einfo2.to_vec(),
2020-12-12 21:53:33 -08:00
registration_request: registration_request_bytes,
registration_response: registration_response_bytes,
registration_upload: registration_upload_bytes,
2020-12-12 21:53:33 -08:00
credential_request: credential_request_bytes,
credential_response: credential_response_bytes,
credential_finalization: credential_finalization_bytes,
2020-06-05 09:35:14 -07:00
password_file: password_file_bytes,
client_registration_state,
server_registration_state,
client_login_state,
server_login_state,
session_key: client_login_finish_result.session_key,
2020-12-12 21:53:33 -08:00
export_key: client_registration_finish_result.export_key.to_vec(),
2020-06-05 09:35:14 -07:00
}
}
#[test]
fn generate_test_vectors() {
2021-01-25 13:20:36 -08:00
let parameters = generate_parameters::<RistrettoSha5123dhNoSlowHash>();
2020-06-05 09:35:14 -07:00
println!("{}", stringify_test_vectors(&parameters));
}
#[test]
2020-12-12 21:53:33 -08:00
fn test_registration_request() -> Result<(), ProtocolError> {
2020-06-05 09:35:14 -07:00
let parameters = populate_test_vectors(&serde_json::from_str(TEST_VECTOR).unwrap());
2021-01-25 13:20:36 -08:00
let mut rng = CycleRng::new(parameters.blinding_factor.to_vec());
let client_registration_start_result =
ClientRegistration::<RistrettoSha5123dhNoSlowHash>::start(&mut rng, &parameters.password)?;
2020-12-12 21:53:33 -08:00
assert_eq!(
hex::encode(&parameters.registration_request),
hex::encode(client_registration_start_result.message.serialize())
);
2020-06-05 09:35:14 -07:00
assert_eq!(
hex::encode(&parameters.client_registration_state),
hex::encode(client_registration_start_result.state.serialize())
2020-06-05 09:35:14 -07:00
);
Ok(())
}
#[test]
2020-12-12 21:53:33 -08:00
fn test_registration_response() -> Result<(), ProtocolError> {
2020-06-05 09:35:14 -07:00
let parameters = populate_test_vectors(&serde_json::from_str(TEST_VECTOR).unwrap());
let mut oprf_key_rng = CycleRng::new(parameters.oprf_key);
2021-01-25 13:20:36 -08:00
let server_registration_start_result =
ServerRegistration::<RistrettoSha5123dhNoSlowHash>::start(
&mut oprf_key_rng,
RegistrationRequest::deserialize(&parameters.registration_request[..])?,
&Key::try_from(&parameters.server_s_pk[..])?,
2021-01-25 13:20:36 -08:00
)?;
2020-12-12 21:53:33 -08:00
assert_eq!(
hex::encode(parameters.registration_response),
hex::encode(server_registration_start_result.message.serialize())
);
2020-06-05 09:35:14 -07:00
assert_eq!(
hex::encode(&parameters.server_registration_state),
hex::encode(server_registration_start_result.state.serialize())
2020-06-05 09:35:14 -07:00
);
Ok(())
}
#[test]
fn test_registration_upload() -> Result<(), ProtocolError> {
2020-06-05 09:35:14 -07:00
let parameters = populate_test_vectors(&serde_json::from_str(TEST_VECTOR).unwrap());
let client_s_sk_and_nonce: Vec<u8> =
[parameters.client_s_sk, parameters.envelope_nonce].concat();
let mut finish_registration_rng = CycleRng::new(client_s_sk_and_nonce);
let result = ClientRegistration::<RistrettoSha5123dhNoSlowHash>::deserialize(
2020-06-05 09:35:14 -07:00
&parameters.client_registration_state[..],
2020-12-09 12:49:59 -08:00
)?
.finish(
2020-06-05 09:35:14 -07:00
&mut finish_registration_rng,
RegistrationResponse::deserialize(&parameters.registration_response[..])?,
ClientRegistrationFinishParameters::WithIdentifiers(parameters.id_u, parameters.id_s),
2020-12-09 12:49:59 -08:00
)?;
2020-12-12 21:53:33 -08:00
assert_eq!(
hex::encode(parameters.registration_upload),
2020-12-12 21:53:33 -08:00
hex::encode(result.message.serialize())
);
2020-06-05 09:35:14 -07:00
assert_eq!(
hex::encode(parameters.export_key),
2020-12-12 21:53:33 -08:00
hex::encode(result.export_key.to_vec())
2020-06-05 09:35:14 -07:00
);
Ok(())
}
#[test]
2020-12-09 12:49:59 -08:00
fn test_password_file() -> Result<(), ProtocolError> {
2020-06-05 09:35:14 -07:00
let parameters = populate_test_vectors(&serde_json::from_str(TEST_VECTOR).unwrap());
let server_registration = ServerRegistration::<RistrettoSha5123dhNoSlowHash>::deserialize(
&parameters.server_registration_state[..],
2020-12-09 12:49:59 -08:00
)?;
let password_file = server_registration.finish(RegistrationUpload::deserialize(
&parameters.registration_upload[..],
)?)?;
2020-12-12 21:53:33 -08:00
2020-06-05 09:35:14 -07:00
assert_eq!(
hex::encode(parameters.password_file),
hex::encode(password_file.serialize())
2020-06-05 09:35:14 -07:00
);
Ok(())
}
#[test]
2020-12-12 21:53:33 -08:00
fn test_credential_request() -> Result<(), ProtocolError> {
2020-06-05 09:35:14 -07:00
let parameters = populate_test_vectors(&serde_json::from_str(TEST_VECTOR).unwrap());
2021-01-25 13:20:36 -08:00
let client_login_start_rng = [
parameters.blinding_factor,
2020-06-05 09:35:14 -07:00
parameters.client_e_sk,
parameters.client_nonce,
]
.concat();
2021-01-25 13:20:36 -08:00
let mut client_login_start_rng = CycleRng::new(client_login_start_rng);
let client_login_start_result = ClientLogin::<RistrettoSha5123dhNoSlowHash>::start(
&mut client_login_start_rng,
2020-12-12 21:53:33 -08:00
&parameters.password,
ClientLoginStartParameters::WithInfo(parameters.info1),
2020-12-09 12:49:59 -08:00
)?;
2020-11-16 14:05:43 -08:00
assert_eq!(
2020-12-12 21:53:33 -08:00
hex::encode(&parameters.credential_request),
hex::encode(client_login_start_result.message.serialize())
2020-11-16 14:05:43 -08:00
);
2020-06-05 09:35:14 -07:00
assert_eq!(
hex::encode(&parameters.client_login_state),
hex::encode(client_login_start_result.state.serialize())
2020-06-05 09:35:14 -07:00
);
Ok(())
}
#[test]
2020-12-12 21:53:33 -08:00
fn test_credential_response() -> Result<(), ProtocolError> {
2020-06-05 09:35:14 -07:00
let parameters = populate_test_vectors(&serde_json::from_str(TEST_VECTOR).unwrap());
let mut server_e_sk_and_nonce_rng =
CycleRng::new([parameters.server_e_sk, parameters.server_nonce].concat());
2021-01-25 13:20:36 -08:00
let server_login_start_result = ServerLogin::<RistrettoSha5123dhNoSlowHash>::start(
&mut server_e_sk_and_nonce_rng,
ServerRegistration::deserialize(&parameters.password_file[..])?,
&Key::try_from(&parameters.server_s_sk[..])?,
2021-01-25 13:20:36 -08:00
CredentialRequest::<RistrettoSha5123dhNoSlowHash>::deserialize(
&parameters.credential_request[..],
)?,
ServerLoginStartParameters::WithInfoAndIdentifiers(
parameters.einfo2.to_vec(),
parameters.id_u,
parameters.id_s,
),
2020-12-09 12:49:59 -08:00
)?;
assert_eq!(
hex::encode(&parameters.info1),
hex::encode(server_login_start_result.plain_info),
);
2020-11-16 14:05:43 -08:00
assert_eq!(
2020-12-12 21:53:33 -08:00
hex::encode(&parameters.credential_response),
hex::encode(server_login_start_result.message.serialize())
2020-11-16 14:05:43 -08:00
);
2020-06-05 09:35:14 -07:00
assert_eq!(
hex::encode(&parameters.server_login_state),
hex::encode(server_login_start_result.state.serialize())
2020-06-05 09:35:14 -07:00
);
Ok(())
}
#[test]
fn test_credential_finalization() -> Result<(), ProtocolError> {
2020-06-05 09:35:14 -07:00
let parameters = populate_test_vectors(&serde_json::from_str(TEST_VECTOR).unwrap());
let client_login_finish_result = ClientLogin::<RistrettoSha5123dhNoSlowHash>::deserialize(
&parameters.client_login_state[..],
)?
.finish(
CredentialResponse::<RistrettoSha5123dhNoSlowHash>::deserialize(
&parameters.credential_response[..],
)?,
ClientLoginFinishParameters::WithIdentifiers(parameters.id_u, parameters.id_s),
)?;
2020-12-12 21:53:33 -08:00
assert_eq!(
hex::encode(&parameters.einfo2),
hex::encode(&client_login_finish_result.confidential_info)
);
assert_eq!(
hex::encode(&parameters.server_s_pk),
hex::encode(&client_login_finish_result.server_s_pk.to_arr().to_vec())
);
2020-06-05 09:35:14 -07:00
assert_eq!(
hex::encode(&parameters.session_key),
hex::encode(&client_login_finish_result.session_key)
2020-11-16 14:05:43 -08:00
);
assert_eq!(
hex::encode(&parameters.credential_finalization),
hex::encode(client_login_finish_result.message.serialize())
2020-06-05 09:35:14 -07:00
);
assert_eq!(
hex::encode(&parameters.export_key),
2020-11-16 14:05:43 -08:00
hex::encode(client_login_finish_result.export_key)
2020-06-05 09:35:14 -07:00
);
Ok(())
}
#[test]
fn test_server_login_finish() -> Result<(), ProtocolError> {
let parameters = populate_test_vectors(&serde_json::from_str(TEST_VECTOR).unwrap());
let server_login_result = ServerLogin::<RistrettoSha5123dhNoSlowHash>::deserialize(
&parameters.server_login_state[..],
)?
.finish(CredentialFinalization::deserialize(
&parameters.credential_finalization[..],
)?)?;
2020-12-12 21:53:33 -08:00
2020-06-05 09:35:14 -07:00
assert_eq!(
hex::encode(parameters.session_key),
hex::encode(server_login_result.session_key)
2020-06-05 09:35:14 -07:00
);
Ok(())
}
fn test_complete_flow(
registration_password: &[u8],
login_password: &[u8],
) -> Result<(), ProtocolError> {
let mut client_rng = OsRng;
let mut server_rng = OsRng;
2021-01-25 13:20:36 -08:00
let server_kp = RistrettoSha5123dhNoSlowHash::generate_random_keypair(&mut server_rng);
let client_registration_start_result =
ClientRegistration::<RistrettoSha5123dhNoSlowHash>::start(
&mut client_rng,
registration_password,
)?;
let server_registration_start_result =
ServerRegistration::<RistrettoSha5123dhNoSlowHash>::start(
&mut server_rng,
client_registration_start_result.message,
server_kp.public(),
)?;
let client_registration_finish_result = client_registration_start_result.state.finish(
&mut client_rng,
server_registration_start_result.message,
ClientRegistrationFinishParameters::default(),
)?;
2020-12-12 21:53:33 -08:00
let p_file = server_registration_start_result
.state
.finish(client_registration_finish_result.message)?;
2021-01-25 13:20:36 -08:00
let client_login_start_result = ClientLogin::<RistrettoSha5123dhNoSlowHash>::start(
2020-11-16 14:05:43 -08:00
&mut client_rng,
2020-12-12 21:53:33 -08:00
login_password,
2020-11-16 14:05:43 -08:00
ClientLoginStartParameters::default(),
)?;
2021-01-25 13:20:36 -08:00
let server_login_start_result = ServerLogin::<RistrettoSha5123dhNoSlowHash>::start(
2020-12-12 21:53:33 -08:00
&mut server_rng,
2020-07-13 15:23:29 -07:00
p_file,
&server_kp.private(),
2020-12-12 21:53:33 -08:00
client_login_start_result.message,
2020-11-16 14:05:43 -08:00
ServerLoginStartParameters::default(),
2020-07-13 15:23:29 -07:00
)?;
2020-06-05 09:35:14 -07:00
2020-12-12 21:53:33 -08:00
let client_login_result = client_login_start_result.state.finish(
server_login_start_result.message,
2020-11-16 14:05:43 -08:00
ClientLoginFinishParameters::default(),
);
2020-06-05 09:35:14 -07:00
if hex::encode(registration_password) == hex::encode(login_password) {
2020-11-16 14:05:43 -08:00
let client_login_finish_result = client_login_result?;
let server_login_finish_result = server_login_start_result
2020-12-12 21:53:33 -08:00
.state
.finish(client_login_finish_result.message)?;
2020-06-05 09:35:14 -07:00
assert_eq!(
hex::encode(server_login_finish_result.session_key),
hex::encode(client_login_finish_result.session_key)
2020-06-05 09:35:14 -07:00
);
assert_eq!(
2020-12-12 21:53:33 -08:00
hex::encode(client_registration_finish_result.export_key),
2020-11-16 14:05:43 -08:00
hex::encode(client_login_finish_result.export_key)
2020-06-05 09:35:14 -07:00
);
} else {
let res = matches!(
client_login_result,
Err(ProtocolError::VerificationError(
PakeError::InvalidLoginError
))
);
2020-06-05 09:35:14 -07:00
assert!(res);
}
Ok(())
}
#[test]
fn test_complete_flow_success() -> Result<(), ProtocolError> {
test_complete_flow(b"good password", b"good password")
}
#[test]
fn test_complete_flow_fail() -> Result<(), ProtocolError> {
test_complete_flow(b"good password", b"bad password")
}