Fixing test vectors and use of SHA512 (#120)
This commit is contained in:
@@ -55,7 +55,7 @@ pub struct TestVectorParameters {
|
||||
pub registration_upload: Vec<u8>,
|
||||
pub credential_request: Vec<u8>,
|
||||
pub credential_response: Vec<u8>,
|
||||
pub key_exchange: Vec<u8>,
|
||||
pub credential_finalization: Vec<u8>,
|
||||
client_registration_state: Vec<u8>,
|
||||
server_registration_state: Vec<u8>,
|
||||
client_login_state: Vec<u8>,
|
||||
@@ -67,37 +67,37 @@ pub struct TestVectorParameters {
|
||||
|
||||
static TEST_VECTOR: &str = r#"
|
||||
{
|
||||
"client_s_pk": "64b071d0b8eccc39673b16384e86df49f258a12bad24f21f5d5f4a9a8f45561c",
|
||||
"client_s_sk": "98a23d0757ac5c7aba8b218c5643c3a3029fb815a656de24cfc05df877925809",
|
||||
"client_e_pk": "3a575317d7a6269bc4e76074ec906d8886b4c135fb6b590972f6fdd6c1a55676",
|
||||
"client_e_sk": "163b91328785a5e84e21579e941be1dd7bdbc44d4c959f603d7f79417ab6b201",
|
||||
"server_s_pk": "fc0d7d59e0fabe7c876c01c8d5408fc60dc5fdec7b89acdc5af2bc7c0de26d75",
|
||||
"server_s_sk": "f7068582fdf2a57f7da63e6f5142abda805a7b508ce171c84f58a4e5e634a406",
|
||||
"server_e_pk": "8e32a64f670b9d2115eba0006b00667972523bf2f8686933ef2a2819d6b5a13b",
|
||||
"server_e_sk": "a3a06d81eeb60aeedaee96769149ae5f45184eec66e1b2bdeb04114d27019206",
|
||||
"client_s_pk": "ba8c7e239ed64ea1e6068b52cbd5a34ba6f55d635d20a4593884dc271865ea63",
|
||||
"client_s_sk": "edb5e886441ddcd4fdd80593d9ea7b7f82f284fcc1d565b802e99997457b960a",
|
||||
"client_e_pk": "08973113b27d6f2291aaaeb92f34a8438d279a48b1b412bddbf2785be660e479",
|
||||
"client_e_sk": "28fb3aadbc2716844d8de562d35e61914da734dcea0fa6ebd79603ef9eff4e01",
|
||||
"server_s_pk": "b67d948b98eecfb516a626fab94170e490ccd90da05fce94a016c4d5d6b7136a",
|
||||
"server_s_sk": "52350a684c353e39bbaadeb042b2de94226a493f6ae172b7fc45408bbfda6401",
|
||||
"server_e_pk": "42103d44b03f3886fe3e419b1b96521fa5a706bb1a4e003907daa381960d664a",
|
||||
"server_e_sk": "564e113d5b2784fcf3a55d5ca48512a2fd5c3c393753f6cfd157cb712b317c04",
|
||||
"id_u": "696455",
|
||||
"id_s": "696453",
|
||||
"password": "70617373776f7264",
|
||||
"blinding_factor": "3497d8c6728a3dc0873e363dcd60acd95f7897d15d33cdf1d49c8b856f061900",
|
||||
"oprf_key": "c728d1ea06fb94f577ef63d50d1645e9fea14575987971e4a64e05dda367c703",
|
||||
"envelope_nonce": "d7d138a3a4cb796662814391f5221e05b66438a92e5f57cc9624e6227da34eab",
|
||||
"client_nonce": "ad87ae4609f1f56aeb1de0f4760120fa75ceff39751dffc35d25ff3f2896bb60",
|
||||
"server_nonce": "d7a8cd7cd2c4f0f7650390f6f2d4858ae99ac79f2769a9e15583d570b11c434c",
|
||||
"blinding_factor": "a70b37951d84ed312a0a8e025b71eafdd362b4e7db872881762d506a271b6e07",
|
||||
"oprf_key": "1eaf3cdd64da67e17e3364182f00ed0c323bfb44b20a1b7e0025a0334ab6d40d",
|
||||
"envelope_nonce": "5dba53e994e82b6d76353341102791cdfb1c2b460e1f913c5741a9c8cf2017c9",
|
||||
"client_nonce": "488244dbf75f86ebaa30307773d3e0eabccb91be349abef8a69c458dbf236e4c",
|
||||
"server_nonce": "13cc5ceb7687d80293005e7f9452ce104d1bac6598dd2265f184cacd558d6b31",
|
||||
"info1": "696e666f31",
|
||||
"einfo2": "65696e666f32",
|
||||
"registration_request": "002096738fbc9883a85a8067763abe33efadce0adb2bc64857d3cd0a6cc92e9ce325",
|
||||
"registration_response": "0020a86baffac435f6239cfe5f61d823e7458ac211dce1d3c364375e9d1f40843c750020fc0d7d59e0fabe7c876c01c8d5408fc60dc5fdec7b89acdc5af2bc7c0de26d75",
|
||||
"registration_upload": "01d7d138a3a4cb796662814391f5221e05b66438a92e5f57cc9624e6227da34eab002229979df679067f8baecbbe063ee97e2b5be88c2b99163d595b32a74d640138771d70002c0020fc0d7d59e0fabe7c876c01c8d5408fc60dc5fdec7b89acdc5af2bc7c0de26d750003696455000369645300400b6119d0de405d85e0e6b1748eb66194b1768ea71fd47c103f8e1fcbc837add2b282889469921798d626a02b6dd763ee9cd028f333386a19c13a3d4d4c6a3312002064b071d0b8eccc39673b16384e86df49f258a12bad24f21f5d5f4a9a8f45561c",
|
||||
"credential_request": "002096738fbc9883a85a8067763abe33efadce0adb2bc64857d3cd0a6cc92e9ce325ad87ae4609f1f56aeb1de0f4760120fa75ceff39751dffc35d25ff3f2896bb600005696e666f313a575317d7a6269bc4e76074ec906d8886b4c135fb6b590972f6fdd6c1a55676",
|
||||
"credential_response": "0020a86baffac435f6239cfe5f61d823e7458ac211dce1d3c364375e9d1f40843c750020fc0d7d59e0fabe7c876c01c8d5408fc60dc5fdec7b89acdc5af2bc7c0de26d7501d7d138a3a4cb796662814391f5221e05b66438a92e5f57cc9624e6227da34eab002229979df679067f8baecbbe063ee97e2b5be88c2b99163d595b32a74d640138771d70002c0020fc0d7d59e0fabe7c876c01c8d5408fc60dc5fdec7b89acdc5af2bc7c0de26d750003696455000369645300400b6119d0de405d85e0e6b1748eb66194b1768ea71fd47c103f8e1fcbc837add2b282889469921798d626a02b6dd763ee9cd028f333386a19c13a3d4d4c6a3312a3a06d81eeb60aeedaee96769149ae5f45184eec66e1b2bdeb04114d270192068e32a64f670b9d2115eba0006b00667972523bf2f8686933ef2a2819d6b5a13b00066c7c22ba8dbae814beb02d1b89659379ca61697cd3212169d387b61f5659b77f6993833a1542a692cb5ad259244a1d53a51243fb5366a5bd8e4ed7eb2f50caa9a568fc8267e9",
|
||||
"key_exchange": "3f9d3754920514328529bf4e78d4c2d0f411dfb871a4ef83c87d3462119b836381bdc651096cb62ca96de5f4b5a9acaa87b180d2acefebd2f3feb5785adcd038",
|
||||
"client_registration_state": "3497d8c6728a3dc0873e363dcd60acd95f7897d15d33cdf1d49c8b856f06190070617373776f7264",
|
||||
"client_login_state": "3497d8c6728a3dc0873e363dcd60acd95f7897d15d33cdf1d49c8b856f061900163b91328785a5e84e21579e941be1dd7bdbc44d4c959f603d7f79417ab6b201ad87ae4609f1f56aeb1de0f4760120fa75ceff39751dffc35d25ff3f2896bb607962b421c96efcfdb465365eea8fe9914e6ac5c0b216e2b07c7fb3b17fa0d21ee8c37373fee8dfec6a5eae559f21c8c4e1505ed974ce8baff3529304cb4d90b570617373776f7264",
|
||||
"server_registration_state": "c728d1ea06fb94f577ef63d50d1645e9fea14575987971e4a64e05dda367c703",
|
||||
"server_login_state": "644fb6d36a91e0197f5d82d17f04354f9e24794988923160534d99c80970b66fe54a3d8b36d5a4d21eaf0fa7bb4717ed1741be3f7d24b96d27aeb7f4b59a72bf80d0d969a2398ea5a5232d3257c60516dcc0de65b66fc5a07b8e2f58523eb0079ac09798a23cee0e31454594d25e40f34b10b92195fea6f90e197c0fbc8658bb3435bb6179370029f03d2dbd5efa2d0f8b8f4f69ca42ef70245686f70c2d7f326d0a8bc596145099e6a668d23ce1a93f9a3f83bfdddde15c78f467a639f124dd",
|
||||
"password_file": "c728d1ea06fb94f577ef63d50d1645e9fea14575987971e4a64e05dda367c70364b071d0b8eccc39673b16384e86df49f258a12bad24f21f5d5f4a9a8f45561c01d7d138a3a4cb796662814391f5221e05b66438a92e5f57cc9624e6227da34eab002229979df679067f8baecbbe063ee97e2b5be88c2b99163d595b32a74d640138771d70002c0020fc0d7d59e0fabe7c876c01c8d5408fc60dc5fdec7b89acdc5af2bc7c0de26d750003696455000369645300400b6119d0de405d85e0e6b1748eb66194b1768ea71fd47c103f8e1fcbc837add2b282889469921798d626a02b6dd763ee9cd028f333386a19c13a3d4d4c6a3312",
|
||||
"export_key": "005ba69bed794d3e24ac750ed575165a0235e103d1f8d7ca1b9aa0cfc2c3d9b6",
|
||||
"shared_secret": "3435bb6179370029f03d2dbd5efa2d0f8b8f4f69ca42ef70245686f70c2d7f326d0a8bc596145099e6a668d23ce1a93f9a3f83bfdddde15c78f467a639f124dd"
|
||||
"registration_request": "ecf819ef83351e4c75e016ef845b62a12c14f397328960574935a42e04e0fa42",
|
||||
"registration_response": "2e9bf80e5c101ee2d391ff2aec06af97af17f443fc93a5cc98189681cb943d700020b67d948b98eecfb516a626fab94170e490ccd90da05fce94a016c4d5d6b7136a",
|
||||
"registration_upload": "0020ba8c7e239ed64ea1e6068b52cbd5a34ba6f55d635d20a4593884dc271865ea63015dba53e994e82b6d76353341102791cdfb1c2b460e1f913c5741a9c8cf2017c90022f11b89b207eb0735f2bdb2a9968bc9d7c1c962fd0274b4fc1fff2466c769d3710586a3a21ac8ecf13aafe2dc5460eb2f52d8f760396a17beeaf1ef3d1e4e50dd906555832fc51fc474554cb9ff063f6685f9043efc08fd6816666833d68d3b0eb6d9",
|
||||
"credential_request": "ecf819ef83351e4c75e016ef845b62a12c14f397328960574935a42e04e0fa42488244dbf75f86ebaa30307773d3e0eabccb91be349abef8a69c458dbf236e4c0005696e666f3108973113b27d6f2291aaaeb92f34a8438d279a48b1b412bddbf2785be660e479",
|
||||
"credential_response": "2e9bf80e5c101ee2d391ff2aec06af97af17f443fc93a5cc98189681cb943d700020b67d948b98eecfb516a626fab94170e490ccd90da05fce94a016c4d5d6b7136a015dba53e994e82b6d76353341102791cdfb1c2b460e1f913c5741a9c8cf2017c90022f11b89b207eb0735f2bdb2a9968bc9d7c1c962fd0274b4fc1fff2466c769d3710586a3a21ac8ecf13aafe2dc5460eb2f52d8f760396a17beeaf1ef3d1e4e50dd906555832fc51fc474554cb9ff063f6685f9043efc08fd6816666833d68d3b0eb6d913cc5ceb7687d80293005e7f9452ce104d1bac6598dd2265f184cacd558d6b3142103d44b03f3886fe3e419b1b96521fa5a706bb1a4e003907daa381960d664a0006a0f4de671e13c37b24e29138ff9d3df3d55c3b822fedee8dcefd643a1deab7cda5aa1c20f31a0c2a1823c8de3e793f50b257833788b75609fb6c5c4a9cad225f3a981c4ff7b2",
|
||||
"credential_finalization": "0640114ec21fbad6da11c61dfa77a48026646a2a1bd091ef5c9dc46b45f9e53c72f5d714e026d808b6de8911947eef437e9f6a6e969e1ea13f2f4880adc7c879",
|
||||
"client_registration_state": "a70b37951d84ed312a0a8e025b71eafdd362b4e7db872881762d506a271b6e0770617373776f7264",
|
||||
"client_login_state": "a70b37951d84ed312a0a8e025b71eafdd362b4e7db872881762d506a271b6e0700a728fb3aadbc2716844d8de562d35e61914da734dcea0fa6ebd79603ef9eff4e01488244dbf75f86ebaa30307773d3e0eabccb91be349abef8a69c458dbf236e4cecf819ef83351e4c75e016ef845b62a12c14f397328960574935a42e04e0fa42488244dbf75f86ebaa30307773d3e0eabccb91be349abef8a69c458dbf236e4c0005696e666f3108973113b27d6f2291aaaeb92f34a8438d279a48b1b412bddbf2785be660e47970617373776f7264",
|
||||
"server_registration_state": "1eaf3cdd64da67e17e3364182f00ed0c323bfb44b20a1b7e0025a0334ab6d40d",
|
||||
"server_login_state": "4952acf61167e6d0e799572827724fdf8c80bda8c62ac28deb68d125661dade2cc1136e634d5fb93f1de4d170ae3e2f5885e333ac3b72d630ab56618c2247fa4d5968eefd69cd270ed14fbcb39627fea9a93cd18175e1b5cfceb06f705bbcb5ecddcd0602aacd7cb358f3273b1099895210bf8baa37d2fab5ed8c092fe9e5739bc6c50cf08ca7d4f4107d48057507480e0c9534b4f04d77cd5156cbd112565d8a2d5beaa473003dcf8dd82d4046648a701c72afeed0f627fcb782627dfaed3ca",
|
||||
"password_file": "1eaf3cdd64da67e17e3364182f00ed0c323bfb44b20a1b7e0025a0334ab6d40dba8c7e239ed64ea1e6068b52cbd5a34ba6f55d635d20a4593884dc271865ea63015dba53e994e82b6d76353341102791cdfb1c2b460e1f913c5741a9c8cf2017c90022f11b89b207eb0735f2bdb2a9968bc9d7c1c962fd0274b4fc1fff2466c769d3710586a3a21ac8ecf13aafe2dc5460eb2f52d8f760396a17beeaf1ef3d1e4e50dd906555832fc51fc474554cb9ff063f6685f9043efc08fd6816666833d68d3b0eb6d9",
|
||||
"export_key": "2b86667de895e4d2c15b93bc70f0aa2df67b83987fa53deac9473697e2fade045e0fd0e4af478ccff52165c1467272993da34dcb3baa45aa59cf9d817e6c6bcb",
|
||||
"shared_secret": "bc6c50cf08ca7d4f4107d48057507480e0c9534b4f04d77cd5156cbd112565d8a2d5beaa473003dcf8dd82d4046648a701c72afeed0f627fcb782627dfaed3ca"
|
||||
}
|
||||
"#;
|
||||
|
||||
@@ -132,7 +132,7 @@ fn populate_test_vectors(values: &Value) -> TestVectorParameters {
|
||||
registration_upload: decode(&values, "registration_upload").unwrap(),
|
||||
credential_request: decode(&values, "credential_request").unwrap(),
|
||||
credential_response: decode(&values, "credential_response").unwrap(),
|
||||
key_exchange: decode(&values, "key_exchange").unwrap(),
|
||||
credential_finalization: decode(&values, "credential_finalization").unwrap(),
|
||||
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(),
|
||||
@@ -211,7 +211,13 @@ fn stringify_test_vectors(p: &TestVectorParameters) -> String {
|
||||
)
|
||||
.as_str(),
|
||||
);
|
||||
s.push_str(format!("\"key_exchange\": \"{}\",\n", hex::encode(&p.key_exchange)).as_str());
|
||||
s.push_str(
|
||||
format!(
|
||||
"\"credential_finalization\": \"{}\",\n",
|
||||
hex::encode(&p.credential_finalization)
|
||||
)
|
||||
.as_str(),
|
||||
);
|
||||
s.push_str(
|
||||
format!(
|
||||
"\"client_registration_state\": \"{}\",\n",
|
||||
@@ -349,9 +355,15 @@ fn generate_parameters<CS: CipherSuite>() -> TestVectorParameters {
|
||||
let credential_request_bytes = client_login_start_result.message.serialize().to_vec();
|
||||
let client_login_state = client_login_start_result.state.to_bytes().to_vec();
|
||||
|
||||
let mut server_e_sk_rng = CycleRng::new(server_e_kp.private().to_arr().to_vec());
|
||||
let mut server_e_sk_and_nonce_rng = CycleRng::new(
|
||||
[
|
||||
server_e_kp.private().to_arr().to_vec(),
|
||||
server_nonce.to_vec(),
|
||||
]
|
||||
.concat(),
|
||||
);
|
||||
let server_login_start_result = ServerLogin::<CS>::start(
|
||||
&mut server_e_sk_rng,
|
||||
&mut server_e_sk_and_nonce_rng,
|
||||
password_file,
|
||||
server_s_kp.private(),
|
||||
client_login_start_result.message,
|
||||
@@ -372,7 +384,7 @@ fn generate_parameters<CS: CipherSuite>() -> TestVectorParameters {
|
||||
ClientLoginFinishParameters::WithIdentifiers(id_u.to_vec(), id_s.to_vec()),
|
||||
)
|
||||
.unwrap();
|
||||
let key_exchange_bytes = client_login_finish_result.message.to_bytes().to_vec();
|
||||
let credential_finalization_bytes = client_login_finish_result.message.to_bytes().to_vec();
|
||||
|
||||
TestVectorParameters {
|
||||
client_s_pk: client_s_kp.public().to_arr().to_vec(),
|
||||
@@ -398,7 +410,7 @@ fn generate_parameters<CS: CipherSuite>() -> TestVectorParameters {
|
||||
registration_upload: registration_upload_bytes,
|
||||
credential_request: credential_request_bytes,
|
||||
credential_response: credential_response_bytes,
|
||||
key_exchange: key_exchange_bytes,
|
||||
credential_finalization: credential_finalization_bytes,
|
||||
password_file: password_file_bytes,
|
||||
client_registration_state,
|
||||
server_registration_state,
|
||||
@@ -529,9 +541,10 @@ fn test_credential_request() -> Result<(), ProtocolError> {
|
||||
fn test_credential_response() -> Result<(), ProtocolError> {
|
||||
let parameters = populate_test_vectors(&serde_json::from_str(TEST_VECTOR).unwrap());
|
||||
|
||||
let mut server_e_sk_rng = CycleRng::new(parameters.server_e_sk);
|
||||
let mut server_e_sk_and_nonce_rng =
|
||||
CycleRng::new([parameters.server_e_sk, parameters.server_nonce].concat());
|
||||
let server_login_start_result = ServerLogin::<RistrettoSha5123dhNoSlowHash>::start(
|
||||
&mut server_e_sk_rng,
|
||||
&mut server_e_sk_and_nonce_rng,
|
||||
ServerRegistration::try_from(¶meters.password_file[..]).unwrap(),
|
||||
&Key::try_from(¶meters.server_s_sk[..]).unwrap(),
|
||||
CredentialRequest::<RistrettoSha5123dhNoSlowHash>::deserialize(
|
||||
@@ -560,7 +573,7 @@ fn test_credential_response() -> Result<(), ProtocolError> {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_key_exchange() -> Result<(), ProtocolError> {
|
||||
fn test_credential_finalization() -> Result<(), ProtocolError> {
|
||||
let parameters = populate_test_vectors(&serde_json::from_str(TEST_VECTOR).unwrap());
|
||||
|
||||
let client_login_finish_result =
|
||||
@@ -586,7 +599,7 @@ fn test_key_exchange() -> Result<(), ProtocolError> {
|
||||
hex::encode(&client_login_finish_result.shared_secret)
|
||||
);
|
||||
assert_eq!(
|
||||
hex::encode(¶meters.key_exchange),
|
||||
hex::encode(¶meters.credential_finalization),
|
||||
hex::encode(client_login_finish_result.message.to_bytes())
|
||||
);
|
||||
assert_eq!(
|
||||
@@ -604,7 +617,7 @@ fn test_server_login_finish() -> Result<(), ProtocolError> {
|
||||
let server_login_result =
|
||||
ServerLogin::<RistrettoSha5123dhNoSlowHash>::try_from(¶meters.server_login_state[..])?
|
||||
.finish(CredentialFinalization::try_from(
|
||||
¶meters.key_exchange[..],
|
||||
¶meters.credential_finalization[..],
|
||||
)?)?;
|
||||
|
||||
assert_eq!(
|
||||
+2
-1
@@ -3,6 +3,7 @@
|
||||
// This source code is licensed under the MIT license found in the
|
||||
// LICENSE file in the root directory of this source tree.
|
||||
|
||||
mod full_test;
|
||||
pub mod mock_rng;
|
||||
mod opaque_ke_test;
|
||||
mod opaque_test_vectors;
|
||||
mod voprf_test_vectors;
|
||||
|
||||
@@ -0,0 +1,430 @@
|
||||
// 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, errors::*, key_exchange::tripledh::TripleDH, keypair::Key, opaque::*,
|
||||
slow_hash::NoOpHash, tests::mock_rng::CycleRng, *,
|
||||
};
|
||||
use curve25519_dalek::ristretto::RistrettoPoint;
|
||||
use rand_core::OsRng;
|
||||
use serde_json::Value;
|
||||
use std::convert::TryFrom;
|
||||
|
||||
// Tests
|
||||
// =====
|
||||
|
||||
struct Ristretto255Sha512NoSlowHash;
|
||||
impl CipherSuite for Ristretto255Sha512NoSlowHash {
|
||||
type Group = RistrettoPoint;
|
||||
type KeyExchange = TripleDH;
|
||||
type Hash = sha2::Sha512;
|
||||
type SlowHash = NoOpHash;
|
||||
}
|
||||
|
||||
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>,
|
||||
pub client_identifier: Vec<u8>,
|
||||
pub server_identifier: Vec<u8>,
|
||||
pub password: Vec<u8>,
|
||||
pub blinding_factor_registration: 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 info2: Vec<u8>,
|
||||
pub registration_request: Vec<u8>,
|
||||
pub registration_response: Vec<u8>,
|
||||
pub registration_upload: Vec<u8>,
|
||||
pub credential_request: Vec<u8>,
|
||||
pub blinding_factor_login: Vec<u8>,
|
||||
pub credential_response: Vec<u8>,
|
||||
pub credential_finalization: Vec<u8>,
|
||||
pub password_file: Vec<u8>,
|
||||
pub export_key: Vec<u8>,
|
||||
pub shared_secret: Vec<u8>,
|
||||
}
|
||||
|
||||
static TEST_VECTOR: &str = r#"
|
||||
{
|
||||
"auth_key": "5da3dcc6721e638fa4eef769f7af5bd30f7132308d41fff00f0cf9745e9090235f75697a0dc58fe8692204c4702a20db4a6ee59119fe6ab4173322f06b896309",
|
||||
"blinding_factor_login": "ed8366feb6b1d05d1f46acb727061e43aadfafe9c10e5a64e7518d63e3263503",
|
||||
"blinding_factor_registration": "c604c785ada70d77a5256ae21767de8c3304115237d262134f5e46e512cf8e03",
|
||||
"client_e_pk": "645a5d8c715454a2ba77918d44234d9cbbd723d03113b68c9ea076ab4e776067",
|
||||
"client_e_sk": "9be30157b01e572d9ee296defd7bd2f98fed15fbbf3cbed847547d6759c73c08",
|
||||
"client_identifier": "0aa0f9643e2ecaf3075201e9e762371d1b5cdfac674494b2d5ed0b0908c46e5b",
|
||||
"client_nonce": "a9f275415d9bee6b86c2c390b7577c7684d70479c7e23bfbc01652a7464fb1cc",
|
||||
"client_s_pk": "0aa0f9643e2ecaf3075201e9e762371d1b5cdfac674494b2d5ed0b0908c46e5b",
|
||||
"client_s_sk": "8772da7da9af3fcdae2a23cf8a34a49954a56b48ae2f866b71113132664f0e09",
|
||||
"credential_finalization": "b8de4c989e5caefb57f5a506fd469c4e329aa3076d17a8c8648266c2c2db6f4c33be2161c11c63b7039459de0f9f7f9c5b6a429e6002ac03516ba3979fc970f7",
|
||||
"credential_request": "b68e0e356f8490fa9c3bed952e16cc02db21eda686b3c484f3d9d912caa41f76a9f275415d9bee6b86c2c390b7577c7684d70479c7e23bfbc01652a7464fb1cc000968656c6c6f20626f62645a5d8c715454a2ba77918d44234d9cbbd723d03113b68c9ea076ab4e776067",
|
||||
"credential_response": "e83812f06568d57b8cdfdcc90fe91454e21bd25dd2a1c32dd1599a2e4a4b6c35002008a499182bb67b86190e2d8315ca1ae4a6cdd503db50bed3d90cc7670dcb9f2b0090f17bbbfeaf88def8713679002f4825d936a5347afdf4d020a99167843056d60022147e90c0c40a3652bdef905ab2f61386a4119a121f3411c1da6463ac5d0c633c6e6eaf0eb0d45ab8afb746ccd00a1e96cbb2eca09cdc61520772b32978470dcdb0f8aaec7016681d431f194a447bea2c0be84c7191837e362f0f69b7f29676e15d0351c529e997a215d410ef6f387a2f1e708729d2316bf27b75138fb440020c1fcdbcae720a4acd4a44602024a9d6f2d536baf230f8301c9f9ff5113e229549fd05000f3b629da91fc6405e82b16c18ae4be1ff00020b37dfa8dbd7eeea4bef1c678693b2f1e2da0370e6792f5ab860fad7a098f0d5d00d4d4205aae4d70887fb28edc16f5f1268aa021dba8810909cb2f9e6",
|
||||
"envU": "0090f17bbbfeaf88def8713679002f4825d936a5347afdf4d020a99167843056d60022147e90c0c40a3652bdef905ab2f61386a4119a121f3411c1da6463ac5d0c633c6e6eaf0eb0d45ab8afb746ccd00a1e96cbb2eca09cdc61520772b32978470dcdb0f8aaec7016681d431f194a447bea2c0be84c7191837e362f0f69b7f29676e15d03",
|
||||
"envelope_nonce": "90f17bbbfeaf88def8713679002f4825d936a5347afdf4d020a99167843056d6",
|
||||
"export_key": "453f61eae9b840519eb025d2297eb31ad13c960deba40c2799d2cd4b5034161e1c13695877b460643386ed5e41d5ec9bf2bc845592469fab50abf77d4812fcf0",
|
||||
"handshake_secret": "67b75ff7291d68e20bdbc6a15209aba0c61b7b690d69f293db3761ad62f6014476daeb8ce1235e2d29404bdba3b843dbd544250751e51af747010bb25c310fd5",
|
||||
"info1": "68656c6c6f20626f62",
|
||||
"info2": "6772656574696e677320616c696365",
|
||||
"ke2": "44feeac8078ca91e22ac0133fe33890207c3d927ace293fffa66296c74e82e09ffb1ac00f76198e0ebe74eab722ac49173bdee616f32b3a7416ddee1d8075d54",
|
||||
"km2": "0d5b3bd8e1f6b937570b501d5647cb061276bba36cfc3213205c36d2240e8fe55f2338108f52947fd589ce344ce0a677ddb178c881deb4d075874ade133b99c7",
|
||||
"km3": "8ed3a633ad925fedcf19f9f4acca15f8bfbd147ba11e0950a2ae6c3efb6e41aef75faa20ae0f9104801bdb8a4edbd23a5cc19fe626a00c50e4718d8dedb180fd",
|
||||
"oprf_key": "5ed895206bfc53316d307b23e46ecc6623afb3086da74189a416012be037e50b",
|
||||
"password": "436f7272656374486f72736542617474657279537461706c65",
|
||||
"pseudorandom_pad": "145e17b21e779ffd82223e70913999b20088ceb7747cbfee5c0f12bd6c3e05736067",
|
||||
"registration_request": "241b621c417c0705b5ea7a8b7cdd5039fd61e6b63effe2a44418164c4d49003e",
|
||||
"registration_response": "1867301bcc67bdf8e640b7d6edcbe2a65488446417b50d30cdba66ccb379e572002008a499182bb67b86190e2d8315ca1ae4a6cdd503db50bed3d90cc7670dcb9f2b",
|
||||
"registration_upload": "00200aa0f9643e2ecaf3075201e9e762371d1b5cdfac674494b2d5ed0b0908c46e5b0090f17bbbfeaf88def8713679002f4825d936a5347afdf4d020a99167843056d60022147e90c0c40a3652bdef905ab2f61386a4119a121f3411c1da6463ac5d0c633c6e6eaf0eb0d45ab8afb746ccd00a1e96cbb2eca09cdc61520772b32978470dcdb0f8aaec7016681d431f194a447bea2c0be84c7191837e362f0f69b7f29676e15d03",
|
||||
"rwdU": "17eacc90e168aafd6cf5cbf4aba71e6c08d16800e4880a3fcc5252a1b5072ab7253942f3b4da8a2132863730970ca7a737b5bec96e038a8fa2915b4eeb678180",
|
||||
"server_e_pk": "bcae720a4acd4a44602024a9d6f2d536baf230f8301c9f9ff5113e229549fd05",
|
||||
"server_e_sk": "c02a638f90e8a9fd25b69252ec7465b7dd33aa905ba947c013b6e6be6edf3909",
|
||||
"server_identifier": "08a499182bb67b86190e2d8315ca1ae4a6cdd503db50bed3d90cc7670dcb9f2b",
|
||||
"server_nonce": "51c529e997a215d410ef6f387a2f1e708729d2316bf27b75138fb440020c1fcd",
|
||||
"server_s_pk": "08a499182bb67b86190e2d8315ca1ae4a6cdd503db50bed3d90cc7670dcb9f2b",
|
||||
"server_s_sk": "852b5300434b5f39f7885ee812255747793e04846b910cf9ae80a5a904bd3a03",
|
||||
"shared_secret": "d0336451e8de1df9a648772c86f97a1b9ed860297f0fafa13faa4e23bb44b9355ec196a25ba39e7db5b9102a06fa09ca778b10aee5acb11f4eb5826b1370e98c",
|
||||
"password_file": "5ed895206bfc53316d307b23e46ecc6623afb3086da74189a416012be037e50b0aa0f9643e2ecaf3075201e9e762371d1b5cdfac674494b2d5ed0b0908c46e5b0090f17bbbfeaf88def8713679002f4825d936a5347afdf4d020a99167843056d60022147e90c0c40a3652bdef905ab2f61386a4119a121f3411c1da6463ac5d0c633c6e6eaf0eb0d45ab8afb746ccd00a1e96cbb2eca09cdc61520772b32978470dcdb0f8aaec7016681d431f194a447bea2c0be84c7191837e362f0f69b7f29676e15d03"
|
||||
}
|
||||
"#;
|
||||
|
||||
fn decode(values: &Value, key: &str) -> Option<Vec<u8>> {
|
||||
values[key]
|
||||
.as_str()
|
||||
.and_then(|s| hex::decode(&s.to_string()).ok())
|
||||
}
|
||||
|
||||
macro_rules! parse {
|
||||
( $v:ident, $s:expr ) => {
|
||||
match decode(&$v, $s) {
|
||||
Some(x) => x,
|
||||
None => vec![],
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
fn populate_test_vectors(values: &Value) -> TestVectorParameters {
|
||||
TestVectorParameters {
|
||||
client_s_pk: parse!(values, "client_s_pk"),
|
||||
client_s_sk: parse!(values, "client_s_sk"),
|
||||
client_e_pk: parse!(values, "client_e_pk"),
|
||||
client_e_sk: parse!(values, "client_e_sk"),
|
||||
server_s_pk: parse!(values, "server_s_pk"),
|
||||
server_s_sk: parse!(values, "server_s_sk"),
|
||||
server_e_pk: parse!(values, "server_e_pk"),
|
||||
server_e_sk: parse!(values, "server_e_sk"),
|
||||
client_identifier: parse!(values, "client_identifier"),
|
||||
server_identifier: parse!(values, "server_identifier"),
|
||||
password: parse!(values, "password"),
|
||||
blinding_factor_registration: parse!(values, "blinding_factor_registration"),
|
||||
oprf_key: parse!(values, "oprf_key"),
|
||||
envelope_nonce: parse!(values, "envelope_nonce"),
|
||||
client_nonce: parse!(values, "client_nonce"),
|
||||
server_nonce: parse!(values, "server_nonce"),
|
||||
info1: parse!(values, "info1"),
|
||||
info2: parse!(values, "info2"),
|
||||
registration_request: parse!(values, "registration_request"),
|
||||
registration_response: parse!(values, "registration_response"),
|
||||
registration_upload: parse!(values, "registration_upload"),
|
||||
credential_request: parse!(values, "credential_request"),
|
||||
credential_response: parse!(values, "credential_response"),
|
||||
credential_finalization: parse!(values, "credential_finalization"),
|
||||
blinding_factor_login: parse!(values, "blinding_factor_login"),
|
||||
password_file: parse!(values, "password_file"),
|
||||
export_key: parse!(values, "export_key"),
|
||||
shared_secret: parse!(values, "shared_secret"),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_registration_request() -> Result<(), ProtocolError> {
|
||||
let parameters = populate_test_vectors(&serde_json::from_str(TEST_VECTOR).unwrap());
|
||||
let mut rng = CycleRng::new(parameters.blinding_factor_registration.to_vec());
|
||||
let client_registration_start_result =
|
||||
ClientRegistration::<Ristretto255Sha512NoSlowHash>::start(&mut rng, ¶meters.password)?;
|
||||
assert_eq!(
|
||||
hex::encode(¶meters.registration_request),
|
||||
hex::encode(client_registration_start_result.message.serialize())
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_registration_response() -> Result<(), ProtocolError> {
|
||||
let parameters = populate_test_vectors(&serde_json::from_str(TEST_VECTOR).unwrap());
|
||||
let mut oprf_key_rng = CycleRng::new(parameters.oprf_key);
|
||||
let server_registration_start_result =
|
||||
ServerRegistration::<Ristretto255Sha512NoSlowHash>::start(
|
||||
&mut oprf_key_rng,
|
||||
RegistrationRequest::deserialize(¶meters.registration_request[..]).unwrap(),
|
||||
&Key::try_from(¶meters.server_s_pk[..]).unwrap(),
|
||||
)?;
|
||||
assert_eq!(
|
||||
hex::encode(parameters.registration_response),
|
||||
hex::encode(server_registration_start_result.message.serialize())
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_registration_upload() -> Result<(), ProtocolError> {
|
||||
let parameters = populate_test_vectors(&serde_json::from_str(TEST_VECTOR).unwrap());
|
||||
|
||||
let mut rng = CycleRng::new(parameters.blinding_factor_registration.to_vec());
|
||||
let client_registration_start_result =
|
||||
ClientRegistration::<Ristretto255Sha512NoSlowHash>::start(&mut rng, ¶meters.password)?;
|
||||
|
||||
let sk_u_and_nonce: Vec<u8> = [parameters.client_s_sk, parameters.envelope_nonce].concat();
|
||||
let mut finish_registration_rng = CycleRng::new(sk_u_and_nonce);
|
||||
let result = client_registration_start_result.state.finish(
|
||||
&mut finish_registration_rng,
|
||||
RegistrationResponse::deserialize(¶meters.registration_response[..]).unwrap(),
|
||||
ClientRegistrationFinishParameters::default(),
|
||||
)?;
|
||||
|
||||
assert_eq!(
|
||||
hex::encode(parameters.registration_upload),
|
||||
hex::encode(result.message.serialize())
|
||||
);
|
||||
assert_eq!(
|
||||
hex::encode(parameters.export_key),
|
||||
hex::encode(result.export_key.to_vec())
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_password_file() -> Result<(), ProtocolError> {
|
||||
let parameters = populate_test_vectors(&serde_json::from_str(TEST_VECTOR).unwrap());
|
||||
|
||||
let mut oprf_key_rng = CycleRng::new(parameters.oprf_key);
|
||||
let server_registration_start_result =
|
||||
ServerRegistration::<Ristretto255Sha512NoSlowHash>::start(
|
||||
&mut oprf_key_rng,
|
||||
RegistrationRequest::deserialize(¶meters.registration_request[..]).unwrap(),
|
||||
&Key::try_from(¶meters.server_s_pk[..]).unwrap(),
|
||||
)?;
|
||||
|
||||
let password_file = server_registration_start_result
|
||||
.state
|
||||
.finish(RegistrationUpload::deserialize(¶meters.registration_upload[..]).unwrap())?;
|
||||
assert_eq!(
|
||||
hex::encode(parameters.password_file),
|
||||
hex::encode(password_file.to_bytes())
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_credential_request() -> Result<(), ProtocolError> {
|
||||
let parameters = populate_test_vectors(&serde_json::from_str(TEST_VECTOR).unwrap());
|
||||
|
||||
let client_login_start = [
|
||||
parameters.blinding_factor_login,
|
||||
parameters.client_e_sk,
|
||||
parameters.client_nonce,
|
||||
]
|
||||
.concat();
|
||||
let mut client_login_start_rng = CycleRng::new(client_login_start);
|
||||
let client_login_start_result = ClientLogin::<Ristretto255Sha512NoSlowHash>::start(
|
||||
&mut client_login_start_rng,
|
||||
¶meters.password,
|
||||
ClientLoginStartParameters::WithInfo(parameters.info1),
|
||||
)?;
|
||||
assert_eq!(
|
||||
hex::encode(¶meters.credential_request),
|
||||
hex::encode(client_login_start_result.message.serialize())
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_credential_response() -> Result<(), ProtocolError> {
|
||||
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());
|
||||
let server_login_start_result = ServerLogin::<Ristretto255Sha512NoSlowHash>::start(
|
||||
&mut server_e_sk_and_nonce_rng,
|
||||
ServerRegistration::try_from(¶meters.password_file[..]).unwrap(),
|
||||
&Key::try_from(¶meters.server_s_sk[..]).unwrap(),
|
||||
CredentialRequest::<Ristretto255Sha512NoSlowHash>::deserialize(
|
||||
¶meters.credential_request[..],
|
||||
)
|
||||
.unwrap(),
|
||||
ServerLoginStartParameters::WithInfo(parameters.info2.to_vec()),
|
||||
)?;
|
||||
assert_eq!(
|
||||
hex::encode(¶meters.info1),
|
||||
hex::encode(server_login_start_result.plain_info),
|
||||
);
|
||||
assert_eq!(
|
||||
hex::encode(¶meters.credential_response),
|
||||
hex::encode(server_login_start_result.message.serialize())
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_credential_finalization() -> Result<(), ProtocolError> {
|
||||
let parameters = populate_test_vectors(&serde_json::from_str(TEST_VECTOR).unwrap());
|
||||
|
||||
let client_login_start = [
|
||||
parameters.blinding_factor_login,
|
||||
parameters.client_e_sk,
|
||||
parameters.client_nonce,
|
||||
]
|
||||
.concat();
|
||||
let mut client_login_start_rng = CycleRng::new(client_login_start);
|
||||
let client_login_start_result = ClientLogin::<Ristretto255Sha512NoSlowHash>::start(
|
||||
&mut client_login_start_rng,
|
||||
¶meters.password,
|
||||
ClientLoginStartParameters::WithInfo(parameters.info1),
|
||||
)?;
|
||||
|
||||
let client_login_finish_result = client_login_start_result.state.finish(
|
||||
CredentialResponse::<Ristretto255Sha512NoSlowHash>::deserialize(
|
||||
¶meters.credential_response[..],
|
||||
)?,
|
||||
ClientLoginFinishParameters::default(),
|
||||
)?;
|
||||
|
||||
assert_eq!(
|
||||
hex::encode(¶meters.info2),
|
||||
hex::encode(&client_login_finish_result.confidential_info)
|
||||
);
|
||||
assert_eq!(
|
||||
hex::encode(¶meters.shared_secret),
|
||||
hex::encode(&client_login_finish_result.shared_secret)
|
||||
);
|
||||
assert_eq!(
|
||||
hex::encode(¶meters.credential_finalization),
|
||||
hex::encode(client_login_finish_result.message.to_bytes())
|
||||
);
|
||||
assert_eq!(
|
||||
hex::encode(¶meters.export_key),
|
||||
hex::encode(client_login_finish_result.export_key)
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_server_login_finish() -> Result<(), ProtocolError> {
|
||||
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());
|
||||
let server_login_start_result = ServerLogin::<Ristretto255Sha512NoSlowHash>::start(
|
||||
&mut server_e_sk_and_nonce_rng,
|
||||
ServerRegistration::try_from(¶meters.password_file[..]).unwrap(),
|
||||
&Key::try_from(¶meters.server_s_sk[..]).unwrap(),
|
||||
CredentialRequest::<Ristretto255Sha512NoSlowHash>::deserialize(
|
||||
¶meters.credential_request[..],
|
||||
)
|
||||
.unwrap(),
|
||||
ServerLoginStartParameters::WithInfo(parameters.info2.to_vec()),
|
||||
)?;
|
||||
|
||||
let server_login_result =
|
||||
server_login_start_result
|
||||
.state
|
||||
.finish(CredentialFinalization::try_from(
|
||||
¶meters.credential_finalization[..],
|
||||
)?)?;
|
||||
|
||||
assert_eq!(
|
||||
hex::encode(parameters.shared_secret),
|
||||
hex::encode(server_login_result.shared_secret)
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn test_complete_flow(
|
||||
registration_password: &[u8],
|
||||
login_password: &[u8],
|
||||
) -> Result<(), ProtocolError> {
|
||||
let mut client_rng = OsRng;
|
||||
let mut server_rng = OsRng;
|
||||
let server_kp = Ristretto255Sha512NoSlowHash::generate_random_keypair(&mut server_rng);
|
||||
let client_registration_start_result =
|
||||
ClientRegistration::<Ristretto255Sha512NoSlowHash>::start(
|
||||
&mut client_rng,
|
||||
registration_password,
|
||||
)?;
|
||||
let server_registration_start_result =
|
||||
ServerRegistration::<Ristretto255Sha512NoSlowHash>::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(),
|
||||
)?;
|
||||
let p_file = server_registration_start_result
|
||||
.state
|
||||
.finish(client_registration_finish_result.message)?;
|
||||
let client_login_start_result = ClientLogin::<Ristretto255Sha512NoSlowHash>::start(
|
||||
&mut client_rng,
|
||||
login_password,
|
||||
ClientLoginStartParameters::default(),
|
||||
)?;
|
||||
let server_login_start_result = ServerLogin::<Ristretto255Sha512NoSlowHash>::start(
|
||||
&mut server_rng,
|
||||
p_file,
|
||||
&server_kp.private(),
|
||||
client_login_start_result.message,
|
||||
ServerLoginStartParameters::default(),
|
||||
)?;
|
||||
|
||||
let client_login_result = client_login_start_result.state.finish(
|
||||
server_login_start_result.message,
|
||||
ClientLoginFinishParameters::default(),
|
||||
);
|
||||
|
||||
if hex::encode(registration_password) == hex::encode(login_password) {
|
||||
let client_login_finish_result = client_login_result?;
|
||||
let server_login_finish_result = server_login_start_result
|
||||
.state
|
||||
.finish(client_login_finish_result.message)?;
|
||||
|
||||
assert_eq!(
|
||||
hex::encode(server_login_finish_result.shared_secret),
|
||||
hex::encode(client_login_finish_result.shared_secret)
|
||||
);
|
||||
assert_eq!(
|
||||
hex::encode(client_registration_finish_result.export_key),
|
||||
hex::encode(client_login_finish_result.export_key)
|
||||
);
|
||||
} else {
|
||||
let res = matches!(
|
||||
client_login_result,
|
||||
Err(ProtocolError::VerificationError(
|
||||
PakeError::InvalidLoginError
|
||||
))
|
||||
);
|
||||
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")
|
||||
}
|
||||
Reference in New Issue
Block a user