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

2584 lines
140 KiB
Rust

// Copyright (c) Facebook, Inc. and its affiliates.
//
// 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.
#![allow(unsafe_code)]
use core::ops::Add;
use std::string::String;
use std::vec::Vec;
use std::{format, println, ptr, vec};
use digest::core_api::{BlockSizeUser, CoreProxy};
use digest::{Output, OutputSizeUser};
use generic_array::typenum::{IsLess, IsLessOrEqual, Le, NonZero, Sum, Unsigned, U256};
use generic_array::ArrayLength;
use rand::rngs::OsRng;
use serde_json::Value;
use subtle::ConstantTimeEq;
use voprf::Group;
use crate::ciphersuite::{CipherSuite, OprfGroup, OprfHash};
use crate::envelope::EnvelopeLen;
use crate::errors::*;
use crate::hash::{Hash, OutputSize, ProxyHash};
use crate::key_exchange::group::KeGroup;
use crate::key_exchange::traits::{Ke1MessageLen, Ke1StateLen, Ke2MessageLen};
use crate::key_exchange::tripledh::{NonceLen, TripleDh};
use crate::keypair::SecretKey;
use crate::ksf::Identity;
use crate::messages::{
CredentialRequestLen, CredentialResponseLen, CredentialResponseWithoutKeLen,
RegistrationResponseLen, RegistrationUploadLen,
};
use crate::opaque::*;
use crate::tests::mock_rng::CycleRng;
use crate::*;
// Tests
// =====
#[cfg(feature = "ristretto255")]
struct Ristretto255;
#[cfg(feature = "ristretto255")]
impl CipherSuite for Ristretto255 {
type OprfCs = crate::Ristretto255;
type KeGroup = crate::Ristretto255;
type KeyExchange = TripleDh;
type Ksf = Identity;
}
#[cfg(feature = "ristretto255")]
struct Ristretto255P256;
#[cfg(feature = "ristretto255")]
impl CipherSuite for Ristretto255P256 {
type OprfCs = p256::NistP256;
type KeGroup = crate::Ristretto255;
type KeyExchange = TripleDh;
type Ksf = Identity;
}
#[cfg(feature = "ristretto255")]
struct Ristretto255P384;
#[cfg(feature = "ristretto255")]
impl CipherSuite for Ristretto255P384 {
type OprfCs = p384::NistP384;
type KeGroup = crate::Ristretto255;
type KeyExchange = TripleDh;
type Ksf = Identity;
}
struct P256;
impl CipherSuite for P256 {
type OprfCs = p256::NistP256;
type KeGroup = p256::NistP256;
type KeyExchange = TripleDh;
type Ksf = Identity;
}
struct P256P384;
impl CipherSuite for P256P384 {
type OprfCs = p384::NistP384;
type KeGroup = p256::NistP256;
type KeyExchange = TripleDh;
type Ksf = Identity;
}
#[cfg(feature = "ristretto255")]
struct P256Ristretto255;
#[cfg(feature = "ristretto255")]
impl CipherSuite for P256Ristretto255 {
type OprfCs = crate::Ristretto255;
type KeGroup = p256::NistP256;
type KeyExchange = TripleDh;
type Ksf = Identity;
}
struct P384;
impl CipherSuite for P384 {
type OprfCs = p384::NistP384;
type KeGroup = p384::NistP384;
type KeyExchange = TripleDh;
type Ksf = Identity;
}
struct P384P256;
impl CipherSuite for P384P256 {
type OprfCs = p256::NistP256;
type KeGroup = p384::NistP384;
type KeyExchange = TripleDh;
type Ksf = Identity;
}
#[cfg(feature = "ristretto255")]
struct P384Ristretto255;
#[cfg(feature = "ristretto255")]
impl CipherSuite for P384Ristretto255 {
type OprfCs = crate::Ristretto255;
type KeGroup = p384::NistP384;
type KeyExchange = TripleDh;
type Ksf = Identity;
}
#[cfg(all(feature = "curve25519", feature = "ristretto255"))]
struct Curve25519Ristretto255;
#[cfg(all(feature = "curve25519", feature = "ristretto255"))]
impl CipherSuite for Curve25519Ristretto255 {
type OprfCs = crate::Ristretto255;
type KeGroup = crate::Curve25519;
type KeyExchange = TripleDh;
type Ksf = Identity;
}
#[cfg(feature = "curve25519")]
struct Curve25519P256;
#[cfg(feature = "curve25519")]
impl CipherSuite for Curve25519P256 {
type OprfCs = p256::NistP256;
type KeGroup = crate::Curve25519;
type KeyExchange = TripleDh;
type Ksf = Identity;
}
#[cfg(feature = "curve25519")]
struct Curve25519P384;
#[cfg(feature = "curve25519")]
impl CipherSuite for Curve25519P384 {
type OprfCs = p384::NistP384;
type KeGroup = crate::Curve25519;
type KeyExchange = TripleDh;
type Ksf = Identity;
}
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 fake_sk: Vec<u8>,
pub credential_identifier: Vec<u8>,
pub id_u: Vec<u8>,
pub id_s: Vec<u8>,
pub password: Vec<u8>,
pub blinding_factor: Vec<u8>,
pub oprf_seed: Vec<u8>,
pub masking_nonce: Vec<u8>,
pub envelope_nonce: Vec<u8>,
pub client_nonce: Vec<u8>,
pub server_nonce: Vec<u8>,
pub context: Vec<u8>,
pub registration_request: Vec<u8>,
pub registration_response: Vec<u8>,
pub registration_upload: Vec<u8>,
pub credential_request: Vec<u8>,
pub credential_response: Vec<u8>,
pub credential_finalization: Vec<u8>,
client_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>,
}
static STR_PASSWORD: &str = "password";
static STR_CREDENTIAL_IDENTIFIER: &str = "credential_identifier";
// To regenerate these test vectors, run:
// cargo test --features curve25519 -- --nocapture generate_test_vectors
#[cfg(feature = "ristretto255")]
static TEST_VECTOR_RISTRETTO255: &str = r#"
{
"client_s_pk": "58f84ab1de6d6baed997b8622a7340470a2e321778cf15a6a349f57143181b6d",
"client_s_sk": "ca1860c537f99dce6da9d0bf674f7c5c483c7e12c07487821d0fc60b78702a03",
"client_e_pk": "5898671746f581bbaa9019ea3e5dc5809612960e38f3fd3569237e8d0cf14a23",
"client_e_sk": "bd61a18173fe09b88529b4c04424637ce066fabc0f077985713ae12457d7b601",
"server_s_pk": "32033f92bfd82242f7dc9b2574f6916a53aa4ef83ecab4f4d912aad9957d8027",
"server_s_sk": "ab8f8598cb4166fb5ee1d437b6f5b563b59e4b699ded8e176c25ee77358bac01",
"server_e_pk": "f4ac5c4ef8dfae76705ddc1dd6c64b916680f69975cad5733ba7a4570bdd5629",
"server_e_sk": "7bf9ca648ab766269eeed497f640264cc248caaf94498b3aba2324395d061308",
"fake_sk": "23c51f2bd15324bbc088313184ff2daf81454c24002887b8abd8dc1d78f35000",
"credential_identifier": "637265644964656e746966696572",
"id_u": "696455",
"id_s": "696453",
"password": "70617373776f7264",
"blinding_factor": "16d9379d74dd857d97ed7470bc022290f0aed9d14c8de873c03139360d7c2203",
"oprf_seed": "089519f6ab43cb90f6c37abe2f4d6ef7928106fd5920c9856d717c6db229d6887b98ea296e8c48f962065e8c224ee1d687b5e9ea9be5c9fd66a1d5edf4326aa3",
"masking_nonce": "ff24215c44990ee27982e667ed57e1fefe21a38ecae3cf8dad951237ba6166cfef780945009e3cfc031f59552a8d7b84571c7c13722d88a52f2b7d279e27ff84",
"envelope_nonce": "add2e39416fb5917d1328dd9987b9e8e2ee30c04eb4f4a8ae5c52e63b719846a",
"client_nonce": "db1f9c4b2e3f4f307d35490a2d9ace7ccd2e124c5a08655bfb97597f24d5da55",
"server_nonce": "00285d1b30f04f84f020dc60d702581cf36fc8f683b75b1efd21e01056a1a102",
"context": "636f6e74657874",
"registration_request": "3025151fce8a32a8961aaf77031402a3d0cf70370052b22b6131c78de82e8366",
"registration_response": "1a566c5cb551027e996788ad999b14ecd8bc0f230348aef90674e733d946cd6332033f92bfd82242f7dc9b2574f6916a53aa4ef83ecab4f4d912aad9957d8027",
"registration_upload": "90c46263e6709e038ffd12d5e97eca652800edc492b942a798951da8af74ef289e8fe0c9fef7a8f785445c82f6185f1e8682ae907197ce97ae0521c0f5ce4f636781ad5b5c3f9df7c4af0dfdd0f77ce98846d019cf4189b8f0a793cd59e2b42aca1860c537f99dce6da9d0bf674f7c5c483c7e12c07487821d0fc60b78702a039923ef46ae4f5b0240484250d690a6b1533bc8d5cd89e5b5bb78ebe4cb40d4439275e924b80683c6b8833cb503059bd3bcb083aa72bf70d1d2cb4e6d40cd61d7",
"credential_request": "3025151fce8a32a8961aaf77031402a3d0cf70370052b22b6131c78de82e8366db1f9c4b2e3f4f307d35490a2d9ace7ccd2e124c5a08655bfb97597f24d5da555898671746f581bbaa9019ea3e5dc5809612960e38f3fd3569237e8d0cf14a23",
"credential_response": "1a566c5cb551027e996788ad999b14ecd8bc0f230348aef90674e733d946cd63ff24215c44990ee27982e667ed57e1fefe21a38ecae3cf8dad951237ba6166cfd7635651e5f867c08c02e7564b86a03d1b1b198dec5b9b54f998d3bfba0f4fe956d3e795c672c275ac2fb0a5ce38920bc17f532348243f79db5aaf34db507ce41096d9a326ee453f02ab1d1c9b738507fbe87197b13c65720e4f16737f9da173613b90bd5b2ee6812c0462299a7c3b179e439e88af08abf607796e4e9d23e17f7bf9ca648ab766269eeed497f640264cc248caaf94498b3aba2324395d061308a0c9863142b43845b16e9bf9e1d236038a0cf8a470a7291c60e8579dae1e2128d7919f28f7a4ff9fdd915f00b42007aa1de6f9a0bded2cbbf297e923bcef57f42fb06bcfca035fbc66cf74300c54daec3738dbaca2ba470bb81330efab584256",
"credential_finalization": "6a3f177d73886db031e081e116a1eb7c13ef763a60a0ae8b7477f4fcf6c7d22618651402f3ab7bd501f42442a010a185253c87bb051cca80686b54ceb5c410d3",
"client_registration_state": "16d9379d74dd857d97ed7470bc022290f0aed9d14c8de873c03139360d7c22033025151fce8a32a8961aaf77031402a3d0cf70370052b22b6131c78de82e8366",
"client_login_state": "16d9379d74dd857d97ed7470bc022290f0aed9d14c8de873c03139360d7c22033025151fce8a32a8961aaf77031402a3d0cf70370052b22b6131c78de82e8366db1f9c4b2e3f4f307d35490a2d9ace7ccd2e124c5a08655bfb97597f24d5da555898671746f581bbaa9019ea3e5dc5809612960e38f3fd3569237e8d0cf14a23bd61a18173fe09b88529b4c04424637ce066fabc0f077985713ae12457d7b601db1f9c4b2e3f4f307d35490a2d9ace7ccd2e124c5a08655bfb97597f24d5da55",
"server_login_state": "01410c086ece65443dcbca42c6703d08bae0d293f4b9b78449df626f7f8b04d8cada3f693670e74683f4ec6f9df9d1773fa4212a6ddc52343874bcfb0a87dd82cd25afdbb29dd431c859b337de3123e325d9aa9c99e9a59fd98858c6835e8c34d0945a251261f456ffa67399c8745e478c7377a3774930a49f0b7c351ed654e38d62e93a5ec5cd0305521bcce9695b3ce23b4713a699bd9e1e102049652bc407fc6579cf4c7f8e5e3dcfaadb73a36c49bc2084b82246c01c630dde63a5bbfb40",
"password_file": "90c46263e6709e038ffd12d5e97eca652800edc492b942a798951da8af74ef289e8fe0c9fef7a8f785445c82f6185f1e8682ae907197ce97ae0521c0f5ce4f636781ad5b5c3f9df7c4af0dfdd0f77ce98846d019cf4189b8f0a793cd59e2b42aca1860c537f99dce6da9d0bf674f7c5c483c7e12c07487821d0fc60b78702a039923ef46ae4f5b0240484250d690a6b1533bc8d5cd89e5b5bb78ebe4cb40d4439275e924b80683c6b8833cb503059bd3bcb083aa72bf70d1d2cb4e6d40cd61d7",
"export_key": "55833fcf856af07df1ec4d98a2180ca90227edddf53bca6787cb86f40337290491dec6dbc95efd56e15e7f2bb9bea2c2e683b956b1f85b2f9abce2a87cf61e4b",
"session_key": "8d62e93a5ec5cd0305521bcce9695b3ce23b4713a699bd9e1e102049652bc407fc6579cf4c7f8e5e3dcfaadb73a36c49bc2084b82246c01c630dde63a5bbfb40"
}
"#;
#[cfg(feature = "ristretto255")]
static TEST_VECTOR_RISTRETTO255_P256: &str = r#"
{
"client_s_pk": "f88bd648ec3275a06d2f64f7f2e35f9b79cef7d6ead6ba05945b700658643e2f",
"client_s_sk": "04e1b7f9448b6913ff7de5e0b4ccc2f6e88eb6ef80963c75f89db0f634cb000b",
"client_e_pk": "907bd6c4d780c85415ce1b9e8cff2a6c10bec716d6eab80cf3f9646469033a3c",
"client_e_sk": "8c0e7d7310db05a12a418c0616c8969855008946702d7d0e2b0b1f10dd24c402",
"server_s_pk": "681525049da7bedd96b863b95f13859b616aa9729b752676dde32513acfb7611",
"server_s_sk": "30aa1bf8df6bf6ed30e7c9579e3bda2804dad268ea2d3bc793173a35e895ad00",
"server_e_pk": "68732765fd7a76511f7c2a50bf7df6efe54efa15b0bfce2ba162ee922c4e0452",
"server_e_sk": "4961b6b17fef0eb216c13c97e5a2c28db78feddbbbdcfe9eaea937c6fb625d05",
"fake_sk": "d3fd635217181a826cb07eaad0d6c722e73731a3c719f26322ccef9d2130990d",
"credential_identifier": "637265644964656e746966696572",
"id_u": "696455",
"id_s": "696453",
"password": "70617373776f7264",
"blinding_factor": "ce2a220c656632c5bb630351bf2bc9258631acd226c5ecb1686aa82ea5baf308",
"oprf_seed": "3d108c5667216961a69098fc9a94294cd8761aa4af76c51ea35df3a06f2139f6",
"masking_nonce": "ef9aebb14f7f965ac8fcba0418a83340646747cb00d056b57f7ba2671945728ce3648bf46c6d2b21890ad09c25142e57360cea1300ed7d74dc0580e61fa5b5e7",
"envelope_nonce": "23abd8c07fec3913673426fd49f4d2832c29855b5846fea5ffa6d91ede58f6ac",
"client_nonce": "dff3b604d150842e692aa20fd0621ba8718581fd6fa4a3409108bba35d5f7bdc",
"server_nonce": "e3d70b5657db6fa047f106843a746091c602d2c2e8280d9ac8994cf39bf93d30",
"context": "636f6e74657874",
"registration_request": "03ae0926f45e0b5efab9e15e6acddd7dd4bdbf15b1accccbae1927d5450532229a",
"registration_response": "03f2a9e0737a10e41a5501f853d2401a89a7c8c626926e6899205357a7d971c238681525049da7bedd96b863b95f13859b616aa9729b752676dde32513acfb7611",
"registration_upload": "7e7ea08bc8cceb5d89b7ceb8e91deadb721a2ad684272510e85570acb9563451ad667e253cfd587092cfc3a788aec8b0cf3e248d84cc7ff98e7d5488736deb3704e1b7f9448b6913ff7de5e0b4ccc2f6e88eb6ef80963c75f89db0f634cb000bfc47ba0ccf49efab4a706d72cf038a01c6f32fa4fa10a30c6ce94df37a86504f",
"credential_request": "03ae0926f45e0b5efab9e15e6acddd7dd4bdbf15b1accccbae1927d5450532229adff3b604d150842e692aa20fd0621ba8718581fd6fa4a3409108bba35d5f7bdc907bd6c4d780c85415ce1b9e8cff2a6c10bec716d6eab80cf3f9646469033a3c",
"credential_response": "03f2a9e0737a10e41a5501f853d2401a89a7c8c626926e6899205357a7d971c238ef9aebb14f7f965ac8fcba0418a83340646747cb00d056b57f7ba2671945728cb166cbc26eadb074abec8888288bb157ba6e995e4983277dde3a8b164e78efcf261a0a2ae4dcbb379a1e651b128bf356108a2be9e10f5e0d95f5e51c748b890b96e6304f8380ee71f623e3bfde447ee58bb60e40281e44f8496e5a799c24506f4961b6b17fef0eb216c13c97e5a2c28db78feddbbbdcfe9eaea937c6fb625d05c0b7b235a518f55c3026b2bc375841f35c3b2e1fc381c3963b721a97d34d887ea4dfb155d59da8ad912aac17df06e6a21b118cac0cfd15903f0c20658fa717b4",
"credential_finalization": "10653ec75b594a7401ffcde895d463002c3eac839f0343ac779fa9210e4782dc",
"client_registration_state": "ce2a220c656632c5bb630351bf2bc9258631acd226c5ecb1686aa82ea5baf30803ae0926f45e0b5efab9e15e6acddd7dd4bdbf15b1accccbae1927d5450532229a",
"client_login_state": "ce2a220c656632c5bb630351bf2bc9258631acd226c5ecb1686aa82ea5baf30803ae0926f45e0b5efab9e15e6acddd7dd4bdbf15b1accccbae1927d5450532229adff3b604d150842e692aa20fd0621ba8718581fd6fa4a3409108bba35d5f7bdc907bd6c4d780c85415ce1b9e8cff2a6c10bec716d6eab80cf3f9646469033a3c8c0e7d7310db05a12a418c0616c8969855008946702d7d0e2b0b1f10dd24c402dff3b604d150842e692aa20fd0621ba8718581fd6fa4a3409108bba35d5f7bdc",
"server_login_state": "2b6792d84ae19d64f39ae233b54ce79ab8793f9648c24f4bd22df7b4f9e4e6e77fe5ead3ce6faf1d05cbc64518cfe259cfe522b381eadc79019c0c81f613233d91910ea0c4c286eeec89dd2ceec93478f936454f4f41206c75407862150cdf3a",
"password_file": "7e7ea08bc8cceb5d89b7ceb8e91deadb721a2ad684272510e85570acb9563451ad667e253cfd587092cfc3a788aec8b0cf3e248d84cc7ff98e7d5488736deb3704e1b7f9448b6913ff7de5e0b4ccc2f6e88eb6ef80963c75f89db0f634cb000bfc47ba0ccf49efab4a706d72cf038a01c6f32fa4fa10a30c6ce94df37a86504f",
"export_key": "b776d68ad88a7534f571625727ce09a13ff203b9c26e16da9aaa1b7698cd1645",
"session_key": "91910ea0c4c286eeec89dd2ceec93478f936454f4f41206c75407862150cdf3a"
}
"#;
#[cfg(feature = "ristretto255")]
static TEST_VECTOR_RISTRETTO255_P384: &str = r#"
{
"client_s_pk": "86a1adb5a45e87b1cb92f082a5bf5890e9e21e2d78d4773ab7f0d021664b7b69",
"client_s_sk": "950ac3b5fcca8fbcc740e24a9f0a0703bf06c1e345459cb662bed0ae91f10904",
"client_e_pk": "d697f15ff9e34fd51a2a8980995503d17bd11cbb0407d51502138f384f908112",
"client_e_sk": "c320ee0eb5eef9e6e00872cef1196e362d20712ae9da185e7466397324a72907",
"server_s_pk": "d0433b254df7a9952f281f10b86d9c4cc14faef3a3c67943a01b208782da620e",
"server_s_sk": "94985ed3d85392c7957c53b9f24ab138acbdbba80357c79eeccea19602434b0d",
"server_e_pk": "00ea32a0e605deb301bc73b4df661100d7de331c6e4548b9e5dbf02872fe7529",
"server_e_sk": "e4d2a0ea0adf9edb4a8d7e0d236ea9022bdcae7d7c24665928c7c9e765ffe700",
"fake_sk": "26e8e0bf9739b54dafab24a3454cceef1b3c61b0b6e521dc5cba404722517101",
"credential_identifier": "637265644964656e746966696572",
"id_u": "696455",
"id_s": "696453",
"password": "70617373776f7264",
"blinding_factor": "454092e5dcb20854d987421466835f4a270bcaffeae8e094a0cd1c4f636946b90bb5d8d0cc2bddfcde1bc97042021043",
"oprf_seed": "e4d402280ebe5718f2b2887ef5595a6b2020f6fb983b5f117ab7db986e2fdca9675b4bc94ff4db6cd249810ff08bb760",
"masking_nonce": "ed6dd7938ad35abd1088e892d55706ea3394d88351e18b6574b7b2931210e5b6320a60040a96d8a68f8ca197dc77c9072964e0a267eb4d51bf6327d40ec3091f",
"envelope_nonce": "866f1e43f59ab3076f7ffa80e3d180d74dfe472a4399378477927ac88e99483c",
"client_nonce": "c4eb516c8f385cabe449e30bd55975cb8c73b8cd4121e392202c95dc1ca58ff6",
"server_nonce": "7eba5738ead262ae3288e908cc31126d8755b79471e34a0fed7bda22abdf830b",
"context": "636f6e74657874",
"registration_request": "031032c75bd6d20572956af17c27c8a628f493993903e8a2dbd4db1b069f2dacbf05767428f0e4c58150af7d6577c42cc1",
"registration_response": "024fbffd6d812d62d98009ac0277c0740e3245e98bf3c62a8dda34152b350b8a74f34fb5677b848b45e982d663ee7ae522d0433b254df7a9952f281f10b86d9c4cc14faef3a3c67943a01b208782da620e",
"registration_upload": "82961e5ba6f42e3dede98b0eb333668f768df6e28335896e1d1c764d45b26101937f31c8f82cda4be30080d8edeefdce8d43a11a8dc089111f48d173d9a057fa35dc0dfe0a59457a6bfec84298d5e4d8950ac3b5fcca8fbcc740e24a9f0a0703bf06c1e345459cb662bed0ae91f1090468008a29cf8f061e01bdc0940a04bee4a49391c2eb3a10552254f3904e2b374a2018fd6153e948d7bb74e47de4b3765e",
"credential_request": "031032c75bd6d20572956af17c27c8a628f493993903e8a2dbd4db1b069f2dacbf05767428f0e4c58150af7d6577c42cc1c4eb516c8f385cabe449e30bd55975cb8c73b8cd4121e392202c95dc1ca58ff6d697f15ff9e34fd51a2a8980995503d17bd11cbb0407d51502138f384f908112",
"credential_response": "024fbffd6d812d62d98009ac0277c0740e3245e98bf3c62a8dda34152b350b8a74f34fb5677b848b45e982d663ee7ae522ed6dd7938ad35abd1088e892d55706ea3394d88351e18b6574b7b2931210e5b631a1b6b837aa901a6016382e5174dc0afe05c4c382066c68a4712a9472382b22e0f41eec742cfb4fb44606388b40c4460b87996048768e54f2d130cabead02de5e564ca78adb2f72c45c966cf8feadeecbbefbdab76b21474a1513c098a61e2fb00c6b3e23b248d9d95740d44b81e54ae4d2a0ea0adf9edb4a8d7e0d236ea9022bdcae7d7c24665928c7c9e765ffe700bac9e8a7cec2359871b91d1f87d975888ff28262c2520d729a48f27e6c8f722b7b778392ded7de3648a63e312aaca0dfdac3177583b016d64ee3735f983e2b1dbe622fa1f92d9a38fe55550948416592",
"credential_finalization": "17a0cf86d1021759062b89f802a798b5d2492f7373462e1b75d6197a21d599e1f16b0fafad97ba72b0ad69683e69a145",
"client_registration_state": "454092e5dcb20854d987421466835f4a270bcaffeae8e094a0cd1c4f636946b90bb5d8d0cc2bddfcde1bc97042021043031032c75bd6d20572956af17c27c8a628f493993903e8a2dbd4db1b069f2dacbf05767428f0e4c58150af7d6577c42cc1",
"client_login_state": "454092e5dcb20854d987421466835f4a270bcaffeae8e094a0cd1c4f636946b90bb5d8d0cc2bddfcde1bc97042021043031032c75bd6d20572956af17c27c8a628f493993903e8a2dbd4db1b069f2dacbf05767428f0e4c58150af7d6577c42cc1c4eb516c8f385cabe449e30bd55975cb8c73b8cd4121e392202c95dc1ca58ff6d697f15ff9e34fd51a2a8980995503d17bd11cbb0407d51502138f384f908112c320ee0eb5eef9e6e00872cef1196e362d20712ae9da185e7466397324a72907c4eb516c8f385cabe449e30bd55975cb8c73b8cd4121e392202c95dc1ca58ff6",
"server_login_state": "1ac407a2442a2b126afd56a7790d790c1dcbd16b3d9d89963267f26c798a0266d896e8c1daa912d5933be902cfa301e42f1fe785b8429087cc492f9e8731139628530254e4524a0df9a6840748dc8bd12b65bf3141f09a696b55760bd4f65fc3e952e42d4d61618bd93459e43b4ee699eba8d9d3ed3c0c31bd605b654e9fc289a87799c43267570e7644c16436463fd0",
"password_file": "82961e5ba6f42e3dede98b0eb333668f768df6e28335896e1d1c764d45b26101937f31c8f82cda4be30080d8edeefdce8d43a11a8dc089111f48d173d9a057fa35dc0dfe0a59457a6bfec84298d5e4d8950ac3b5fcca8fbcc740e24a9f0a0703bf06c1e345459cb662bed0ae91f1090468008a29cf8f061e01bdc0940a04bee4a49391c2eb3a10552254f3904e2b374a2018fd6153e948d7bb74e47de4b3765e",
"export_key": "6507d9329bb8fb8468d7fbf89781f02e3d56e887aa8cd0e56b622bb9b2cf78e079000936c0cbacdf3acbae65b929f143",
"session_key": "e952e42d4d61618bd93459e43b4ee699eba8d9d3ed3c0c31bd605b654e9fc289a87799c43267570e7644c16436463fd0"
}
"#;
static TEST_VECTOR_P256: &str = r#"
{
"client_s_pk": "032d82f5e7db19c5f87db1cb296d5f847315e98aa4ae2f14cb94fe9fefae5b23a1",
"client_s_sk": "4c2bd02fd037cfe6aa8aa243bbf0419c6f4196565470192554bdf3da966ae1d5",
"client_e_pk": "03b2ee310f831c43b6ecf8683ab3a0f903f4c54d42b5851652667d24a051805e54",
"client_e_sk": "11fd841fa4c27ed5849632ce256a242c526f1f828e170a68800fa4a7a9c93047",
"server_s_pk": "022cc9aadeaed45bdae85464af1512614edde6adf97c1407d6721e5cd1a985734a",
"server_s_sk": "e6334d73a9a34212886d4c4b7368df72f06a90b2887e5632f0eadad4cc8c9d3d",
"server_e_pk": "03ca02f4d31f1e66624dc21864e410876f2dc8fdcfff031090f170736d73060a10",
"server_e_sk": "6a6b22ac2bc7bd6401cc2e42f588a4550651cbd30d9529b69ebb88d7b073e6a2",
"fake_sk": "8362d70183ab78942b21ae3cba95f1edb5d314fb2f2afa49a452222a02f6dcc4",
"credential_identifier": "637265644964656e746966696572",
"id_u": "696455",
"id_s": "696453",
"password": "70617373776f7264",
"blinding_factor": "87700138241d25149a2ca6fd9a27e7f9d71a8e718fe1c411862a975cdb17a413",
"oprf_seed": "8b10b0445efce9c59e6e5a39f89961722fba14a809068620b9d77433bafb254e",
"masking_nonce": "52b2cf34ba108ffd2ef1e516585d845b90e34af198f379b6465744f5812274680c5dc1dca7e6a73a4dd48159cbd4b35913ff51bac2605a63563602e681aeb171",
"envelope_nonce": "f97a0c9a7de14b073531d24ba6d7893191a2724fffa6fe242099c17c6640e210",
"client_nonce": "4c5dbddfb063ecba7fd528c0caec52893ef206bf86362dafb27fe13d96e0b538",
"server_nonce": "fab1f9fa3f0356fc5d9b766ea3bdd53884ab38bac8371842d047a3b815c79428",
"context": "636f6e74657874",
"registration_request": "030e9bc97e025d9b5eacf7e76b16ada9a568401c509d2d1c507914c56d820be7ea",
"registration_response": "03dc5d4ba61011266879896966f26fde5e188a5d30df17deca56d5e227efbc8102022cc9aadeaed45bdae85464af1512614edde6adf97c1407d6721e5cd1a985734a",
"registration_upload": "035153b60a0f66ddf3d45d00c6bf6506a0898e6d438f1f73fbec916d538f6b43b042eaa5fe4bb07b55cce02bdc53225886bff138edf3a57a7f28d256d52b1755c84c2bd02fd037cfe6aa8aa243bbf0419c6f4196565470192554bdf3da966ae1d5489d88b7908412724d6c28f209a1c45ff7d509cbdb67b017c08802a4532e04d5",
"credential_request": "030e9bc97e025d9b5eacf7e76b16ada9a568401c509d2d1c507914c56d820be7ea4c5dbddfb063ecba7fd528c0caec52893ef206bf86362dafb27fe13d96e0b53803b2ee310f831c43b6ecf8683ab3a0f903f4c54d42b5851652667d24a051805e54",
"credential_response": "03dc5d4ba61011266879896966f26fde5e188a5d30df17deca56d5e227efbc810252b2cf34ba108ffd2ef1e516585d845b90e34af198f379b6465744f5812274682cc3c3b734abf18e0ee058a9983f91017022b220d76a7bea6a99e7a7ca8bce9dfe0d670272cdfe25136f9bf00b4607a79133c37f367da3e8b9ead9059f40a2bca60b7d99ba5a2557de3be49de1b62e5771a2855d1fbce37ffbf403ca5fa3a37c3b6a6b22ac2bc7bd6401cc2e42f588a4550651cbd30d9529b69ebb88d7b073e6a203e0f0020d7d9a024e799db237b7dedc4faa8a4a8ce17e93ff490ea66ebc654ba67c17359620d1e627a528c40c961d55d77de2882a9c510ea920974f1ddc97f3c5",
"credential_finalization": "a6836d9d17ed9a5e7c562002058f0a68e1c41925f7736e959965811b6e3e0783",
"client_registration_state": "87700138241d25149a2ca6fd9a27e7f9d71a8e718fe1c411862a975cdb17a413030e9bc97e025d9b5eacf7e76b16ada9a568401c509d2d1c507914c56d820be7ea",
"client_login_state": "87700138241d25149a2ca6fd9a27e7f9d71a8e718fe1c411862a975cdb17a413030e9bc97e025d9b5eacf7e76b16ada9a568401c509d2d1c507914c56d820be7ea4c5dbddfb063ecba7fd528c0caec52893ef206bf86362dafb27fe13d96e0b53803b2ee310f831c43b6ecf8683ab3a0f903f4c54d42b5851652667d24a051805e5411fd841fa4c27ed5849632ce256a242c526f1f828e170a68800fa4a7a9c930474c5dbddfb063ecba7fd528c0caec52893ef206bf86362dafb27fe13d96e0b538",
"server_login_state": "f7954aa457f509c7695b9e3313a7a445086cb7c0340f75249544d638fe2faba161395f0bfaeb1f56bfb8c93b56b5cb77e5e63c15d328e7e5bb4310e92cb2cdd867e4fa4ba1fdae0282a7b8dadb9bb30081ff2fd351c3ff24dac160d46e3192cb",
"password_file": "035153b60a0f66ddf3d45d00c6bf6506a0898e6d438f1f73fbec916d538f6b43b042eaa5fe4bb07b55cce02bdc53225886bff138edf3a57a7f28d256d52b1755c84c2bd02fd037cfe6aa8aa243bbf0419c6f4196565470192554bdf3da966ae1d5489d88b7908412724d6c28f209a1c45ff7d509cbdb67b017c08802a4532e04d5",
"export_key": "dfaad05e13c091a4cd11d9342bbf361111bfd7ae0b09866175a6c76403afef15",
"session_key": "67e4fa4ba1fdae0282a7b8dadb9bb30081ff2fd351c3ff24dac160d46e3192cb"
}
"#;
static TEST_VECTOR_P256_P384: &str = r#"
{
"client_s_pk": "02ffaa7a9ad8d8fbdf51462333be3baf795e927626afc30a825299b2738be56e64",
"client_s_sk": "867143397117121b3cf8bbbdbb577e7a3ec3de33a5d052e6ea5e736d8da5243a",
"client_e_pk": "02d71ac13b7c461a0aff3ffcf6fb43961f3cc78d159a88190e11814cf8c1c47e63",
"client_e_sk": "e48b752d3f498fbd8e605e95a076f342574b6d6717483fe11a8f8bb1f7f404a9",
"server_s_pk": "03b0c19cb4a9c38a4f8dfd3108d346153612258eda0a918a66898ead514a087484",
"server_s_sk": "799ec708dff22260a940b1daab1bf246f7dc0b3ef36edf5e325e4783ed580b15",
"server_e_pk": "0266a3ee38dd097628288b9f12ddcd8ba2d581dd3f390bc82c88019fb6da84b4ab",
"server_e_sk": "2d40040888e6eabc3ef1192abe45de7e72de591e88f9cb85624f6fe69a829abe",
"fake_sk": "1f63b1381351cdee56bb69a649210a0e401946033210a1d1abb310ee84b057be",
"credential_identifier": "637265644964656e746966696572",
"id_u": "696455",
"id_s": "696453",
"password": "70617373776f7264",
"blinding_factor": "898b728c633b5f335da29527ae279122049cc0a48adde3de699707f9008e58808383b39014554696359c1ff9198092cf",
"oprf_seed": "a681bb60cbc5f65264fbdd29b487fb7eff1bc1b1fad69ba6dad7d802714251fcadd91cbddb9d203be691c99be04dd3a9",
"masking_nonce": "596d13dbdaf0a67f38ab3560f1a8ad539f6879365d2499c35c61822ab457656b5d3102a21c019920324671b47f0c86e6d573179babcd8b87980804a0cec8655c",
"envelope_nonce": "027b3fe224cd45ea4a88125341fb12f903c36665fcfd9f86e20e91b094e935b3",
"client_nonce": "86c1a1f3bf1872e0f19ce42ca68f4e69c0c7fa2bcd0f9728af650b849f35995d",
"server_nonce": "f649bf73c6e0625c8c204a300b6da5f9efcd182634df70175e6cfeb74bbde7ed",
"context": "636f6e74657874",
"registration_request": "03b9f9c8b76887dd8c74246c02bf77a29af14cb5ba2b02e13992db2c8c87f48068c040a9898dca0d4122e42ccf65219522",
"registration_response": "038fe2c1e3b7d968e312b48077edd6545550fcabfdfa25b9420c78c8331dc413028fe973e15270b96673c101ce98c944c303b0c19cb4a9c38a4f8dfd3108d346153612258eda0a918a66898ead514a087484",
"registration_upload": "02e07f9bd7377e8275dd95713f4a8de1a13699f61359b69095cfcada7efbb1ab72b8ff9db6b14b4f8bcb1bf6978cf1b02ce7c75af8d63433d6a75caa620ad851cde67df132e8e71a92c2f6cc137c09ddfd867143397117121b3cf8bbbdbb577e7a3ec3de33a5d052e6ea5e736d8da5243a4f30fd6be311843b3b8309d41a0a11f5f1d42eadc5539959457a6eed12d4adfb599fe45a546effd7dca5dcac5b5ff498",
"credential_request": "03b9f9c8b76887dd8c74246c02bf77a29af14cb5ba2b02e13992db2c8c87f48068c040a9898dca0d4122e42ccf6521952286c1a1f3bf1872e0f19ce42ca68f4e69c0c7fa2bcd0f9728af650b849f35995d02d71ac13b7c461a0aff3ffcf6fb43961f3cc78d159a88190e11814cf8c1c47e63",
"credential_response": "038fe2c1e3b7d968e312b48077edd6545550fcabfdfa25b9420c78c8331dc413028fe973e15270b96673c101ce98c944c3596d13dbdaf0a67f38ab3560f1a8ad539f6879365d2499c35c61822ab457656b967df0a08fb74ca0bbbb915587e55808699b877c9d9f7370e0ba290f3d95e175d66fb98adf8f3aff5b9c06a5dd2a7b5d20a2a76a4f2dc6ef5a67113461a85a03174b585c78445c7a6b1438edd882f75cb56e380f4447e3d366430ca3f2ef372e439b5bb7ac2e1f9dc5b3487232e60a1ddf2d40040888e6eabc3ef1192abe45de7e72de591e88f9cb85624f6fe69a829abe033f366e71bf3f7573a431bac0b35aa60db23b40d2003af7d8eb5f55940b75af3e62ea7b191b1f5b9fae34bb92f0c10b06b95918e784f4afb06c846c254113bdfb3a5b5ca81890dc601dfdb80fabb3865d",
"credential_finalization": "188fe8130fab154ddf481a80349f50685d160e6e1db4d11acdff51e1b5d617032e8a62b39e43116f2ffc3651df61995b",
"client_registration_state": "898b728c633b5f335da29527ae279122049cc0a48adde3de699707f9008e58808383b39014554696359c1ff9198092cf03b9f9c8b76887dd8c74246c02bf77a29af14cb5ba2b02e13992db2c8c87f48068c040a9898dca0d4122e42ccf65219522",
"client_login_state": "898b728c633b5f335da29527ae279122049cc0a48adde3de699707f9008e58808383b39014554696359c1ff9198092cf03b9f9c8b76887dd8c74246c02bf77a29af14cb5ba2b02e13992db2c8c87f48068c040a9898dca0d4122e42ccf6521952286c1a1f3bf1872e0f19ce42ca68f4e69c0c7fa2bcd0f9728af650b849f35995d02d71ac13b7c461a0aff3ffcf6fb43961f3cc78d159a88190e11814cf8c1c47e63e48b752d3f498fbd8e605e95a076f342574b6d6717483fe11a8f8bb1f7f404a986c1a1f3bf1872e0f19ce42ca68f4e69c0c7fa2bcd0f9728af650b849f35995d",
"server_login_state": "6c196b4c6cd855c215852c5c11fd1590038eb9d7c69adc062777e3fed1464526d6a8aafd04e9a5845b32bc92bab852520200c994e54b7c3a8844c75c7952d1c0d2cf5232bd3fe6fa24d7b74e6373ccf66d48ead98331257efc320a16864908f4fce34bf2c26ec5f73072d3522d3b42306dfde8ce0b6827dff1202bd1ca11e767d758b4237c30e30d8878db1ebd4bb595",
"password_file": "02e07f9bd7377e8275dd95713f4a8de1a13699f61359b69095cfcada7efbb1ab72b8ff9db6b14b4f8bcb1bf6978cf1b02ce7c75af8d63433d6a75caa620ad851cde67df132e8e71a92c2f6cc137c09ddfd867143397117121b3cf8bbbdbb577e7a3ec3de33a5d052e6ea5e736d8da5243a4f30fd6be311843b3b8309d41a0a11f5f1d42eadc5539959457a6eed12d4adfb599fe45a546effd7dca5dcac5b5ff498",
"export_key": "431c7293c534c3a555c36ac8b665130066c667b26f86403b3b3e1f06c5e941447f52976265a234fcb0edf4bdef99aaff",
"session_key": "fce34bf2c26ec5f73072d3522d3b42306dfde8ce0b6827dff1202bd1ca11e767d758b4237c30e30d8878db1ebd4bb595"
}
"#;
#[cfg(feature = "ristretto255")]
static TEST_VECTOR_P256_RISTRETTO255: &str = r#"
{
"client_s_pk": "027e83df2e0b7380bb430352afc9326a63cd53d6bf6955b60114ae56a9ada8a005",
"client_s_sk": "125dee3f99fd11e6dfc10f3269010644abbe1676856c1fd28c3f1c11fb12e8a9",
"client_e_pk": "02e1a67fc34629e5d0bc6c7d2873673e873514114e15a72a27e71fde337351ab79",
"client_e_sk": "3ba3bfd9cf3b5970a7557260fbd9c1f5480ad2434f3ca788bf0e298e3adb1728",
"server_s_pk": "0363418a22f5e2d041a3cc49ac195bb72c484fe2422756874eea2502b1f37265f2",
"server_s_sk": "9ca7d0b89c84808c6a3a234383f2a400171d0362fd9cd66874a812b29309aea7",
"server_e_pk": "02d3da0962e20af7c63624aff08fcf98f622cdc75d1c475bdec059064cb176da41",
"server_e_sk": "7c7aea17291d0c297fc2685c2876b0b57a67b91dfa7d20edce1872341c86a74c",
"fake_sk": "2fb1ab3f8edf772701cc7c2a4773ac7441fc17157c00132d0bc4df63703953c3",
"credential_identifier": "637265644964656e746966696572",
"id_u": "696455",
"id_s": "696453",
"password": "70617373776f7264",
"blinding_factor": "5b4e8ccffa209c8df0ec71d0d1092de288ae05e472e71f9f95ff8d4b34a45a0f",
"oprf_seed": "a519f2078900c38d7764481978296720f9b02b472e5aa5e08a32ec1d72c23dc2e3fbd680d367668ce032f45c214aa4efe76b4722f487732aed6c4063a5ab067b",
"masking_nonce": "4e3843835669dac4e6875c1627391e2a5589d4f4a3cfb507f0956c16566feb62692db88b2fbaf002a729a31afecbc016e06b004b11c8f9f53d10430c51db1c9f",
"envelope_nonce": "d9d3327bd827540d1e5f267605c222cd154c5da6dadd43845d8498c58420fc06",
"client_nonce": "246142ff274fe7c3385f6268e7e9c0c1ae2804c664308cec59d2cd0e5af683a4",
"server_nonce": "4f9277be8c0deeccb8c67c5312332ea8fc268360c9a46603c2f5f06f94e45f37",
"context": "636f6e74657874",
"registration_request": "0ca151ef38b3b82f1b2166b6627671943ae8371b207dadfc4c4ccbc93db0fc51",
"registration_response": "ca2757e756faaed5e3956fff22ed9d7f5e7114856b11753b3f84f904831d8c290363418a22f5e2d041a3cc49ac195bb72c484fe2422756874eea2502b1f37265f2",
"registration_upload": "0273a4a83ef4a4c014623a59d3188370e4592b0c1d2d695dda98a07339a1536e77c5aab89c3434cfb25289d087d3f35680d82a3eaf34b539317a82a219652e2bc1b151f423e945eab65a598624a9328265f91a8e69f5975c7517905db6091894b2125dee3f99fd11e6dfc10f3269010644abbe1676856c1fd28c3f1c11fb12e8a90944628ebe4b83026cca4f2b719ab0e836c01f42bc854a2262f7f0cfcf83b026426371c91a3a3f6ebc47225e092b76fb54636aec37618815f2ba0f9da6290def",
"credential_request": "0ca151ef38b3b82f1b2166b6627671943ae8371b207dadfc4c4ccbc93db0fc51246142ff274fe7c3385f6268e7e9c0c1ae2804c664308cec59d2cd0e5af683a402e1a67fc34629e5d0bc6c7d2873673e873514114e15a72a27e71fde337351ab79",
"credential_response": "ca2757e756faaed5e3956fff22ed9d7f5e7114856b11753b3f84f904831d8c294e3843835669dac4e6875c1627391e2a5589d4f4a3cfb507f0956c16566feb624c697ec15f81508a6d26927d6240ec09672cc5c6afefba3e6ad828b722c2f13ad1814ee338fbe739ce915c8c77e65a0c1c6baf42e96474997c9eaf8a3c828bf609f60be9d98b30e4d86b14717b16929839e77583d990205a05689ac46773e83e6b35f95770c9c5919484c4e9bed34a85d1ee7db3f9914329f9f559bbed677f8a457c7aea17291d0c297fc2685c2876b0b57a67b91dfa7d20edce1872341c86a74c02c44f9047c059de10dc36ce904b3f1754dbee6b1e0657a194d563db45348198b3448dc365a3112a25c17fd5d02837cb4cb342ca831ba383b61ca684f9afdad1dab235ecd48f3c093bce9ca95449a1b26f7f2cb51b882ee5757ab3b99a078e0670",
"credential_finalization": "156511d3bed0e04bb931e21d4e01203ecb8035c8f2a13203a6d7c76156bd98c70161ec4dd434a0da576d7841483d2d6468e2d2df6b046a132a13a148be9f2ed9",
"client_registration_state": "5b4e8ccffa209c8df0ec71d0d1092de288ae05e472e71f9f95ff8d4b34a45a0f0ca151ef38b3b82f1b2166b6627671943ae8371b207dadfc4c4ccbc93db0fc51",
"client_login_state": "5b4e8ccffa209c8df0ec71d0d1092de288ae05e472e71f9f95ff8d4b34a45a0f0ca151ef38b3b82f1b2166b6627671943ae8371b207dadfc4c4ccbc93db0fc51246142ff274fe7c3385f6268e7e9c0c1ae2804c664308cec59d2cd0e5af683a402e1a67fc34629e5d0bc6c7d2873673e873514114e15a72a27e71fde337351ab793ba3bfd9cf3b5970a7557260fbd9c1f5480ad2434f3ca788bf0e298e3adb1728246142ff274fe7c3385f6268e7e9c0c1ae2804c664308cec59d2cd0e5af683a4",
"server_login_state": "00f0c2c254202ccf13ae33839e39a895a23778a8063334ba699cc4157646951fac5da2dc3363fc5cf051157b5f092c1d662ebe258211b02a051335aed2372387e8de8436dcd35b59eed28f6ca2cd4a0e969456e435393fabd0aa6b5e437018c49697c130b7075c7bc3deedb60ead5dd3b4b1f1cd8a86586f26fb1fca907bf27c9c97cc96869f519d4139e5ed967f4b82cee172a06c72702699d194ee49424bf11f73bf6ea75fe40712b3e9c7ae85328a02dacb453f7a95820836026f20dd4815",
"password_file": "0273a4a83ef4a4c014623a59d3188370e4592b0c1d2d695dda98a07339a1536e77c5aab89c3434cfb25289d087d3f35680d82a3eaf34b539317a82a219652e2bc1b151f423e945eab65a598624a9328265f91a8e69f5975c7517905db6091894b2125dee3f99fd11e6dfc10f3269010644abbe1676856c1fd28c3f1c11fb12e8a90944628ebe4b83026cca4f2b719ab0e836c01f42bc854a2262f7f0cfcf83b026426371c91a3a3f6ebc47225e092b76fb54636aec37618815f2ba0f9da6290def",
"export_key": "47c8aeb7e4b5fcb65728f8b2b07e7d0112496c3e72e5ecb17f00794e90d00fb4e4a9f8f2dccfdd19df8302e3c38d2b7f819ff373c3c829e34705e54dd95fcb09",
"session_key": "9c97cc96869f519d4139e5ed967f4b82cee172a06c72702699d194ee49424bf11f73bf6ea75fe40712b3e9c7ae85328a02dacb453f7a95820836026f20dd4815"
}
"#;
static TEST_VECTOR_P384: &str = r#"
{
"client_s_pk": "02d30caa7523fe782794a4dafdc34b236b3ef01a887ed6f705ff4644cb06df4140cfeaeeeb123d8a4394c485cf6c930fab",
"client_s_sk": "26f4f688d5c314da59d08a7672d444ff48c3580fd02ed9998a3906d507c506bf7059f166bec930032afc7fa59fdc6455",
"client_e_pk": "022d5b9d95e3686a8274435bf61414a0a371bd1351760fed07da6b281a419aef32c1b9b1eab59222111198d30ed63c7cbd",
"client_e_sk": "319076296bb7ce07bd9d383d7bfc6544222b99938e0ec627e7e284391f55e6a98b076a7843f383cbe802a907584fd271",
"server_s_pk": "03801a686045ee201b54f8367fc5a3ce577a5310b6431eadbf4abbf2f87213cf8b3853875f7f7badb10d029fe0c6f1cad4",
"server_s_sk": "209af74445ade701f4a99011c8e7304e3914ef9101fd92ea8b62d8ae6220a446cf544ca0eaf22552a21b149fc5e12008",
"server_e_pk": "021fdb138cd5b99a905285673be1b62085de588b4921ea35f3188aa6d4a57159d072ebda60a163996641473cd82e917633",
"server_e_sk": "061bc6ed455e852e8ad7eaf6836bbf061642043e48aef18416575071dc976577296eca9902af72c0d59e324e96abf34e",
"fake_sk": "3232e916073a895b65040efcec1a4038bf2fc4c41f8ae2e66bbccc5cf9ce8e31ca84e609b29af7207556452a4ebcf023",
"credential_identifier": "637265644964656e746966696572",
"id_u": "696455",
"id_s": "696453",
"password": "70617373776f7264",
"blinding_factor": "6522c4e1432f30cdf2d3ad20ddb2677ef444a9447ccb643992a545ed1c9a8c255af28ec952ff87046256a0d942c4be48",
"oprf_seed": "0b2ab841c8c79a53710e424a768939d9a36fc5baffc4fad5e8731736c831b3750f61010140ef62708b58dbc0734c4228",
"masking_nonce": "3df9ef31bbf2e58364690728a86862b5bb9b6cfb874631006b3fc8da98e13c4a196cf0ae225742a918be575c1f98c5c54ccaa679c55693834d2d7e0ad7374f29",
"envelope_nonce": "b358bd034c790212f83b8b9d2f1373a5067314392e244606292856afc9020405",
"client_nonce": "c14909f325841eed32aae25899d84c7044c2223e58a18f715977df310e2c2e7d",
"server_nonce": "8c4e71dab0435f22238d5e1ae8686d694ca8f6f0131ad5e106b6a909a53de050",
"context": "636f6e74657874",
"registration_request": "03182483430a1dcccd138466a63f05f523e44f2d0078fd9f21d0c3e145137437ca75f187d38d0d2b806b0c1f21fde2207f",
"registration_response": "0256a3f872e6307d2b7c93aee4573a3d18a61ac0cff31d5e2de354f36728663d4f491a040d1b88f2abd7594f2e5cd130fa03801a686045ee201b54f8367fc5a3ce577a5310b6431eadbf4abbf2f87213cf8b3853875f7f7badb10d029fe0c6f1cad4",
"registration_upload": "03c8c502f79257e6d92cbfe79767b539fd4e0dbec4fc6543bf9191587986a6e205b899f38ee12a383420488a69d6ce104478ee84a8c4031e77d13a8a8d42041d78ff48e67a970e399d4333812ae0579fa18b2eebcdf6c6fd3f1d180bca053c941726f4f688d5c314da59d08a7672d444ff48c3580fd02ed9998a3906d507c506bf915bdbf6215beb014ea81a290fa38804957f72f2b7473bf33d7e7cecf84f3edf5c67aeebae6b538c6a629a9046719966",
"credential_request": "03182483430a1dcccd138466a63f05f523e44f2d0078fd9f21d0c3e145137437ca75f187d38d0d2b806b0c1f21fde2207fc14909f325841eed32aae25899d84c7044c2223e58a18f715977df310e2c2e7d022d5b9d95e3686a8274435bf61414a0a371bd1351760fed07da6b281a419aef32c1b9b1eab59222111198d30ed63c7cbd",
"credential_response": "0256a3f872e6307d2b7c93aee4573a3d18a61ac0cff31d5e2de354f36728663d4f491a040d1b88f2abd7594f2e5cd130fa3df9ef31bbf2e58364690728a86862b5bb9b6cfb874631006b3fc8da98e13c4a42035f0afefe847d522d37a6a7e40965f1c81ebfda02b4632df08d7f8136ed222dcf9c723cefa9deb7fb60a4df1682bf9ff2906db5af47728b8ca3815ce820c4677787e631a39e6912ba7705a634c251bf420771a9cac8436a2b53b524b60f9e0047d97bad37d741e5abaf710b9c81bff8ed6d84a319c62dcbab952221e0e9d9511642043e48aef18416575071dc976577296eca9902af72c0d59e324e96abf34e025a82f2ecec7de30ae500fe0efc1b9b6bf925d0ec00b2e21e8a446acc37f063f5f77703d6cc87c3c688f4430fd8c6875a8abe86e344e263b4a450dd7a4684f26052c244defcec09768c6d305b73e09d8e9135228d98c8b84cc586d8cff97bb675",
"credential_finalization": "8c0e0cf31d1490a4678994bc4f47e8a5e1b4380d770881d000370ad8c5ef3ffd2e8d7f6101e9411e453a367a65ff146d",
"client_registration_state": "6522c4e1432f30cdf2d3ad20ddb2677ef444a9447ccb643992a545ed1c9a8c255af28ec952ff87046256a0d942c4be4803182483430a1dcccd138466a63f05f523e44f2d0078fd9f21d0c3e145137437ca75f187d38d0d2b806b0c1f21fde2207f",
"client_login_state": "6522c4e1432f30cdf2d3ad20ddb2677ef444a9447ccb643992a545ed1c9a8c255af28ec952ff87046256a0d942c4be4803182483430a1dcccd138466a63f05f523e44f2d0078fd9f21d0c3e145137437ca75f187d38d0d2b806b0c1f21fde2207fc14909f325841eed32aae25899d84c7044c2223e58a18f715977df310e2c2e7d022d5b9d95e3686a8274435bf61414a0a371bd1351760fed07da6b281a419aef32c1b9b1eab59222111198d30ed63c7cbd319076296bb7ce07bd9d383d7bfc6544222b99938e0ec627e7e284391f55e6a98b076a7843f383cbe802a907584fd271c14909f325841eed32aae25899d84c7044c2223e58a18f715977df310e2c2e7d",
"server_login_state": "79814d2b3ba60f503d5ac2a71cf10e66ef8f0d3af2cfcb20898415721147c48458b752bbd88d86c3399addfe7e1adca52f32055b893d59fb1b4c16b8bca49a6c425cb713061ea35d73472b9a70059f9007e0e881d934ae2d2f8b2cfd2a2ea2607aa2592bc9b387e4776df01efd287465a729a66b17550afd9a540536c437e89084d101d66afbf0be092f4b0ab1167ac4",
"password_file": "03c8c502f79257e6d92cbfe79767b539fd4e0dbec4fc6543bf9191587986a6e205b899f38ee12a383420488a69d6ce104478ee84a8c4031e77d13a8a8d42041d78ff48e67a970e399d4333812ae0579fa18b2eebcdf6c6fd3f1d180bca053c941726f4f688d5c314da59d08a7672d444ff48c3580fd02ed9998a3906d507c506bf915bdbf6215beb014ea81a290fa38804957f72f2b7473bf33d7e7cecf84f3edf5c67aeebae6b538c6a629a9046719966",
"export_key": "b05096e7ff9666fb3845c8ef552b69332b96d3ee63ad46c3da497d0ea85bbe8ee866f7fd606f958ecd08a2100adaa8fa",
"session_key": "7aa2592bc9b387e4776df01efd287465a729a66b17550afd9a540536c437e89084d101d66afbf0be092f4b0ab1167ac4"
}
"#;
static TEST_VECTOR_P384_P256: &str = r#"
{
"client_s_pk": "0254911f1d17aee72f5b891cfaeb8d0b0e68e9db9fb25f2dc42d672382f45b01e559639dc93a21a294461318be76144819",
"client_s_sk": "526e10a69a7f9c7ae685defcd8dc4f23f2b668f63cf558c9d76cdb83bbb5b216ef9e91763fa2e015c66ec827316131cc",
"client_e_pk": "03a01066dccb456e0e4a238d7afd1dcc788283154f0f7936295b950b316c66d0f52376b26e64585da98308c1ceea732c93",
"client_e_sk": "6de338c62147b2f5cd9579109b40584768e7dc1ae451f7d566fb28011bc13c180f3f1001a700c59488716b45011ad5e6",
"server_s_pk": "03df5ea7a932ff02124130743543236f3b8de290a1f27c8b9d518112beb72c527a8818a13914cf27c2375f75f832a23093",
"server_s_sk": "fd59eb004849e24eb70cd7d6e1ddcd87afae0743b82f2921c0bfe093831db2f17d031c4d63af482c778002394e3cb9ae",
"server_e_pk": "033b51d2ec7c6d8db890b5dbc0eaf13298ff25eb516249c2f367d84cb45d1717ed55f1b46f8b142ca899d480cc8a493e86",
"server_e_sk": "81443e69a1cc93d7a779235de18be512a0bfc4a2288b16e5323092e54ef4139dac21ed831d34e78e7d03dff908cae373",
"fake_sk": "05ef5e97565fa9fc1f485e4aad8516ad9104533397b2bac011aec371c2e98938a9b09b66fed328d4c9ca7bd1c941792c",
"credential_identifier": "637265644964656e746966696572",
"id_u": "696455",
"id_s": "696453",
"password": "70617373776f7264",
"blinding_factor": "3f3ff410cb7927e1ffe1d1c0f0d2360f49ef04effc2242782f155c858b50c4d6",
"oprf_seed": "9c98df8aaf13048694099325ff6bea1ddee273bf632e192c25fdf4a748d95a91",
"masking_nonce": "e4315a82379378b7d190c95a24d62871ec68b6b47f206d03a9ae0c27e6397556f50ecae65da56ee71155638cfdc932e8ec1997c16a96be1f55631977618c0b09",
"envelope_nonce": "26c52be641cd24569f0b566bb6fc3a8f6490229bac9ffef3345170be8d1135e4",
"client_nonce": "0f0f56edf27a8591093e280f79f6b304a003a4aab3565a59d4c4f6ea1e27e76b",
"server_nonce": "42679ba32e3301bab082c2d9580ea367cd8b737f422315329213c8b0dd5c2254",
"context": "636f6e74657874",
"registration_request": "030d2425e25d95ca6380beac64813feb5b127681fc2d3d37814a453f3815fb28dd",
"registration_response": "02c4610c2be8d4e308b8a31d9f4ea07686631b8237adfd7bbebd8c8c3be951d7d603df5ea7a932ff02124130743543236f3b8de290a1f27c8b9d518112beb72c527a8818a13914cf27c2375f75f832a23093",
"registration_upload": "02120a5aada0251e2a005bddd90a69003b97b8343467a25010e5a5f444c3cfb74ad562c4b4dcb66dc4083a81516e99cf0f4b77b4a187e359ada76ffcc29ba6e895aa3e2b1386be6eed16ad865b92d4f130526e10a69a7f9c7ae685defcd8dc4f23f2b668f63cf558c9d76cdb83bbb5b2162335ec8cc8815e9d4e604a48e1248be2bd92015103fe0396a167d7f5e031c640",
"credential_request": "030d2425e25d95ca6380beac64813feb5b127681fc2d3d37814a453f3815fb28dd0f0f56edf27a8591093e280f79f6b304a003a4aab3565a59d4c4f6ea1e27e76b03a01066dccb456e0e4a238d7afd1dcc788283154f0f7936295b950b316c66d0f52376b26e64585da98308c1ceea732c93",
"credential_response": "02c4610c2be8d4e308b8a31d9f4ea07686631b8237adfd7bbebd8c8c3be951d7d6e4315a82379378b7d190c95a24d62871ec68b6b47f206d03a9ae0c27e6397556e9aa0bfbbab92e92dd3a8e20799eba9ca690e2a7178256c394d413e9ea29321322ca32d89b4988835bc56366def8916684bdf2a06198f9535f898e35736ac1679925faffb6584c2ddf7d38185a095c5a471073142df269826c8a7baadf69ed8a3923d7b2a7073dfb2aeb780b75ab8cc991a0bfc4a2288b16e5323092e54ef4139dac21ed831d34e78e7d03dff908cae3730304fd477b4439cd862643630c4c141dccb9794d02228624d7fe1394c388fbdcdcfc6d522119b53354745e51e114f9ea1d25057b52c5403716ccf21ff0c3c22a946d65d3272add1236b8c8c0d01f801282",
"credential_finalization": "aad107b4b6396ef9ce3233c46992276908c3490026164817aec4b3ee301821a6",
"client_registration_state": "3f3ff410cb7927e1ffe1d1c0f0d2360f49ef04effc2242782f155c858b50c4d6030d2425e25d95ca6380beac64813feb5b127681fc2d3d37814a453f3815fb28dd",
"client_login_state": "3f3ff410cb7927e1ffe1d1c0f0d2360f49ef04effc2242782f155c858b50c4d6030d2425e25d95ca6380beac64813feb5b127681fc2d3d37814a453f3815fb28dd0f0f56edf27a8591093e280f79f6b304a003a4aab3565a59d4c4f6ea1e27e76b03a01066dccb456e0e4a238d7afd1dcc788283154f0f7936295b950b316c66d0f52376b26e64585da98308c1ceea732c936de338c62147b2f5cd9579109b40584768e7dc1ae451f7d566fb28011bc13c180f3f1001a700c59488716b45011ad5e60f0f56edf27a8591093e280f79f6b304a003a4aab3565a59d4c4f6ea1e27e76b",
"server_login_state": "2bee3adc9a7db1e964fd11f6b0a4cc87286762fa7548ab5d3393966f19da7cc5ca72928b4ad955a857ead83fe4a375afb7bb050f8c09c755823d7062e52c37bca3853ad81a963f92049b08f96b940e17cd5f2a8767714c5e28be1c5fa95a8d26",
"password_file": "02120a5aada0251e2a005bddd90a69003b97b8343467a25010e5a5f444c3cfb74ad562c4b4dcb66dc4083a81516e99cf0f4b77b4a187e359ada76ffcc29ba6e895aa3e2b1386be6eed16ad865b92d4f130526e10a69a7f9c7ae685defcd8dc4f23f2b668f63cf558c9d76cdb83bbb5b2162335ec8cc8815e9d4e604a48e1248be2bd92015103fe0396a167d7f5e031c640",
"export_key": "3cf2a36cb8f9df152f797718fbdead0dac400eb45300e6c93fa40c0b42713795",
"session_key": "a3853ad81a963f92049b08f96b940e17cd5f2a8767714c5e28be1c5fa95a8d26"
}
"#;
#[cfg(feature = "ristretto255")]
static TEST_VECTOR_P384_RISTRETTO255: &str = r#"
{
"client_s_pk": "02cc4db2cf4cd01a188ad2d24f37c13d542253202a15c1967fbc01ff3c67ec3976a09d950be6e61fd331ceee6c73afe071",
"client_s_sk": "90a2c638013427e671591d125152921d0d18a84a6de44fd7b2b58e139b295628c137d26fc8e4b31e3d23e0a886aa70e2",
"client_e_pk": "031c9d7101bd543a64537944c7ffbef579852d03e109386d1cb7d40438a494a3f466daf8ce56866ff94cca71e4c8a4baf4",
"client_e_sk": "6e84980c5aaa6d78d3d634668b9a8427219ebf3da0dbc364d41cf29549c8dbecdcf55c91794b1147ed1f80b3f21aab9a",
"server_s_pk": "0330a19238b845ed798b626d991645d5454b35bdf78c1aaaa8370ca1ee90839bdfeb3022f0967103a9bf7dd65f0bd764e7",
"server_s_sk": "c947228ef3e8f98e14dcf8d44209508133425fa3ecd5b5dea57271b34619ec78503954df1c0d8a17067fdea51568feb0",
"server_e_pk": "035ec4661b6d7d838d34438a683e2260be53e49adf362f7e68e366d4eada87a475c98898f57b38f89777f470f33056a5f5",
"server_e_sk": "91d5f270837a3109f011a0fb1dc05fb26cb6c312dbaf5258d9c731a581e9398134cb0c5cadad0b09aeb1bbb1856973ac",
"fake_sk": "440fc2ef4f616072e5cc984cb49a0a6100d8ba22a002b4a7e88baf000da81acf26399e0cb1277cd55e4cbf0d595714d6",
"credential_identifier": "637265644964656e746966696572",
"id_u": "696455",
"id_s": "696453",
"password": "70617373776f7264",
"blinding_factor": "18b3146671040f5e23f8df4e40411af98c64f356f34d4abdf8e7023c173a130e",
"oprf_seed": "d79e4976efa4866928d3e4fe7e463ec9e1ed756b67a2b156a991ce8c08b7a5d351d42f6e79416d30cae9032afbdedd4e46a360d3a67a2c088cc4f17f23cf548a",
"masking_nonce": "f28da85667feea48ee90660484e463b5a3e9c26d78ee966919413e28e5e3298314a233fe33720e72f2086e9adafa8f3ed4b994271e764a836572492e0706b6c5",
"envelope_nonce": "b33217f0bfca84df0f5c0e06944d7099ae657138e093e8b8fbd06886ca704f1b",
"client_nonce": "6d6547ddbb040af90fd6fcd961e605ed2eec4c2dee24ae729f5145eaab8c3867",
"server_nonce": "90901fa0e77d2e184ea1cde30eecd25e7c076245fb9ed40dcf2e64249d58c0be",
"context": "636f6e74657874",
"registration_request": "b4ab9b7315e3a66face7d81f24d8e2d538e6a09acb929fa3990d8fe3f5cdc665",
"registration_response": "aa9159f5472d0f32d06205095eeca6cf2bfb402e2174120b1bb2d42719c5f93b0330a19238b845ed798b626d991645d5454b35bdf78c1aaaa8370ca1ee90839bdfeb3022f0967103a9bf7dd65f0bd764e7",
"registration_upload": "02c1c9a0f2a01152ca24c81449e4d86c9d88f2709fc5e8c03c368b8952eae9ef9485a9dc65cf9cee71991266a9c339122601b02d1deee0df0ae3d4cd90cd0ee7b775cecaf73519fa7b1744344dd8f667f566c7fff174152c539fa0e276135862cb2581154db6ce754b594f13c4cdc7649d90a2c638013427e671591d125152921d0d18a84a6de44fd7b2b58e139b2956288a1c235698eb9f64a9b3ff2392a2f927c724a4bd9eac605f445d744614ccd15ed9222d0d0c6a4ba5c3edfa58b2ba386b9cfdb23229c2baf9cd01d30cc6a4267d",
"credential_request": "b4ab9b7315e3a66face7d81f24d8e2d538e6a09acb929fa3990d8fe3f5cdc6656d6547ddbb040af90fd6fcd961e605ed2eec4c2dee24ae729f5145eaab8c3867031c9d7101bd543a64537944c7ffbef579852d03e109386d1cb7d40438a494a3f466daf8ce56866ff94cca71e4c8a4baf4",
"credential_response": "aa9159f5472d0f32d06205095eeca6cf2bfb402e2174120b1bb2d42719c5f93bf28da85667feea48ee90660484e463b5a3e9c26d78ee966919413e28e5e329838f55cc8db1b7a3159515f4f8659424bec2003f52ddc1cacf3375ebc99ce25796776206afc2336e9eac2526801f3dc865ea4f41312342de7f0380a3dbf19d07fca963efbd55279d227397bdd4061f0d6018f8e921568a13a48ead1841adb79e6fccca36e58c831e08ba390d374b54d2ea57872867e522510a5b5acd6e8db6eea17728d8193047d15a92c6b7ccc21f731a286cb6c312dbaf5258d9c731a581e9398134cb0c5cadad0b09aeb1bbb1856973ac02a333fd1a99cd9efdc223198828ceb73535ad7583f8b2d1a660e9111fb90e7d59699c6a59b7222ffef86be508701cfb16327891268981272101c472e0018e8f685976e9fc02a760a05c4260477400092cfb9e57f91c487194cbb6eee9abe2d99957151a0f11bcfee0fe3862012119847c",
"credential_finalization": "4a6ecd34b51d45a77f34f8a959dbac7e507c749ec869eb936d6c591691f74c13c8906a9e02071768eb28f6f0244e9a673c42bdbf326319c5ae93a8837fad2a5b",
"client_registration_state": "18b3146671040f5e23f8df4e40411af98c64f356f34d4abdf8e7023c173a130eb4ab9b7315e3a66face7d81f24d8e2d538e6a09acb929fa3990d8fe3f5cdc665",
"client_login_state": "18b3146671040f5e23f8df4e40411af98c64f356f34d4abdf8e7023c173a130eb4ab9b7315e3a66face7d81f24d8e2d538e6a09acb929fa3990d8fe3f5cdc6656d6547ddbb040af90fd6fcd961e605ed2eec4c2dee24ae729f5145eaab8c3867031c9d7101bd543a64537944c7ffbef579852d03e109386d1cb7d40438a494a3f466daf8ce56866ff94cca71e4c8a4baf46e84980c5aaa6d78d3d634668b9a8427219ebf3da0dbc364d41cf29549c8dbecdcf55c91794b1147ed1f80b3f21aab9a6d6547ddbb040af90fd6fcd961e605ed2eec4c2dee24ae729f5145eaab8c3867",
"server_login_state": "2e28f843e78b3a64e90d4fe4e69e6c905a6f0dc88ec4da004cc6aa83709f5f62631c0359489957187f9bbc1e188a9577cd839e20210ae14da99c921d779a7e7b05542f09b2fa76e5ab43a73b14f3b4be10d14c56271eb1a5a1ee01ef781d220321ca21deaf632855aa442d91f32b6f4d89c5b87cadaf158b93cf71c0c84b7f7ec26fc66b9419dbf492de4a2e9874ef8002c792726b7dc1db770453a5eb1dc94fe245885e7d3aa33ed6e262db3b9344624a5d92b97521a169c78f837d8e5a4f7b",
"password_file": "02c1c9a0f2a01152ca24c81449e4d86c9d88f2709fc5e8c03c368b8952eae9ef9485a9dc65cf9cee71991266a9c339122601b02d1deee0df0ae3d4cd90cd0ee7b775cecaf73519fa7b1744344dd8f667f566c7fff174152c539fa0e276135862cb2581154db6ce754b594f13c4cdc7649d90a2c638013427e671591d125152921d0d18a84a6de44fd7b2b58e139b2956288a1c235698eb9f64a9b3ff2392a2f927c724a4bd9eac605f445d744614ccd15ed9222d0d0c6a4ba5c3edfa58b2ba386b9cfdb23229c2baf9cd01d30cc6a4267d",
"export_key": "d22fbb27898c9d010471f75d5c914cc96543a381e895660e9650f718bbd410c3d1fdee25d251af597cd21bd1b4165861e19bc424dc9cd9c9381cc278fa812b38",
"session_key": "c26fc66b9419dbf492de4a2e9874ef8002c792726b7dc1db770453a5eb1dc94fe245885e7d3aa33ed6e262db3b9344624a5d92b97521a169c78f837d8e5a4f7b"
}
"#;
#[cfg(feature = "curve25519")]
static TEST_VECTOR_CURVE25519_P256: &str = r#"
{
"client_s_pk": "e109acb05ead255b0ddef3b1b2a04161149fdbcf9d1a1583cf3bb39dd43f3d6f",
"client_s_sk": "88e628927240f786517e00a5b77ed2fb383e11361c0d4b3324ffb6b927aef373",
"client_e_pk": "334dff6942070b0b1395835e54dc7531699fd5ceed7f197f81d5d28090316b21",
"client_e_sk": "78ab0d232c8231d1a84ad3cfb4d27226d432954ba9a422a825baac4ac4ee3257",
"server_s_pk": "b005c8dca395f0ecd2b6355d600d46199e2f9f389aa84e719d75424b4b8b2b44",
"server_s_sk": "88193c55d0a16c2c833be2a0004ebba32ed63019d94b1a498cdfc04310a9a563",
"server_e_pk": "20303db181367b52118c89bd7e0d4d97d1c6382bd65ca166cd9876c9b6fc9f1d",
"server_e_sk": "58bbac2fd1ee62043eb05631a361b71abfede72530899129035a0ea5454e8042",
"fake_sk": "08f3aeac6bd5d6a30cd59e0c74e0ec90254828a3ff8b18a622a3e8bc6a31be73",
"credential_identifier": "637265644964656e746966696572",
"id_u": "696455",
"id_s": "696453",
"password": "70617373776f7264",
"blinding_factor": "6b68b1711d94273abfec09e6a747b8d5f9b3b42250dc867d9a69808ddde97602",
"oprf_seed": "a1ebc0d9b741fbe1b4d3d5b97a89eeca2e3f42ea54afad209e3462d9d8c2f5c3",
"masking_nonce": "653f38d85dd789596c39617ef7a54d33b20dc40bab5b1acfc8deef215c14322ab9d7801cd27ac622bcd31f62cf0d739a1e296a2ca8b2f8be854290e0aad33068",
"envelope_nonce": "aa76064915e29d00600b6a2b694c0da826a9388bf58fa39fb41fa22b3e6083f0",
"client_nonce": "be19d2540482db6096279c55970711cda737c4cc1695a8e417d1ebf19691f223",
"server_nonce": "1eaa5da8f04d0b707e147ff78af9aa56f9d9b6042205063c24579d10048cb06e",
"context": "636f6e74657874",
"registration_request": "02efc05fc89c30469d017160a3ac0630a3546b19dd20193a7cbea801482e4d0f00",
"registration_response": "02120dbe7291cf53739fef3955f49956147f518e9f2ee9f17e4c061fefe09c3cccb005c8dca395f0ecd2b6355d600d46199e2f9f389aa84e719d75424b4b8b2b44",
"registration_upload": "ba486310fcc3cbacf1b3835bcd06aa33d302a8cff11874a34f10d2ed3940f81d547dc06cd2faa5afe8fe75880c1e6ebca4b4734f8a9e95a8ff29e19db3d5d99e88e628927240f786517e00a5b77ed2fb383e11361c0d4b3324ffb6b927aef373ef4454dd53eedad0082f2dafb2ef474394d8a15dfc4a907f5fbf75403b399a9e",
"credential_request": "02efc05fc89c30469d017160a3ac0630a3546b19dd20193a7cbea801482e4d0f00be19d2540482db6096279c55970711cda737c4cc1695a8e417d1ebf19691f223334dff6942070b0b1395835e54dc7531699fd5ceed7f197f81d5d28090316b21",
"credential_response": "02120dbe7291cf53739fef3955f49956147f518e9f2ee9f17e4c061fefe09c3ccc653f38d85dd789596c39617ef7a54d33b20dc40bab5b1acfc8deef215c14322a25ceb12702124627c855cd281b4bedb24821ddee72fac2ff840343772ebb3145b9062e1b6804a9b48782be7194cf1092b0f0873ca01a56c04612b8070602e1a361731d0a51df56d9badcb8dfae739c71d640cd5fc49a53d40d109c261a587b9158bbac2fd1ee62043eb05631a361b71abfede72530899129035a0ea5454e80424a84ce00257ddfcfa70d36591f2c2db293276114660134be94d3f5dad10c312ccdc54d5a631789a6d39697a35e12a4900ff7f356b3aa97773f225d32dc901b21",
"credential_finalization": "e1ac3b00c834a871e3163ea28b4611810e530b57c9e0e698b5fe6353c9f7ebba",
"client_registration_state": "6b68b1711d94273abfec09e6a747b8d5f9b3b42250dc867d9a69808ddde9760202efc05fc89c30469d017160a3ac0630a3546b19dd20193a7cbea801482e4d0f00",
"client_login_state": "6b68b1711d94273abfec09e6a747b8d5f9b3b42250dc867d9a69808ddde9760202efc05fc89c30469d017160a3ac0630a3546b19dd20193a7cbea801482e4d0f00be19d2540482db6096279c55970711cda737c4cc1695a8e417d1ebf19691f223334dff6942070b0b1395835e54dc7531699fd5ceed7f197f81d5d28090316b2178ab0d232c8231d1a84ad3cfb4d27226d432954ba9a422a825baac4ac4ee3257be19d2540482db6096279c55970711cda737c4cc1695a8e417d1ebf19691f223",
"server_login_state": "6c744915f5aba566f8cc9c601e3a0388c679a07da549905f0350ec3fbc2bbecf8b62a285aa728a8a124d9b30b986745e334143e0fdd1b112fcfb7f87c412da6b405910d03caf6cb3ec6b21c3c7095f136ff050f3c294ee268c537116b90c8c18",
"password_file": "ba486310fcc3cbacf1b3835bcd06aa33d302a8cff11874a34f10d2ed3940f81d547dc06cd2faa5afe8fe75880c1e6ebca4b4734f8a9e95a8ff29e19db3d5d99e88e628927240f786517e00a5b77ed2fb383e11361c0d4b3324ffb6b927aef373ef4454dd53eedad0082f2dafb2ef474394d8a15dfc4a907f5fbf75403b399a9e",
"export_key": "c8d95a7b0a2c3baa488949effc399d39e64ee09cae26e26ee0ded26e295d9f0b",
"session_key": "405910d03caf6cb3ec6b21c3c7095f136ff050f3c294ee268c537116b90c8c18"
}
"#;
#[cfg(feature = "curve25519")]
static TEST_VECTOR_CURVE25519_P384: &str = r#"
{
"client_s_pk": "47bf6620ef1793404dedc4b92516e8633b3580d8e9ab7d38f4664a9cc4308e3c",
"client_s_sk": "7051dd78600860b1c96bfd4729fc792111c06b7653057ab9dd32efe03052a564",
"client_e_pk": "741bb246da7c5b1361038e78d25006c3d8388b7361e9ca082e5a9770edfd7e42",
"client_e_sk": "68ea700379d9f0d73594cd3edcd2096a8ce99af9faf736c11262d15b91584f51",
"server_s_pk": "cef452814c8d96e7187efdc6f39b4cf3b9af79a3303fdc1ff06d73fcdfa9fc09",
"server_s_sk": "40265c6e7b69c63b1dd77b0a5b55736ed5a3a3e1ef4d6a2be5d84a2b8c9f4078",
"server_e_pk": "95f2ea9503fae836c029d7a85229eb537b6a82c9f0362802e488878eaef5655f",
"server_e_sk": "f0209a74b6f09e05d3214bbdbbd4d1c3386a7d47213746876e8d840a56299f65",
"fake_sk": "8865f09f0d9270e951c7fb723922095ace2febd5a673fd2bfe85456140afb97e",
"credential_identifier": "637265644964656e746966696572",
"id_u": "696455",
"id_s": "696453",
"password": "70617373776f7264",
"blinding_factor": "23b19816e290cafe9796db34c4922211de1498df4bab2e5ce0c318e533658771d117e9a9eae9d016d7433d3400b4d99c",
"oprf_seed": "b29c73aa3651b3eda0cd7e327c0c60693c2b667707d4d7825f862ccca1e319ab0ca5de2f6fa89829cc73c1340fcff00b",
"masking_nonce": "25431b6a925130d744101b95fd1ddd822173d97a945b3a7f721cff33c4d3afd4fd93c70914553bde5d50144117cd601449bcdc15f2606a38402aea3ba404a8b1",
"envelope_nonce": "f7a5c2edad92af2dc4d0901e54090341a66cd925d0b487f92a64c8cf0aaefe2d",
"client_nonce": "48b90f2c8909576edc61743b84d66ce93ae5432d60bb29eadb076e027a163731",
"server_nonce": "b4e8004b2f78bd47a132a9ae1640984990066856553ec12e6d409c55af0f93db",
"context": "636f6e74657874",
"registration_request": "036da1da44ad100ce9c80f074b98e8564e131d6d9186c666e44e2f2ac74822a86aa9af120bc2ebbba3f81dddea21fb418e",
"registration_response": "02faff596ac44ab490917a3153c50d67f46bfd12877c2d42d9ae855af3160461aa055ba4900a7c2df6b89acee908376b09cef452814c8d96e7187efdc6f39b4cf3b9af79a3303fdc1ff06d73fcdfa9fc09",
"registration_upload": "4f6f6c4b7d2dce29897218c5c609aea30288112ed8c33d8cd67f2b19c3fd1928fb65782af6070e84bb7a542813fff00fb7f71a7797089072babfe06ba01d1845e0c8b6a9b17b65f6b992c00ce34f115b7051dd78600860b1c96bfd4729fc792111c06b7653057ab9dd32efe03052a564d02881210e8c7e043f278032e691a23e8451377624aebcbf7364155158c8cc0a3df1f2c3e669785b81f17016ba7a7acd",
"credential_request": "036da1da44ad100ce9c80f074b98e8564e131d6d9186c666e44e2f2ac74822a86aa9af120bc2ebbba3f81dddea21fb418e48b90f2c8909576edc61743b84d66ce93ae5432d60bb29eadb076e027a163731741bb246da7c5b1361038e78d25006c3d8388b7361e9ca082e5a9770edfd7e42",
"credential_response": "02faff596ac44ab490917a3153c50d67f46bfd12877c2d42d9ae855af3160461aa055ba4900a7c2df6b89acee908376b0925431b6a925130d744101b95fd1ddd822173d97a945b3a7f721cff33c4d3afd4ef3e8ead079f059d604ce87722708a50b49fd35ab475d7bad69d507e5a7f1bc499ac79e68265a5a89ee3ef56e250e3b724113ba179d07bf846ff2c068e0e46e2c57c5d98571d169bef75148c2adad3e4d6a927b53763fa8fd197ab6b73500a6dcbc6718556f48a74e87e737802d08c9df0209a74b6f09e05d3214bbdbbd4d1c3386a7d47213746876e8d840a56299f65f7bc99ca5350019cc62b759ddacbb55172e13b762614ebe959987840db244c7f548798cdd6a3354f79d58c1fd39715cc31b7ab7feb1702aec24da864500831fb39a83920b1e2e32ef23e73987fde2e24",
"credential_finalization": "554a499b045b2c94d68f0bddeb41f76c32f7b357000eadbfea0487ba8dc0b146491f4ff614619e955686d64d4575f564",
"client_registration_state": "23b19816e290cafe9796db34c4922211de1498df4bab2e5ce0c318e533658771d117e9a9eae9d016d7433d3400b4d99c036da1da44ad100ce9c80f074b98e8564e131d6d9186c666e44e2f2ac74822a86aa9af120bc2ebbba3f81dddea21fb418e",
"client_login_state": "23b19816e290cafe9796db34c4922211de1498df4bab2e5ce0c318e533658771d117e9a9eae9d016d7433d3400b4d99c036da1da44ad100ce9c80f074b98e8564e131d6d9186c666e44e2f2ac74822a86aa9af120bc2ebbba3f81dddea21fb418e48b90f2c8909576edc61743b84d66ce93ae5432d60bb29eadb076e027a163731741bb246da7c5b1361038e78d25006c3d8388b7361e9ca082e5a9770edfd7e4268ea700379d9f0d73594cd3edcd2096a8ce99af9faf736c11262d15b91584f5148b90f2c8909576edc61743b84d66ce93ae5432d60bb29eadb076e027a163731",
"server_login_state": "ef411e8209facbabbeb99d7b73600d6f6c54df43969048381619b7e2c448eff411a67be3f782d9e7a64fb86434cf4923976f0526ff3ddb232492982e34b85e22ca4d6ce6d77608e69966e6ee946df1895483da7e27974d8013f668aab235376d0fc20aa7385934f47c498b804483c436514ac31e3817067615464a89afb46ffff7cc2bd52e05cbee3a23c6ec9a43705e",
"password_file": "4f6f6c4b7d2dce29897218c5c609aea30288112ed8c33d8cd67f2b19c3fd1928fb65782af6070e84bb7a542813fff00fb7f71a7797089072babfe06ba01d1845e0c8b6a9b17b65f6b992c00ce34f115b7051dd78600860b1c96bfd4729fc792111c06b7653057ab9dd32efe03052a564d02881210e8c7e043f278032e691a23e8451377624aebcbf7364155158c8cc0a3df1f2c3e669785b81f17016ba7a7acd",
"export_key": "c90f604c28e60aa7b386ae9b37fc1d9d2f9aabf9c4e6ead8eb2b132667121f19bc6e99afdfc287aff26224fc451a9328",
"session_key": "0fc20aa7385934f47c498b804483c436514ac31e3817067615464a89afb46ffff7cc2bd52e05cbee3a23c6ec9a43705e"
}
"#;
#[cfg(all(feature = "curve25519", feature = "ristretto255"))]
static TEST_VECTOR_CURVE25519_RISTRETTO255: &str = r#"
{
"client_s_pk": "425d9690de8c494cf18020f0b8977aa02d2701e20ae22f7e9a22396b219bdd09",
"client_s_sk": "48064fdc57a4f75dd1e07013c7123cc9f63bcc7cc812fd4d6785b10d323b2549",
"client_e_pk": "643a85ac2e212108b822e2ed22705aa1da98db515cc010ea5f803a227be1c919",
"client_e_sk": "70662c87da47502582f94edcc41babaf50eff95125ac666a9ff02f06c852276a",
"server_s_pk": "a4fac053abfb5d79def37a3ea1d19d85d34b84a0ac4cbfc4cea1f368cd99553c",
"server_s_sk": "50e025031678aea84429d14259ab2d7e2d95f552e7a694d58d00e1ed4517b14f",
"server_e_pk": "957eb70736694ad3058275fae43bb48204d88d65b80b7b197192f78c0942d013",
"server_e_sk": "6802638853a41e9773fe51a9ab442465176e2ccef3eb3855a343a411ac35e952",
"fake_sk": "881be0fdc6ba406b4725daf16cf0dd6cef20c8e401db26c6827fb93f30906c69",
"credential_identifier": "637265644964656e746966696572",
"id_u": "696455",
"id_s": "696453",
"password": "70617373776f7264",
"blinding_factor": "7dbc12dd8b1280bc76567b32f150e1c96a7d88d8dbb7083eae67c85990905e01",
"oprf_seed": "4c335f4d75f53e9bf593fbbb4971763fc27caed1151ea054aa582178794a95b11ce9fbead333205f705cb9dc717ed643fa743ddfa606f7d7e02fcb750d70294c",
"masking_nonce": "4df6e5189bce92a87ade075e4bfb5aba25e1a215c9da97bfefe3751abbd516f74e65aa7f5571e603936e8aba0d60a317fe991478e12e97e5303ddac6b5eed135",
"envelope_nonce": "bc787b112a62e219225fb7b157a7455014726c9ef4176551526615511d2b08c1",
"client_nonce": "1e930824df3cd0e4d0423a87371ad1d903770fed134a2ff5839493ea29d4ac5f",
"server_nonce": "6d41b975cd7106c6db6e1d89af45e3e7f1635cd0c1c866be96d517314d04b585",
"context": "636f6e74657874",
"registration_request": "ac14c0042d20a0feb27ef3215db82e66786872cddc0568508318526477cc1830",
"registration_response": "3243003d14d0d29621c4136f9ce9a09d4fc24e77fccffeb9619134a26d14c226a4fac053abfb5d79def37a3ea1d19d85d34b84a0ac4cbfc4cea1f368cd99553c",
"registration_upload": "3b7ccbd3e9aba6b0e1b04e2fe7a5a1e7a9e1d4c2ab66e87e2626ab585c50fb3d8f6ce5c600adf8bb328211944c9ff00135fafad3b3552806bda433db0ea2be69f9abc83d572dfefa4d0062dd98f73a51cf9398621fd7398584488614f611ed3748064fdc57a4f75dd1e07013c7123cc9f63bcc7cc812fd4d6785b10d323b254917976677c28c001c43665f9709975a5c403a2fbbaf2fe853b80497ca5bb0e8300c671775ced7247fe6304c34c4f1f96ddcab1323682741cf899a9d208d392ce0",
"credential_request": "ac14c0042d20a0feb27ef3215db82e66786872cddc0568508318526477cc18301e930824df3cd0e4d0423a87371ad1d903770fed134a2ff5839493ea29d4ac5f643a85ac2e212108b822e2ed22705aa1da98db515cc010ea5f803a227be1c919",
"credential_response": "3243003d14d0d29621c4136f9ce9a09d4fc24e77fccffeb9619134a26d14c2264df6e5189bce92a87ade075e4bfb5aba25e1a215c9da97bfefe3751abbd516f77933211492cc397232556fd7092e998fb80ef2d5fb351cec4ab89864fc6822dcb7c88065773da1f9f89df37a18e012c60a90a8464242bd0b627dfd62a435f2ae4ddb54d57b3fb76f625cdb71b1e1927558c3e378503dd17251997c9d19dba8bb0331f474eb49035edc30b4cb8eec75ad261c6ef789ce1dd24d1dc1c1a4004cb36802638853a41e9773fe51a9ab442465176e2ccef3eb3855a343a411ac35e952925e2d2267d597d6f6a672cd95f6ea7ec152ea4d47d4cc7806ae406910627c2f2e8511ea4a4440a7538f7a964f7e789c8041e7a7bafb60c9c07bf9748a435da4a0b6cd195136427cca4414894202913585e488eb1f3406d3e272415827ddc137",
"credential_finalization": "f3b767aeabf8fccbabee31baae90ccb95f0aff73824f8832e1ef91d988f873d4c1c92c6dd47cc3b6cf3d9ba3d74d2111e7709060da1ad17eda5697ad5bdf1523",
"client_registration_state": "7dbc12dd8b1280bc76567b32f150e1c96a7d88d8dbb7083eae67c85990905e01ac14c0042d20a0feb27ef3215db82e66786872cddc0568508318526477cc1830",
"client_login_state": "7dbc12dd8b1280bc76567b32f150e1c96a7d88d8dbb7083eae67c85990905e01ac14c0042d20a0feb27ef3215db82e66786872cddc0568508318526477cc18301e930824df3cd0e4d0423a87371ad1d903770fed134a2ff5839493ea29d4ac5f643a85ac2e212108b822e2ed22705aa1da98db515cc010ea5f803a227be1c91970662c87da47502582f94edcc41babaf50eff95125ac666a9ff02f06c852276a1e930824df3cd0e4d0423a87371ad1d903770fed134a2ff5839493ea29d4ac5f",
"server_login_state": "74116bce8ba020be04b87f65f0cc7687f01538ba573c931ce11b761dd032e7112a2da04f92adda01a33682e425fda5ec0d473f8fabf9bf5f35ccf226e05dd89399de8bb7f84e9ff90a9e0090c98cd3fcfa930da647db50ccea008d44810297c92e0a27400591aabfe0878c2c7040b6a67da760c0d88fba2443b5f0840afe274edd42475990df27dfd26d3823e429e7092664f5cc3e12e9ca4854f44e8d589d79a1a9b796137c2e72e3ff79aceeaf34aa885f1986b849ddee8d3b8635a79a5e41",
"password_file": "3b7ccbd3e9aba6b0e1b04e2fe7a5a1e7a9e1d4c2ab66e87e2626ab585c50fb3d8f6ce5c600adf8bb328211944c9ff00135fafad3b3552806bda433db0ea2be69f9abc83d572dfefa4d0062dd98f73a51cf9398621fd7398584488614f611ed3748064fdc57a4f75dd1e07013c7123cc9f63bcc7cc812fd4d6785b10d323b254917976677c28c001c43665f9709975a5c403a2fbbaf2fe853b80497ca5bb0e8300c671775ced7247fe6304c34c4f1f96ddcab1323682741cf899a9d208d392ce0",
"export_key": "2bd139ff06ca5fe9897640fefbd00380b080239efb84d796df997c235306c9829e52694193f0d0e2bb69235e42276fffa933b436ebd6132a59d7062f3a74b83d",
"session_key": "dd42475990df27dfd26d3823e429e7092664f5cc3e12e9ca4854f44e8d589d79a1a9b796137c2e72e3ff79aceeaf34aa885f1986b849ddee8d3b8635a79a5e41"
}
"#;
fn decode(values: &Value, key: &str) -> Option<Vec<u8>> {
values[key].as_str().and_then(|s| hex::decode(s).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(),
fake_sk: decode(values, "fake_sk").unwrap(),
credential_identifier: decode(values, "credential_identifier").unwrap(),
id_u: decode(values, "id_u").unwrap(),
id_s: decode(values, "id_s").unwrap(),
password: decode(values, "password").unwrap(),
blinding_factor: decode(values, "blinding_factor").unwrap(),
oprf_seed: decode(values, "oprf_seed").unwrap(),
masking_nonce: decode(values, "masking_nonce").unwrap(),
envelope_nonce: decode(values, "envelope_nonce").unwrap(),
client_nonce: decode(values, "client_nonce").unwrap(),
server_nonce: decode(values, "server_nonce").unwrap(),
context: decode(values, "context").unwrap(),
registration_request: decode(values, "registration_request").unwrap(),
registration_response: decode(values, "registration_response").unwrap(),
registration_upload: decode(values, "registration_upload").unwrap(),
credential_request: decode(values, "credential_request").unwrap(),
credential_response: decode(values, "credential_response").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_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(),
}
}
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());
s.push_str(format!("\"fake_sk\": \"{}\",\n", hex::encode(&p.fake_sk)).as_str());
s.push_str(
format!(
"\"credential_identifier\": \"{}\",\n",
hex::encode(&p.credential_identifier)
)
.as_str(),
);
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());
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_seed\": \"{}\",\n", hex::encode(&p.oprf_seed)).as_str());
s.push_str(
format!(
"\"masking_nonce\": \"{}\",\n",
hex::encode(&p.masking_nonce)
)
.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!("\"context\": \"{}\",\n", hex::encode(&p.context)).as_str());
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(),
);
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(),
);
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_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());
s.push_str("}\n");
s
}
fn generate_parameters<CS: CipherSuite>() -> Result<TestVectorParameters, ProtocolError>
where
<OprfHash<CS> as OutputSizeUser>::OutputSize:
IsLess<U256> + IsLessOrEqual<<OprfHash<CS> as BlockSizeUser>::BlockSize>,
OprfHash<CS>: Hash,
<OprfHash<CS> as CoreProxy>::Core: ProxyHash,
<<OprfHash<CS> as CoreProxy>::Core as BlockSizeUser>::BlockSize: IsLess<U256>,
Le<<<OprfHash<CS> as CoreProxy>::Core as BlockSizeUser>::BlockSize, U256>: NonZero,
// ClientRegistration: KgSk + KgPk
<OprfGroup<CS> as Group>::ScalarLen: Add<<OprfGroup<CS> as Group>::ElemLen>,
ClientRegistrationLen<CS>: ArrayLength<u8>,
// RegistrationResponse: KgPk + KePk
<OprfGroup<CS> as Group>::ElemLen: Add<<CS::KeGroup as KeGroup>::PkLen>,
RegistrationResponseLen<CS>: ArrayLength<u8>,
// Envelope: Nonce + Hash
NonceLen: Add<OutputSize<OprfHash<CS>>>,
EnvelopeLen<CS>: ArrayLength<u8>,
// RegistrationUpload: (KePk + Hash) + Envelope
<CS::KeGroup as KeGroup>::PkLen: Add<OutputSize<OprfHash<CS>>>,
Sum<<CS::KeGroup as KeGroup>::PkLen, OutputSize<OprfHash<CS>>>:
ArrayLength<u8> + Add<EnvelopeLen<CS>>,
RegistrationUploadLen<CS>: ArrayLength<u8>,
// ServerRegistration = RegistrationUpload
// Ke1Message: Nonce + KePk
NonceLen: Add<<CS::KeGroup as KeGroup>::PkLen>,
Ke1MessageLen<CS>: ArrayLength<u8>,
// CredentialRequest: KgPk + Ke1Message
<OprfGroup<CS> as Group>::ElemLen: Add<Ke1MessageLen<CS>>,
CredentialRequestLen<CS>: ArrayLength<u8>,
// ClientLogin: KgSk + CredentialRequest + Ke1State
<OprfGroup<CS> as Group>::ScalarLen: Add<CredentialRequestLen<CS>>,
Sum<<OprfGroup<CS> as Group>::ScalarLen, CredentialRequestLen<CS>>:
ArrayLength<u8> + Add<Ke1StateLen<CS>>,
ClientLoginLen<CS>: ArrayLength<u8>,
// MaskedResponse: (Nonce + Hash) + KePk
NonceLen: Add<OutputSize<OprfHash<CS>>>,
Sum<NonceLen, OutputSize<OprfHash<CS>>>: ArrayLength<u8> + Add<<CS::KeGroup as KeGroup>::PkLen>,
MaskedResponseLen<CS>: ArrayLength<u8>,
// CredentialResponseWithoutKeLen: (KgPk + Nonce) + MaskedResponse
<OprfGroup<CS> as Group>::ElemLen: Add<NonceLen>,
Sum<<OprfGroup<CS> as Group>::ElemLen, NonceLen>: ArrayLength<u8> + Add<MaskedResponseLen<CS>>,
CredentialResponseWithoutKeLen<CS>: ArrayLength<u8>,
// Ke2Message: (Nonce + KePk) + Hash
NonceLen: Add<<CS::KeGroup as KeGroup>::PkLen>,
Sum<NonceLen, <CS::KeGroup as KeGroup>::PkLen>: ArrayLength<u8> + Add<OutputSize<OprfHash<CS>>>,
Ke2MessageLen<CS>: ArrayLength<u8>,
// CredentialResponse: CredentialResponseWithoutKeLen + Ke2Message
CredentialResponseWithoutKeLen<CS>: Add<Ke2MessageLen<CS>>,
CredentialResponseLen<CS>: ArrayLength<u8>,
{
use rand::RngCore;
use crate::keypair::KeyPair;
let mut rng = OsRng;
// Inputs
let server_s_kp = KeyPair::<CS::KeGroup>::generate_random(&mut rng);
let server_e_kp = KeyPair::<CS::KeGroup>::generate_random(&mut rng);
let client_s_kp = KeyPair::<CS::KeGroup>::generate_random(&mut rng);
let client_e_kp = KeyPair::<CS::KeGroup>::generate_random(&mut rng);
let fake_kp = KeyPair::<CS::KeGroup>::generate_random(&mut rng);
let credential_identifier = b"credIdentifier";
let id_u = b"idU";
let id_s = b"idS";
let password = b"password";
let context = b"context";
let mut oprf_seed = Output::<OprfHash<CS>>::default();
rng.fill_bytes(&mut oprf_seed);
let mut masking_nonce = [0u8; 64];
rng.fill_bytes(&mut masking_nonce);
let mut envelope_nonce = [0u8; 32];
rng.fill_bytes(&mut envelope_nonce);
let mut client_nonce = [0u8; NonceLen::USIZE];
rng.fill_bytes(&mut client_nonce);
let mut server_nonce = [0u8; NonceLen::USIZE];
rng.fill_bytes(&mut server_nonce);
let fake_sk: Vec<u8> = fake_kp.private().serialize().to_vec();
let server_setup = ServerSetup::<CS>::deserialize(
&[
oprf_seed.as_ref(),
&server_s_kp.private().serialize(),
&fake_sk,
]
.concat(),
)
.unwrap();
let blinding_factor = <OprfGroup<CS> as Group>::random_scalar(&mut rng);
let blinding_factor_bytes = OprfGroup::<CS>::serialize_scalar(blinding_factor);
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 = OprfGroup::<CS>::serialize_scalar(
client_registration_start_result
.state
.oprf_client
.get_blind(),
);
assert_eq!(
hex::encode(&blinding_factor_bytes),
hex::encode(&blinding_factor_bytes_returned)
);
let registration_request_bytes = client_registration_start_result.message.serialize();
let client_registration_state = client_registration_start_result.state.serialize();
let server_registration_start_result = ServerRegistration::<CS>::start(
&server_setup,
client_registration_start_result.message,
credential_identifier,
)
.unwrap();
let registration_response_bytes = server_registration_start_result.message.serialize();
let mut client_s_sk_and_nonce: Vec<u8> = Vec::new();
client_s_sk_and_nonce.extend_from_slice(&client_s_kp.private().serialize());
client_s_sk_and_nonce.extend_from_slice(&envelope_nonce);
let mut finish_registration_rng = CycleRng::new(client_s_sk_and_nonce);
let client_registration_finish_result = client_registration_start_result
.state
.finish(
&mut finish_registration_rng,
password,
server_registration_start_result.message,
ClientRegistrationFinishParameters::new(
Identifiers {
client: Some(id_u),
server: Some(id_s),
},
None,
),
)
.unwrap();
let registration_upload_bytes = client_registration_finish_result.message.serialize();
let password_file = ServerRegistration::finish(client_registration_finish_result.message);
let password_file_bytes = password_file.serialize();
let mut client_login_start: Vec<u8> = Vec::new();
client_login_start.extend_from_slice(&blinding_factor_bytes);
client_login_start.extend_from_slice(&client_e_kp.private().serialize());
client_login_start.extend_from_slice(&client_nonce);
let mut client_login_start_rng = CycleRng::new(client_login_start);
let client_login_start_result =
ClientLogin::<CS>::start(&mut client_login_start_rng, password).unwrap();
let credential_request_bytes = client_login_start_result.message.serialize();
let client_login_state = client_login_start_result.state.serialize().to_vec();
let mut server_e_sk_and_nonce_rng = CycleRng::new(
[
masking_nonce.to_vec(),
server_e_kp.private().serialize().to_vec(),
server_nonce.to_vec(),
]
.concat(),
);
let server_login_start_result = ServerLogin::<CS>::start(
&mut server_e_sk_and_nonce_rng,
&server_setup,
Some(password_file),
client_login_start_result.message,
credential_identifier,
ServerLoginStartParameters {
context: Some(context),
identifiers: Identifiers {
client: Some(id_u),
server: Some(id_s),
},
},
)
.unwrap();
let credential_response_bytes = server_login_start_result.message.serialize();
let server_login_state = server_login_start_result.state.serialize();
let client_login_finish_result = client_login_start_result
.state
.finish(
password,
server_login_start_result.message,
ClientLoginFinishParameters::new(
Some(context),
Identifiers {
client: Some(id_u),
server: Some(id_s),
},
None,
),
)
.unwrap();
let credential_finalization_bytes = client_login_finish_result.message.serialize();
Ok(TestVectorParameters {
client_s_pk: client_s_kp.public().serialize().to_vec(),
client_s_sk: client_s_kp.private().serialize().to_vec(),
client_e_pk: client_e_kp.public().serialize().to_vec(),
client_e_sk: client_e_kp.private().serialize().to_vec(),
server_s_pk: server_s_kp.public().serialize().to_vec(),
server_s_sk: server_s_kp.private().serialize().to_vec(),
server_e_pk: server_e_kp.public().serialize().to_vec(),
server_e_sk: server_e_kp.private().serialize().to_vec(),
fake_sk,
credential_identifier: credential_identifier.to_vec(),
id_u: id_u.to_vec(),
id_s: id_s.to_vec(),
password: password.to_vec(),
blinding_factor: blinding_factor_bytes.to_vec(),
oprf_seed: oprf_seed.to_vec(),
masking_nonce: masking_nonce.to_vec(),
envelope_nonce: envelope_nonce.to_vec(),
client_nonce: client_nonce.to_vec(),
server_nonce: server_nonce.to_vec(),
context: context.to_vec(),
registration_request: registration_request_bytes.to_vec(),
registration_response: registration_response_bytes.to_vec(),
registration_upload: registration_upload_bytes.to_vec(),
credential_request: credential_request_bytes.to_vec(),
credential_response: credential_response_bytes.to_vec(),
credential_finalization: credential_finalization_bytes.to_vec(),
password_file: password_file_bytes.to_vec(),
client_registration_state: client_registration_state.to_vec(),
client_login_state,
server_login_state: server_login_state.to_vec(),
session_key: client_login_finish_result.session_key.to_vec(),
export_key: client_registration_finish_result.export_key.to_vec(),
})
}
#[test]
fn generate_test_vectors() -> Result<(), ProtocolError> {
#[cfg(feature = "ristretto255")]
{
let parameters = generate_parameters::<Ristretto255>()?;
println!("Ristretto255: {}", stringify_test_vectors(&parameters));
let parameters = generate_parameters::<Ristretto255P256>()?;
println!(
"Ristretto255 P-256: {}",
stringify_test_vectors(&parameters)
);
let parameters = generate_parameters::<Ristretto255P384>()?;
println!(
"Ristretto255 P-384: {}",
stringify_test_vectors(&parameters)
);
}
let parameters = generate_parameters::<P256>()?;
println!("P-256: {}", stringify_test_vectors(&parameters));
let parameters = generate_parameters::<P256P384>()?;
println!("P-256 P-384: {}", stringify_test_vectors(&parameters));
#[cfg(feature = "ristretto255")]
{
let parameters = generate_parameters::<P256Ristretto255>()?;
println!(
"P-256 Ristretto255: {}",
stringify_test_vectors(&parameters)
);
}
let parameters = generate_parameters::<P384>()?;
println!("P-384: {}", stringify_test_vectors(&parameters));
let parameters = generate_parameters::<P384P256>()?;
println!("P-384 P-256: {}", stringify_test_vectors(&parameters));
#[cfg(feature = "ristretto255")]
{
let parameters = generate_parameters::<P384Ristretto255>()?;
println!(
"P-384 Ristretto255: {}",
stringify_test_vectors(&parameters)
);
}
#[cfg(feature = "curve25519")]
{
let parameters = generate_parameters::<Curve25519P256>()?;
println!("Curve25519 P-256: {}", stringify_test_vectors(&parameters));
let parameters = generate_parameters::<Curve25519P384>()?;
println!("Curve25519 P-384: {}", stringify_test_vectors(&parameters));
}
#[cfg(all(feature = "curve25519", feature = "ristretto255"))]
{
let parameters = generate_parameters::<Curve25519Ristretto255>()?;
println!(
"Curve25519 Ristretto255: {}",
stringify_test_vectors(&parameters)
);
}
Ok(())
}
#[test]
fn test_registration_request() -> Result<(), ProtocolError> {
fn inner<CS: CipherSuite>(test_vector: &str) -> Result<(), ProtocolError>
where
<OprfHash<CS> as OutputSizeUser>::OutputSize:
IsLess<U256> + IsLessOrEqual<<OprfHash<CS> as BlockSizeUser>::BlockSize>,
OprfHash<CS>: Hash,
<OprfHash<CS> as CoreProxy>::Core: ProxyHash,
<<OprfHash<CS> as CoreProxy>::Core as BlockSizeUser>::BlockSize: IsLess<U256>,
Le<<<OprfHash<CS> as CoreProxy>::Core as BlockSizeUser>::BlockSize, U256>: NonZero,
// ClientRegistration: KgSk + KgPk
<OprfGroup<CS> as Group>::ScalarLen: Add<<OprfGroup<CS> as Group>::ElemLen>,
ClientRegistrationLen<CS>: ArrayLength<u8>,
{
let parameters = populate_test_vectors(&serde_json::from_str(test_vector).unwrap());
let mut rng = CycleRng::new(parameters.blinding_factor.to_vec());
let client_registration_start_result =
ClientRegistration::<CS>::start(&mut rng, &parameters.password)?;
assert_eq!(
hex::encode(&parameters.registration_request),
hex::encode(client_registration_start_result.message.serialize())
);
assert_eq!(
hex::encode(&parameters.client_registration_state),
hex::encode(client_registration_start_result.state.serialize())
);
Ok(())
}
#[cfg(feature = "ristretto255")]
inner::<Ristretto255>(TEST_VECTOR_RISTRETTO255)?;
#[cfg(feature = "ristretto255")]
inner::<Ristretto255P256>(TEST_VECTOR_RISTRETTO255_P256)?;
#[cfg(feature = "ristretto255")]
inner::<Ristretto255P384>(TEST_VECTOR_RISTRETTO255_P384)?;
inner::<P256>(TEST_VECTOR_P256)?;
inner::<P256P384>(TEST_VECTOR_P256_P384)?;
#[cfg(feature = "ristretto255")]
inner::<P256Ristretto255>(TEST_VECTOR_P256_RISTRETTO255)?;
inner::<P384>(TEST_VECTOR_P384)?;
inner::<P384P256>(TEST_VECTOR_P384_P256)?;
#[cfg(feature = "ristretto255")]
inner::<P384Ristretto255>(TEST_VECTOR_P384_RISTRETTO255)?;
#[cfg(feature = "curve25519")]
inner::<Curve25519P256>(TEST_VECTOR_CURVE25519_P256)?;
#[cfg(feature = "curve25519")]
inner::<Curve25519P384>(TEST_VECTOR_CURVE25519_P384)?;
#[cfg(all(feature = "curve25519", feature = "ristretto255"))]
inner::<Curve25519Ristretto255>(TEST_VECTOR_CURVE25519_RISTRETTO255)?;
Ok(())
}
#[cfg(feature = "serde")]
#[test]
fn test_serialization() -> Result<(), ProtocolError> {
fn inner<CS: CipherSuite>(test_vector: &str) -> Result<(), ProtocolError>
where
<OprfHash<CS> as OutputSizeUser>::OutputSize:
IsLess<U256> + IsLessOrEqual<<OprfHash<CS> as BlockSizeUser>::BlockSize>,
OprfHash<CS>: Hash,
<OprfHash<CS> as CoreProxy>::Core: ProxyHash,
<<OprfHash<CS> as CoreProxy>::Core as BlockSizeUser>::BlockSize: IsLess<U256>,
Le<<<OprfHash<CS> as CoreProxy>::Core as BlockSizeUser>::BlockSize, U256>: NonZero,
{
let parameters = populate_test_vectors(&serde_json::from_str(test_vector).unwrap());
let mut rng = CycleRng::new(parameters.blinding_factor.to_vec());
let client_registration_start_result =
ClientRegistration::<CS>::start(&mut rng, &parameters.password)?;
// Test the bincode serialization (binary).
let registration_request =
bincode::serialize(&client_registration_start_result.message).unwrap();
assert_eq!(
registration_request.len(),
RegistrationRequestLen::<CS>::USIZE
);
let registration_request: RegistrationRequest<CS> =
bincode::deserialize(&registration_request).unwrap();
assert_eq!(
hex::encode(client_registration_start_result.message.serialize()),
hex::encode(registration_request.serialize()),
);
Ok(())
}
#[cfg(feature = "ristretto255")]
inner::<Ristretto255>(TEST_VECTOR_RISTRETTO255)?;
#[cfg(feature = "ristretto255")]
inner::<Ristretto255P256>(TEST_VECTOR_RISTRETTO255_P256)?;
#[cfg(feature = "ristretto255")]
inner::<Ristretto255P384>(TEST_VECTOR_RISTRETTO255_P384)?;
inner::<P256>(TEST_VECTOR_P256)?;
inner::<P256P384>(TEST_VECTOR_P256_P384)?;
#[cfg(feature = "ristretto255")]
inner::<P256Ristretto255>(TEST_VECTOR_P256_RISTRETTO255)?;
inner::<P384>(TEST_VECTOR_P384)?;
inner::<P384P256>(TEST_VECTOR_P384_P256)?;
#[cfg(feature = "ristretto255")]
inner::<P384Ristretto255>(TEST_VECTOR_P384_RISTRETTO255)?;
#[cfg(feature = "curve25519")]
inner::<Curve25519P256>(TEST_VECTOR_CURVE25519_P256)?;
#[cfg(feature = "curve25519")]
inner::<Curve25519P384>(TEST_VECTOR_CURVE25519_P384)?;
#[cfg(all(feature = "curve25519", feature = "ristretto255"))]
inner::<Curve25519Ristretto255>(TEST_VECTOR_CURVE25519_RISTRETTO255)?;
Ok(())
}
#[test]
fn test_registration_response() -> Result<(), ProtocolError> {
fn inner<CS: CipherSuite>(test_vector: &str) -> Result<(), ProtocolError>
where
<OprfHash<CS> as OutputSizeUser>::OutputSize:
IsLess<U256> + IsLessOrEqual<<OprfHash<CS> as BlockSizeUser>::BlockSize>,
OprfHash<CS>: Hash,
<OprfHash<CS> as CoreProxy>::Core: ProxyHash,
<<OprfHash<CS> as CoreProxy>::Core as BlockSizeUser>::BlockSize: IsLess<U256>,
Le<<<OprfHash<CS> as CoreProxy>::Core as BlockSizeUser>::BlockSize, U256>: NonZero,
// RegistrationResponse: KgPk + KePk
<OprfGroup<CS> as Group>::ElemLen: Add<<CS::KeGroup as KeGroup>::PkLen>,
RegistrationResponseLen<CS>: ArrayLength<u8>,
{
let parameters = populate_test_vectors(
&serde_json::from_str(test_vector).map_err(|_| ProtocolError::SerializationError)?,
);
let server_setup = ServerSetup::<CS>::deserialize(
&[
parameters.oprf_seed,
parameters.server_s_sk,
parameters.fake_sk,
]
.concat(),
)?;
let server_registration_start_result = ServerRegistration::<CS>::start(
&server_setup,
RegistrationRequest::deserialize(&parameters.registration_request)?,
&parameters.credential_identifier,
)?;
assert_eq!(
hex::encode(parameters.registration_response),
hex::encode(server_registration_start_result.message.serialize())
);
Ok(())
}
#[cfg(feature = "ristretto255")]
inner::<Ristretto255>(TEST_VECTOR_RISTRETTO255)?;
#[cfg(feature = "ristretto255")]
inner::<Ristretto255P256>(TEST_VECTOR_RISTRETTO255_P256)?;
#[cfg(feature = "ristretto255")]
inner::<Ristretto255P384>(TEST_VECTOR_RISTRETTO255_P384)?;
inner::<P256>(TEST_VECTOR_P256)?;
inner::<P256P384>(TEST_VECTOR_P256_P384)?;
#[cfg(feature = "ristretto255")]
inner::<P256Ristretto255>(TEST_VECTOR_P256_RISTRETTO255)?;
inner::<P384>(TEST_VECTOR_P384)?;
inner::<P384P256>(TEST_VECTOR_P384_P256)?;
#[cfg(feature = "ristretto255")]
inner::<P384Ristretto255>(TEST_VECTOR_P384_RISTRETTO255)?;
#[cfg(feature = "curve25519")]
inner::<Curve25519P256>(TEST_VECTOR_CURVE25519_P256)?;
#[cfg(feature = "curve25519")]
inner::<Curve25519P384>(TEST_VECTOR_CURVE25519_P384)?;
#[cfg(all(feature = "curve25519", feature = "ristretto255"))]
inner::<Curve25519Ristretto255>(TEST_VECTOR_CURVE25519_RISTRETTO255)?;
Ok(())
}
#[test]
fn test_registration_upload() -> Result<(), ProtocolError> {
fn inner<CS: CipherSuite>(test_vector: &str) -> Result<(), ProtocolError>
where
<OprfHash<CS> as OutputSizeUser>::OutputSize:
IsLess<U256> + IsLessOrEqual<<OprfHash<CS> as BlockSizeUser>::BlockSize>,
OprfHash<CS>: Hash,
<OprfHash<CS> as CoreProxy>::Core: ProxyHash,
<<OprfHash<CS> as CoreProxy>::Core as BlockSizeUser>::BlockSize: IsLess<U256>,
Le<<<OprfHash<CS> as CoreProxy>::Core as BlockSizeUser>::BlockSize, U256>: NonZero,
// Envelope: Nonce + Hash
NonceLen: Add<OutputSize<OprfHash<CS>>>,
EnvelopeLen<CS>: ArrayLength<u8>,
// RegistrationUpload: (KePk + Hash) + Envelope
<CS::KeGroup as KeGroup>::PkLen: Add<OutputSize<OprfHash<CS>>>,
Sum<<CS::KeGroup as KeGroup>::PkLen, OutputSize<OprfHash<CS>>>:
ArrayLength<u8> + Add<EnvelopeLen<CS>>,
RegistrationUploadLen<CS>: ArrayLength<u8>,
{
let parameters = populate_test_vectors(
&serde_json::from_str(test_vector).map_err(|_| ProtocolError::SerializationError)?,
);
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::<CS>::deserialize(&parameters.client_registration_state)?
.finish(
&mut finish_registration_rng,
&parameters.password,
RegistrationResponse::deserialize(&parameters.registration_response)?,
ClientRegistrationFinishParameters::new(
Identifiers {
client: Some(&parameters.id_u),
server: Some(&parameters.id_s),
},
None,
),
)?;
assert_eq!(
hex::encode(parameters.registration_upload),
hex::encode(result.message.serialize())
);
assert_eq!(
hex::encode(parameters.export_key),
hex::encode(result.export_key)
);
Ok(())
}
#[cfg(feature = "ristretto255")]
inner::<Ristretto255>(TEST_VECTOR_RISTRETTO255)?;
#[cfg(feature = "ristretto255")]
inner::<Ristretto255P256>(TEST_VECTOR_RISTRETTO255_P256)?;
#[cfg(feature = "ristretto255")]
inner::<Ristretto255P384>(TEST_VECTOR_RISTRETTO255_P384)?;
inner::<P256>(TEST_VECTOR_P256)?;
inner::<P256P384>(TEST_VECTOR_P256_P384)?;
#[cfg(feature = "ristretto255")]
inner::<P256Ristretto255>(TEST_VECTOR_P256_RISTRETTO255)?;
inner::<P384>(TEST_VECTOR_P384)?;
inner::<P384P256>(TEST_VECTOR_P384_P256)?;
#[cfg(feature = "ristretto255")]
inner::<P384Ristretto255>(TEST_VECTOR_P384_RISTRETTO255)?;
#[cfg(feature = "curve25519")]
inner::<Curve25519P256>(TEST_VECTOR_CURVE25519_P256)?;
#[cfg(feature = "curve25519")]
inner::<Curve25519P384>(TEST_VECTOR_CURVE25519_P384)?;
#[cfg(all(feature = "curve25519", feature = "ristretto255"))]
inner::<Curve25519Ristretto255>(TEST_VECTOR_CURVE25519_RISTRETTO255)?;
Ok(())
}
#[test]
fn test_password_file() -> Result<(), ProtocolError> {
fn inner<CS: CipherSuite>(test_vector: &str) -> Result<(), ProtocolError>
where
<OprfHash<CS> as OutputSizeUser>::OutputSize:
IsLess<U256> + IsLessOrEqual<<OprfHash<CS> as BlockSizeUser>::BlockSize>,
OprfHash<CS>: Hash,
<OprfHash<CS> as CoreProxy>::Core: ProxyHash,
<<OprfHash<CS> as CoreProxy>::Core as BlockSizeUser>::BlockSize: IsLess<U256>,
Le<<<OprfHash<CS> as CoreProxy>::Core as BlockSizeUser>::BlockSize, U256>: NonZero,
// Envelope: Nonce + Hash
NonceLen: Add<OutputSize<OprfHash<CS>>>,
EnvelopeLen<CS>: ArrayLength<u8>,
// RegistrationUpload: (KePk + Hash) + Envelope
<CS::KeGroup as KeGroup>::PkLen: Add<OutputSize<OprfHash<CS>>>,
Sum<<CS::KeGroup as KeGroup>::PkLen, OutputSize<OprfHash<CS>>>:
ArrayLength<u8> + Add<EnvelopeLen<CS>>,
RegistrationUploadLen<CS>: ArrayLength<u8>,
// ServerRegistration = RegistrationUpload
{
let parameters = populate_test_vectors(&serde_json::from_str(test_vector).unwrap());
let password_file = ServerRegistration::finish(RegistrationUpload::<CS>::deserialize(
&parameters.registration_upload,
)?);
assert_eq!(
hex::encode(parameters.password_file),
hex::encode(password_file.serialize())
);
Ok(())
}
#[cfg(feature = "ristretto255")]
inner::<Ristretto255>(TEST_VECTOR_RISTRETTO255)?;
#[cfg(feature = "ristretto255")]
inner::<Ristretto255P256>(TEST_VECTOR_RISTRETTO255_P256)?;
#[cfg(feature = "ristretto255")]
inner::<Ristretto255P384>(TEST_VECTOR_RISTRETTO255_P384)?;
inner::<P256>(TEST_VECTOR_P256)?;
inner::<P256P384>(TEST_VECTOR_P256_P384)?;
#[cfg(feature = "ristretto255")]
inner::<P256Ristretto255>(TEST_VECTOR_P256_RISTRETTO255)?;
inner::<P384>(TEST_VECTOR_P384)?;
inner::<P384P256>(TEST_VECTOR_P384_P256)?;
#[cfg(feature = "ristretto255")]
inner::<P384Ristretto255>(TEST_VECTOR_P384_RISTRETTO255)?;
#[cfg(feature = "curve25519")]
inner::<Curve25519P256>(TEST_VECTOR_CURVE25519_P256)?;
#[cfg(feature = "curve25519")]
inner::<Curve25519P384>(TEST_VECTOR_CURVE25519_P384)?;
#[cfg(all(feature = "curve25519", feature = "ristretto255"))]
inner::<Curve25519Ristretto255>(TEST_VECTOR_CURVE25519_RISTRETTO255)?;
Ok(())
}
#[test]
fn test_credential_request() -> Result<(), ProtocolError> {
fn inner<CS: CipherSuite>(test_vector: &str) -> Result<(), ProtocolError>
where
<OprfHash<CS> as OutputSizeUser>::OutputSize:
IsLess<U256> + IsLessOrEqual<<OprfHash<CS> as BlockSizeUser>::BlockSize>,
OprfHash<CS>: Hash,
<OprfHash<CS> as CoreProxy>::Core: ProxyHash,
<<OprfHash<CS> as CoreProxy>::Core as BlockSizeUser>::BlockSize: IsLess<U256>,
Le<<<OprfHash<CS> as CoreProxy>::Core as BlockSizeUser>::BlockSize, U256>: NonZero,
// CredentialRequest: KgPk + Ke1Message
<OprfGroup<CS> as Group>::ElemLen: Add<Ke1MessageLen<CS>>,
CredentialRequestLen<CS>: ArrayLength<u8>,
// ClientLogin: KgSk + CredentialRequest + Ke1State
<OprfGroup<CS> as Group>::ScalarLen: Add<CredentialRequestLen<CS>>,
Sum<<OprfGroup<CS> as Group>::ScalarLen, CredentialRequestLen<CS>>:
ArrayLength<u8> + Add<Ke1StateLen<CS>>,
ClientLoginLen<CS>: ArrayLength<u8>,
{
let parameters = populate_test_vectors(&serde_json::from_str(test_vector).unwrap());
let client_login_start_rng = [
parameters.blinding_factor,
parameters.client_e_sk,
parameters.client_nonce,
]
.concat();
let mut client_login_start_rng = CycleRng::new(client_login_start_rng);
let client_login_start_result =
ClientLogin::<CS>::start(&mut client_login_start_rng, &parameters.password)?;
assert_eq!(
hex::encode(&parameters.credential_request),
hex::encode(client_login_start_result.message.serialize())
);
assert_eq!(
hex::encode(&parameters.client_login_state),
hex::encode(client_login_start_result.state.serialize())
);
Ok(())
}
#[cfg(feature = "ristretto255")]
inner::<Ristretto255>(TEST_VECTOR_RISTRETTO255)?;
#[cfg(feature = "ristretto255")]
inner::<Ristretto255P256>(TEST_VECTOR_RISTRETTO255_P256)?;
#[cfg(feature = "ristretto255")]
inner::<Ristretto255P384>(TEST_VECTOR_RISTRETTO255_P384)?;
inner::<P256>(TEST_VECTOR_P256)?;
inner::<P256P384>(TEST_VECTOR_P256_P384)?;
#[cfg(feature = "ristretto255")]
inner::<P256Ristretto255>(TEST_VECTOR_P256_RISTRETTO255)?;
inner::<P384>(TEST_VECTOR_P384)?;
inner::<P384P256>(TEST_VECTOR_P384_P256)?;
#[cfg(feature = "ristretto255")]
inner::<P384Ristretto255>(TEST_VECTOR_P384_RISTRETTO255)?;
#[cfg(feature = "curve25519")]
inner::<Curve25519P256>(TEST_VECTOR_CURVE25519_P256)?;
#[cfg(feature = "curve25519")]
inner::<Curve25519P384>(TEST_VECTOR_CURVE25519_P384)?;
#[cfg(all(feature = "curve25519", feature = "ristretto255"))]
inner::<Curve25519Ristretto255>(TEST_VECTOR_CURVE25519_RISTRETTO255)?;
Ok(())
}
#[test]
fn test_credential_response() -> Result<(), ProtocolError> {
fn inner<CS: CipherSuite>(test_vector: &str) -> Result<(), ProtocolError>
where
<OprfHash<CS> as OutputSizeUser>::OutputSize:
IsLess<U256> + IsLessOrEqual<<OprfHash<CS> as BlockSizeUser>::BlockSize>,
OprfHash<CS>: Hash,
<OprfHash<CS> as CoreProxy>::Core: ProxyHash,
<<OprfHash<CS> as CoreProxy>::Core as BlockSizeUser>::BlockSize: IsLess<U256>,
Le<<<OprfHash<CS> as CoreProxy>::Core as BlockSizeUser>::BlockSize, U256>: NonZero,
// MaskedResponse: (Nonce + Hash) + KePk
NonceLen: Add<OutputSize<OprfHash<CS>>>,
Sum<NonceLen, OutputSize<OprfHash<CS>>>:
ArrayLength<u8> + Add<<CS::KeGroup as KeGroup>::PkLen>,
MaskedResponseLen<CS>: ArrayLength<u8>,
// CredentialResponseWithoutKeLen: (KgPk + Nonce) + MaskedResponse
<OprfGroup<CS> as Group>::ElemLen: Add<NonceLen>,
Sum<<OprfGroup<CS> as Group>::ElemLen, NonceLen>:
ArrayLength<u8> + Add<MaskedResponseLen<CS>>,
CredentialResponseWithoutKeLen<CS>: ArrayLength<u8>,
// CredentialResponse: CredentialResponseWithoutKeLen + Ke2Message
CredentialResponseWithoutKeLen<CS>: Add<Ke2MessageLen<CS>>,
CredentialResponseLen<CS>: ArrayLength<u8>,
{
let parameters = populate_test_vectors(&serde_json::from_str(test_vector).unwrap());
let server_setup = ServerSetup::<CS>::deserialize(
&[
parameters.oprf_seed,
parameters.server_s_sk,
parameters.fake_sk,
]
.concat(),
)?;
let mut server_e_sk_and_nonce_rng = CycleRng::new(
[
parameters.masking_nonce,
parameters.server_e_sk,
parameters.server_nonce,
]
.concat(),
);
let server_login_start_result = ServerLogin::<CS>::start(
&mut server_e_sk_and_nonce_rng,
&server_setup,
Some(ServerRegistration::deserialize(&parameters.password_file)?),
CredentialRequest::<CS>::deserialize(&parameters.credential_request)?,
&parameters.credential_identifier,
ServerLoginStartParameters {
context: Some(&parameters.context),
identifiers: Identifiers {
client: Some(&parameters.id_u),
server: Some(&parameters.id_s),
},
},
)?;
assert_eq!(
hex::encode(&parameters.credential_response),
hex::encode(server_login_start_result.message.serialize())
);
assert_eq!(
hex::encode(&parameters.server_login_state),
hex::encode(server_login_start_result.state.serialize())
);
Ok(())
}
#[cfg(feature = "ristretto255")]
inner::<Ristretto255>(TEST_VECTOR_RISTRETTO255)?;
#[cfg(feature = "ristretto255")]
inner::<Ristretto255P256>(TEST_VECTOR_RISTRETTO255_P256)?;
#[cfg(feature = "ristretto255")]
inner::<Ristretto255P384>(TEST_VECTOR_RISTRETTO255_P384)?;
inner::<P256>(TEST_VECTOR_P256)?;
inner::<P256P384>(TEST_VECTOR_P256_P384)?;
#[cfg(feature = "ristretto255")]
inner::<P256Ristretto255>(TEST_VECTOR_P256_RISTRETTO255)?;
inner::<P384>(TEST_VECTOR_P384)?;
inner::<P384P256>(TEST_VECTOR_P384_P256)?;
#[cfg(feature = "ristretto255")]
inner::<P384Ristretto255>(TEST_VECTOR_P384_RISTRETTO255)?;
#[cfg(feature = "curve25519")]
inner::<Curve25519P256>(TEST_VECTOR_CURVE25519_P256)?;
#[cfg(feature = "curve25519")]
inner::<Curve25519P384>(TEST_VECTOR_CURVE25519_P384)?;
#[cfg(all(feature = "curve25519", feature = "ristretto255"))]
inner::<Curve25519Ristretto255>(TEST_VECTOR_CURVE25519_RISTRETTO255)?;
Ok(())
}
#[test]
fn test_credential_finalization() -> Result<(), ProtocolError> {
fn inner<CS: CipherSuite>(test_vector: &str) -> Result<(), ProtocolError>
where
<OprfHash<CS> as OutputSizeUser>::OutputSize:
IsLess<U256> + IsLessOrEqual<<OprfHash<CS> as BlockSizeUser>::BlockSize>,
OprfHash<CS>: Hash,
<OprfHash<CS> as CoreProxy>::Core: ProxyHash,
<<OprfHash<CS> as CoreProxy>::Core as BlockSizeUser>::BlockSize: IsLess<U256>,
Le<<<OprfHash<CS> as CoreProxy>::Core as BlockSizeUser>::BlockSize, U256>: NonZero,
// MaskedResponse: (Nonce + Hash) + KePk
NonceLen: Add<OutputSize<OprfHash<CS>>>,
Sum<NonceLen, OutputSize<OprfHash<CS>>>:
ArrayLength<u8> + Add<<CS::KeGroup as KeGroup>::PkLen>,
MaskedResponseLen<CS>: ArrayLength<u8>,
{
let parameters = populate_test_vectors(&serde_json::from_str(test_vector).unwrap());
let client_login_finish_result =
ClientLogin::<CS>::deserialize(&parameters.client_login_state)?.finish(
&parameters.password,
CredentialResponse::<CS>::deserialize(&parameters.credential_response)?,
ClientLoginFinishParameters::new(
Some(&parameters.context),
Identifiers {
client: Some(&parameters.id_u),
server: Some(&parameters.id_s),
},
None,
),
)?;
assert_eq!(
hex::encode(&parameters.server_s_pk),
hex::encode(&client_login_finish_result.server_s_pk.serialize())
);
assert_eq!(
hex::encode(&parameters.session_key),
hex::encode(&client_login_finish_result.session_key)
);
assert_eq!(
hex::encode(&parameters.credential_finalization),
hex::encode(client_login_finish_result.message.serialize())
);
assert_eq!(
hex::encode(&parameters.export_key),
hex::encode(client_login_finish_result.export_key)
);
Ok(())
}
#[cfg(feature = "ristretto255")]
inner::<Ristretto255>(TEST_VECTOR_RISTRETTO255)?;
#[cfg(feature = "ristretto255")]
inner::<Ristretto255P256>(TEST_VECTOR_RISTRETTO255_P256)?;
#[cfg(feature = "ristretto255")]
inner::<Ristretto255P384>(TEST_VECTOR_RISTRETTO255_P384)?;
inner::<P256>(TEST_VECTOR_P256)?;
inner::<P256P384>(TEST_VECTOR_P256_P384)?;
#[cfg(feature = "ristretto255")]
inner::<P256Ristretto255>(TEST_VECTOR_P256_RISTRETTO255)?;
inner::<P384>(TEST_VECTOR_P384)?;
inner::<P384P256>(TEST_VECTOR_P384_P256)?;
#[cfg(feature = "ristretto255")]
inner::<P384Ristretto255>(TEST_VECTOR_P384_RISTRETTO255)?;
#[cfg(feature = "curve25519")]
inner::<Curve25519P256>(TEST_VECTOR_CURVE25519_P256)?;
#[cfg(feature = "curve25519")]
inner::<Curve25519P384>(TEST_VECTOR_CURVE25519_P384)?;
#[cfg(all(feature = "curve25519", feature = "ristretto255"))]
inner::<Curve25519Ristretto255>(TEST_VECTOR_CURVE25519_RISTRETTO255)?;
Ok(())
}
#[test]
fn test_server_login_finish() -> Result<(), ProtocolError> {
fn inner<CS: CipherSuite>(test_vector: &str) -> Result<(), ProtocolError>
where
<OprfHash<CS> as OutputSizeUser>::OutputSize:
IsLess<U256> + IsLessOrEqual<<OprfHash<CS> as BlockSizeUser>::BlockSize>,
OprfHash<CS>: Hash,
<OprfHash<CS> as CoreProxy>::Core: ProxyHash,
<<OprfHash<CS> as CoreProxy>::Core as BlockSizeUser>::BlockSize: IsLess<U256>,
Le<<<OprfHash<CS> as CoreProxy>::Core as BlockSizeUser>::BlockSize, U256>: NonZero,
{
let parameters = populate_test_vectors(&serde_json::from_str(test_vector).unwrap());
let server_login_result = ServerLogin::<CS>::deserialize(&parameters.server_login_state)?
.finish(CredentialFinalization::deserialize(
&parameters.credential_finalization,
)?)?;
assert_eq!(
hex::encode(parameters.session_key),
hex::encode(&server_login_result.session_key)
);
Ok(())
}
#[cfg(feature = "ristretto255")]
inner::<Ristretto255>(TEST_VECTOR_RISTRETTO255)?;
#[cfg(feature = "ristretto255")]
inner::<Ristretto255P256>(TEST_VECTOR_RISTRETTO255_P256)?;
#[cfg(feature = "ristretto255")]
inner::<Ristretto255P384>(TEST_VECTOR_RISTRETTO255_P384)?;
inner::<P256>(TEST_VECTOR_P256)?;
inner::<P256P384>(TEST_VECTOR_P256_P384)?;
#[cfg(feature = "ristretto255")]
inner::<P256Ristretto255>(TEST_VECTOR_P256_RISTRETTO255)?;
inner::<P384>(TEST_VECTOR_P384)?;
inner::<P384P256>(TEST_VECTOR_P384_P256)?;
#[cfg(feature = "ristretto255")]
inner::<P384Ristretto255>(TEST_VECTOR_P384_RISTRETTO255)?;
#[cfg(feature = "curve25519")]
inner::<Curve25519P256>(TEST_VECTOR_CURVE25519_P256)?;
#[cfg(feature = "curve25519")]
inner::<Curve25519P384>(TEST_VECTOR_CURVE25519_P384)?;
#[cfg(all(feature = "curve25519", feature = "ristretto255"))]
inner::<Curve25519Ristretto255>(TEST_VECTOR_CURVE25519_RISTRETTO255)?;
Ok(())
}
fn test_complete_flow<CS: CipherSuite>(
registration_password: &[u8],
login_password: &[u8],
) -> Result<(), ProtocolError>
where
<OprfHash<CS> as OutputSizeUser>::OutputSize:
IsLess<U256> + IsLessOrEqual<<OprfHash<CS> as BlockSizeUser>::BlockSize>,
OprfHash<CS>: Hash,
<OprfHash<CS> as CoreProxy>::Core: ProxyHash,
<<OprfHash<CS> as CoreProxy>::Core as BlockSizeUser>::BlockSize: IsLess<U256>,
Le<<<OprfHash<CS> as CoreProxy>::Core as BlockSizeUser>::BlockSize, U256>: NonZero,
// MaskedResponse: (Nonce + Hash) + KePk
NonceLen: Add<OutputSize<OprfHash<CS>>>,
Sum<NonceLen, OutputSize<OprfHash<CS>>>: ArrayLength<u8> + Add<<CS::KeGroup as KeGroup>::PkLen>,
MaskedResponseLen<CS>: ArrayLength<u8>,
{
let credential_identifier = b"credentialIdentifier";
let mut client_rng = OsRng;
let mut server_rng = OsRng;
let server_setup = ServerSetup::<CS>::new(&mut server_rng);
let client_registration_start_result =
ClientRegistration::<CS>::start(&mut client_rng, registration_password)?;
let server_registration_start_result = ServerRegistration::<CS>::start(
&server_setup,
client_registration_start_result.message,
credential_identifier,
)?;
let client_registration_finish_result = client_registration_start_result.state.finish(
&mut client_rng,
registration_password,
server_registration_start_result.message,
ClientRegistrationFinishParameters::default(),
)?;
let p_file = ServerRegistration::finish(client_registration_finish_result.message);
let client_login_start_result = ClientLogin::<CS>::start(&mut client_rng, login_password)?;
let server_login_start_result = ServerLogin::<CS>::start(
&mut server_rng,
&server_setup,
Some(p_file),
client_login_start_result.message,
credential_identifier,
ServerLoginStartParameters::default(),
)?;
let client_login_result = client_login_start_result.state.finish(
login_password,
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.session_key),
hex::encode(&client_login_finish_result.session_key)
);
assert_eq!(
hex::encode(client_registration_finish_result.export_key),
hex::encode(client_login_finish_result.export_key)
);
} else {
assert!(matches!(
client_login_result,
Err(ProtocolError::InvalidLoginError)
));
}
Ok(())
}
#[test]
fn test_complete_flow_success() -> Result<(), ProtocolError> {
#[cfg(feature = "ristretto255")]
test_complete_flow::<Ristretto255>(b"good password", b"good password")?;
#[cfg(feature = "ristretto255")]
test_complete_flow::<Ristretto255P256>(b"good password", b"good password")?;
#[cfg(feature = "ristretto255")]
test_complete_flow::<Ristretto255P384>(b"good password", b"good password")?;
test_complete_flow::<P256>(b"good password", b"good password")?;
test_complete_flow::<P256P384>(b"good password", b"good password")?;
#[cfg(feature = "ristretto255")]
test_complete_flow::<P256Ristretto255>(b"good password", b"good password")?;
test_complete_flow::<P384>(b"good password", b"good password")?;
test_complete_flow::<P384P256>(b"good password", b"good password")?;
#[cfg(feature = "ristretto255")]
test_complete_flow::<P384Ristretto255>(b"good password", b"good password")?;
#[cfg(feature = "curve25519")]
test_complete_flow::<Curve25519P256>(b"good password", b"good password")?;
#[cfg(feature = "curve25519")]
test_complete_flow::<Curve25519P384>(b"good password", b"good password")?;
#[cfg(all(feature = "curve25519", feature = "ristretto255"))]
test_complete_flow::<Curve25519Ristretto255>(b"good password", b"good password")?;
Ok(())
}
#[test]
fn test_complete_flow_fail() -> Result<(), ProtocolError> {
#[cfg(feature = "ristretto255")]
test_complete_flow::<Ristretto255>(b"good password", b"bad password")?;
#[cfg(feature = "ristretto255")]
test_complete_flow::<Ristretto255P256>(b"good password", b"bad password")?;
#[cfg(feature = "ristretto255")]
test_complete_flow::<Ristretto255P384>(b"good password", b"bad password")?;
test_complete_flow::<P256>(b"good password", b"bad password")?;
test_complete_flow::<P256P384>(b"good password", b"bad password")?;
#[cfg(feature = "ristretto255")]
test_complete_flow::<P256Ristretto255>(b"good password", b"bad password")?;
test_complete_flow::<P384>(b"good password", b"bad password")?;
test_complete_flow::<P384P256>(b"good password", b"bad password")?;
#[cfg(feature = "ristretto255")]
test_complete_flow::<P384Ristretto255>(b"good password", b"bad password")?;
#[cfg(feature = "curve25519")]
test_complete_flow::<Curve25519P256>(b"good password", b"bad password")?;
#[cfg(feature = "curve25519")]
test_complete_flow::<Curve25519P384>(b"good password", b"bad password")?;
#[cfg(all(feature = "curve25519", feature = "ristretto255"))]
test_complete_flow::<Curve25519Ristretto255>(b"good password", b"bad password")?;
Ok(())
}
// Zeroize tests
#[test]
fn test_zeroize_client_registration_start() -> Result<(), ProtocolError> {
fn inner<CS: CipherSuite>() -> Result<(), ProtocolError>
where
<OprfHash<CS> as OutputSizeUser>::OutputSize:
IsLess<U256> + IsLessOrEqual<<OprfHash<CS> as BlockSizeUser>::BlockSize>,
OprfHash<CS>: Hash,
<OprfHash<CS> as CoreProxy>::Core: ProxyHash,
<<OprfHash<CS> as CoreProxy>::Core as BlockSizeUser>::BlockSize: IsLess<U256>,
Le<<<OprfHash<CS> as CoreProxy>::Core as BlockSizeUser>::BlockSize, U256>: NonZero,
{
let mut client_rng = OsRng;
let client_registration_start_result =
ClientRegistration::<CS>::start(&mut client_rng, STR_PASSWORD.as_bytes())?;
let mut state = client_registration_start_result.state;
unsafe { ptr::drop_in_place(&mut state) };
for byte in state.to_vec() {
assert_eq!(byte, 0);
}
Ok(())
}
#[cfg(feature = "ristretto255")]
inner::<Ristretto255>()?;
#[cfg(feature = "ristretto255")]
inner::<Ristretto255P256>()?;
#[cfg(feature = "ristretto255")]
inner::<Ristretto255P384>()?;
inner::<P256>()?;
inner::<P256P384>()?;
#[cfg(feature = "ristretto255")]
inner::<P256Ristretto255>()?;
inner::<P384>()?;
inner::<P384P256>()?;
#[cfg(feature = "ristretto255")]
inner::<P384Ristretto255>()?;
#[cfg(feature = "curve25519")]
inner::<Curve25519P256>()?;
#[cfg(feature = "curve25519")]
inner::<Curve25519P384>()?;
#[cfg(all(feature = "curve25519", feature = "ristretto255"))]
inner::<Curve25519Ristretto255>()?;
Ok(())
}
#[test]
fn test_zeroize_client_registration_finish() -> Result<(), ProtocolError> {
fn inner<CS: CipherSuite>() -> Result<(), ProtocolError>
where
<OprfHash<CS> as OutputSizeUser>::OutputSize:
IsLess<U256> + IsLessOrEqual<<OprfHash<CS> as BlockSizeUser>::BlockSize>,
OprfHash<CS>: Hash,
<OprfHash<CS> as CoreProxy>::Core: ProxyHash,
<<OprfHash<CS> as CoreProxy>::Core as BlockSizeUser>::BlockSize: IsLess<U256>,
Le<<<OprfHash<CS> as CoreProxy>::Core as BlockSizeUser>::BlockSize, U256>: NonZero,
{
let mut client_rng = OsRng;
let mut server_rng = OsRng;
let server_setup = ServerSetup::<CS>::new(&mut server_rng);
let client_registration_start_result =
ClientRegistration::<CS>::start(&mut client_rng, STR_PASSWORD.as_bytes())?;
let server_registration_start_result = ServerRegistration::<CS>::start(
&server_setup,
client_registration_start_result.message,
STR_CREDENTIAL_IDENTIFIER.as_bytes(),
)?;
let client_registration_finish_result = client_registration_start_result.state.finish(
&mut client_rng,
STR_PASSWORD.as_bytes(),
server_registration_start_result.message,
ClientRegistrationFinishParameters::default(),
)?;
let mut state = client_registration_finish_result.state;
unsafe { ptr::drop_in_place(&mut state) };
for byte in state.to_vec() {
assert_eq!(byte, 0);
}
Ok(())
}
#[cfg(feature = "ristretto255")]
inner::<Ristretto255>()?;
#[cfg(feature = "ristretto255")]
inner::<Ristretto255P256>()?;
#[cfg(feature = "ristretto255")]
inner::<Ristretto255P384>()?;
inner::<P256>()?;
inner::<P256P384>()?;
#[cfg(feature = "ristretto255")]
inner::<P256Ristretto255>()?;
inner::<P384>()?;
inner::<P384P256>()?;
#[cfg(feature = "ristretto255")]
inner::<P384Ristretto255>()?;
#[cfg(feature = "curve25519")]
inner::<Curve25519P256>()?;
#[cfg(feature = "curve25519")]
inner::<Curve25519P384>()?;
#[cfg(all(feature = "curve25519", feature = "ristretto255"))]
inner::<Curve25519Ristretto255>()?;
Ok(())
}
#[test]
fn test_zeroize_server_registration_finish() -> Result<(), ProtocolError> {
fn inner<CS: CipherSuite>() -> Result<(), ProtocolError>
where
<OprfHash<CS> as OutputSizeUser>::OutputSize:
IsLess<U256> + IsLessOrEqual<<OprfHash<CS> as BlockSizeUser>::BlockSize>,
OprfHash<CS>: Hash,
<OprfHash<CS> as CoreProxy>::Core: ProxyHash,
<<OprfHash<CS> as CoreProxy>::Core as BlockSizeUser>::BlockSize: IsLess<U256>,
Le<<<OprfHash<CS> as CoreProxy>::Core as BlockSizeUser>::BlockSize, U256>: NonZero,
// Envelope: Nonce + Hash
NonceLen: Add<OutputSize<OprfHash<CS>>>,
EnvelopeLen<CS>: ArrayLength<u8>,
// RegistrationUpload: (KePk + Hash) + Envelope
<CS::KeGroup as KeGroup>::PkLen: Add<OutputSize<OprfHash<CS>>>,
Sum<<CS::KeGroup as KeGroup>::PkLen, OutputSize<OprfHash<CS>>>:
ArrayLength<u8> + Add<EnvelopeLen<CS>>,
RegistrationUploadLen<CS>: ArrayLength<u8>,
// ServerRegistration = RegistrationUpload
{
let mut client_rng = OsRng;
let mut server_rng = OsRng;
let server_setup = ServerSetup::<CS>::new(&mut server_rng);
let client_registration_start_result =
ClientRegistration::<CS>::start(&mut client_rng, STR_PASSWORD.as_bytes())?;
let server_registration_start_result = ServerRegistration::<CS>::start(
&server_setup,
client_registration_start_result.message,
STR_CREDENTIAL_IDENTIFIER.as_bytes(),
)?;
let client_registration_finish_result = client_registration_start_result.state.finish(
&mut client_rng,
STR_PASSWORD.as_bytes(),
server_registration_start_result.message,
ClientRegistrationFinishParameters::default(),
)?;
let p_file = ServerRegistration::finish(client_registration_finish_result.message);
let mut state = p_file;
util::drop_manually(&mut state);
util::test_zeroized(&mut state.0.envelope.mode);
util::test_zeroized(&mut state.0.masking_key);
Ok(())
}
#[cfg(feature = "ristretto255")]
inner::<Ristretto255>()?;
#[cfg(feature = "ristretto255")]
inner::<Ristretto255P256>()?;
#[cfg(feature = "ristretto255")]
inner::<Ristretto255P384>()?;
inner::<P256>()?;
inner::<P256P384>()?;
#[cfg(feature = "ristretto255")]
inner::<P256Ristretto255>()?;
inner::<P384>()?;
inner::<P384P256>()?;
#[cfg(feature = "ristretto255")]
inner::<P384Ristretto255>()?;
#[cfg(feature = "curve25519")]
inner::<Curve25519P256>()?;
#[cfg(feature = "curve25519")]
inner::<Curve25519P384>()?;
#[cfg(all(feature = "curve25519", feature = "ristretto255"))]
inner::<Curve25519Ristretto255>()?;
Ok(())
}
#[test]
fn test_zeroize_client_login_start() -> Result<(), ProtocolError> {
fn inner<CS: CipherSuite<KeyExchange = TripleDh>>() -> Result<(), ProtocolError>
where
<OprfHash<CS> as OutputSizeUser>::OutputSize:
IsLess<U256> + IsLessOrEqual<<OprfHash<CS> as BlockSizeUser>::BlockSize>,
OprfHash<CS>: Hash,
<OprfHash<CS> as CoreProxy>::Core: ProxyHash,
<<OprfHash<CS> as CoreProxy>::Core as BlockSizeUser>::BlockSize: IsLess<U256>,
Le<<<OprfHash<CS> as CoreProxy>::Core as BlockSizeUser>::BlockSize, U256>: NonZero,
// CredentialRequest: KgPk + Ke1Message
<OprfGroup<CS> as Group>::ElemLen: Add<Sum<NonceLen, <CS::KeGroup as KeGroup>::PkLen>>,
CredentialRequestLen<CS>: ArrayLength<u8>,
// Ke1State: KeSk + Nonce
<CS::KeGroup as KeGroup>::SkLen: Add<NonceLen>,
Sum<<CS::KeGroup as KeGroup>::SkLen, NonceLen>: ArrayLength<u8>,
// Ke1Message: Nonce + KePk
NonceLen: Add<<CS::KeGroup as KeGroup>::PkLen>,
Sum<NonceLen, <CS::KeGroup as KeGroup>::PkLen>: ArrayLength<u8>,
// Ke2State: (Hash + Hash) + Hash
OutputSize<OprfHash<CS>>: Add<OutputSize<OprfHash<CS>>>,
Sum<OutputSize<OprfHash<CS>>, OutputSize<OprfHash<CS>>>:
ArrayLength<u8> + Add<OutputSize<OprfHash<CS>>>,
Sum<Sum<OutputSize<OprfHash<CS>>, OutputSize<OprfHash<CS>>>, OutputSize<OprfHash<CS>>>:
ArrayLength<u8>,
// Ke2Message: (Nonce + KePk) + Hash
NonceLen: Add<<CS::KeGroup as KeGroup>::PkLen>,
Sum<NonceLen, <CS::KeGroup as KeGroup>::PkLen>:
ArrayLength<u8> + Add<OutputSize<OprfHash<CS>>>,
Sum<Sum<NonceLen, <CS::KeGroup as KeGroup>::PkLen>, OutputSize<OprfHash<CS>>>:
ArrayLength<u8>,
{
let mut client_rng = OsRng;
let client_login_start_result =
ClientLogin::<CS>::start(&mut client_rng, STR_PASSWORD.as_bytes())?;
let mut state = client_login_start_result.state;
util::drop_manually(&mut state);
util::test_zeroized(&mut state.oprf_client);
util::test_zeroized(&mut state.ke1_state);
util::test_zeroized(&mut state.credential_request.ke1_message.client_nonce);
Ok(())
}
#[cfg(feature = "ristretto255")]
inner::<Ristretto255>()?;
#[cfg(feature = "ristretto255")]
inner::<Ristretto255P256>()?;
#[cfg(feature = "ristretto255")]
inner::<Ristretto255P384>()?;
inner::<P256>()?;
inner::<P256P384>()?;
#[cfg(feature = "ristretto255")]
inner::<P256Ristretto255>()?;
inner::<P384>()?;
inner::<P384P256>()?;
#[cfg(feature = "ristretto255")]
inner::<P384Ristretto255>()?;
#[cfg(feature = "curve25519")]
inner::<Curve25519P256>()?;
#[cfg(feature = "curve25519")]
inner::<Curve25519P384>()?;
#[cfg(all(feature = "curve25519", feature = "ristretto255"))]
inner::<Curve25519Ristretto255>()?;
Ok(())
}
#[test]
fn test_zeroize_server_login_start() -> Result<(), ProtocolError> {
fn inner<CS: CipherSuite>() -> Result<(), ProtocolError>
where
<OprfHash<CS> as OutputSizeUser>::OutputSize:
IsLess<U256> + IsLessOrEqual<<OprfHash<CS> as BlockSizeUser>::BlockSize>,
OprfHash<CS>: Hash,
<OprfHash<CS> as CoreProxy>::Core: ProxyHash,
<<OprfHash<CS> as CoreProxy>::Core as BlockSizeUser>::BlockSize: IsLess<U256>,
Le<<<OprfHash<CS> as CoreProxy>::Core as BlockSizeUser>::BlockSize, U256>: NonZero,
// MaskedResponse: (Nonce + Hash) + KePk
NonceLen: Add<OutputSize<OprfHash<CS>>>,
Sum<NonceLen, OutputSize<OprfHash<CS>>>:
ArrayLength<u8> + Add<<CS::KeGroup as KeGroup>::PkLen>,
MaskedResponseLen<CS>: ArrayLength<u8>,
{
let mut client_rng = OsRng;
let mut server_rng = OsRng;
let server_setup = ServerSetup::<CS>::new(&mut server_rng);
let client_registration_start_result =
ClientRegistration::<CS>::start(&mut client_rng, STR_PASSWORD.as_bytes())?;
let server_registration_start_result = ServerRegistration::<CS>::start(
&server_setup,
client_registration_start_result.message,
STR_CREDENTIAL_IDENTIFIER.as_bytes(),
)?;
let client_registration_finish_result = client_registration_start_result.state.finish(
&mut client_rng,
STR_PASSWORD.as_bytes(),
server_registration_start_result.message,
ClientRegistrationFinishParameters::default(),
)?;
let p_file = ServerRegistration::finish(client_registration_finish_result.message);
let client_login_start_result =
ClientLogin::<CS>::start(&mut client_rng, STR_PASSWORD.as_bytes())?;
let server_login_start_result = ServerLogin::<CS>::start(
&mut server_rng,
&server_setup,
Some(p_file),
client_login_start_result.message,
STR_CREDENTIAL_IDENTIFIER.as_bytes(),
ServerLoginStartParameters::default(),
)?;
let mut state = server_login_start_result.state;
unsafe { ptr::drop_in_place(&mut state) };
for byte in state.serialize() {
assert_eq!(byte, 0);
}
Ok(())
}
#[cfg(feature = "ristretto255")]
inner::<Ristretto255>()?;
#[cfg(feature = "ristretto255")]
inner::<Ristretto255P256>()?;
#[cfg(feature = "ristretto255")]
inner::<Ristretto255P384>()?;
inner::<P256>()?;
inner::<P256P384>()?;
#[cfg(feature = "ristretto255")]
inner::<P256Ristretto255>()?;
inner::<P384>()?;
inner::<P384P256>()?;
#[cfg(feature = "ristretto255")]
inner::<P384Ristretto255>()?;
#[cfg(feature = "curve25519")]
inner::<Curve25519P256>()?;
#[cfg(feature = "curve25519")]
inner::<Curve25519P384>()?;
#[cfg(all(feature = "curve25519", feature = "ristretto255"))]
inner::<Curve25519Ristretto255>()?;
Ok(())
}
#[test]
fn test_zeroize_client_login_finish() -> Result<(), ProtocolError> {
fn inner<CS: CipherSuite<KeyExchange = TripleDh>>() -> Result<(), ProtocolError>
where
<OprfHash<CS> as OutputSizeUser>::OutputSize:
IsLess<U256> + IsLessOrEqual<<OprfHash<CS> as BlockSizeUser>::BlockSize>,
OprfHash<CS>: Hash,
<OprfHash<CS> as CoreProxy>::Core: ProxyHash,
<<OprfHash<CS> as CoreProxy>::Core as BlockSizeUser>::BlockSize: IsLess<U256>,
Le<<<OprfHash<CS> as CoreProxy>::Core as BlockSizeUser>::BlockSize, U256>: NonZero,
// MaskedResponse: (Nonce + Hash) + KePk
NonceLen: Add<OutputSize<OprfHash<CS>>>,
Sum<NonceLen, OutputSize<OprfHash<CS>>>:
ArrayLength<u8> + Add<<CS::KeGroup as KeGroup>::PkLen>,
MaskedResponseLen<CS>: ArrayLength<u8>,
// CredentialRequest: KgPk + Ke1Message
<OprfGroup<CS> as Group>::ElemLen: Add<Sum<NonceLen, <CS::KeGroup as KeGroup>::PkLen>>,
CredentialRequestLen<CS>: ArrayLength<u8>,
// Ke1State: KeSk + Nonce
<CS::KeGroup as KeGroup>::SkLen: Add<NonceLen>,
Sum<<CS::KeGroup as KeGroup>::SkLen, NonceLen>: ArrayLength<u8>,
// Ke1Message: Nonce + KePk
NonceLen: Add<<CS::KeGroup as KeGroup>::PkLen>,
Sum<NonceLen, <CS::KeGroup as KeGroup>::PkLen>: ArrayLength<u8>,
// Ke2State: (Hash + Hash) + Hash
OutputSize<OprfHash<CS>>: Add<OutputSize<OprfHash<CS>>>,
Sum<OutputSize<OprfHash<CS>>, OutputSize<OprfHash<CS>>>:
ArrayLength<u8> + Add<OutputSize<OprfHash<CS>>>,
Sum<Sum<OutputSize<OprfHash<CS>>, OutputSize<OprfHash<CS>>>, OutputSize<OprfHash<CS>>>:
ArrayLength<u8>,
// Ke2Message: (Nonce + KePk) + Hash
NonceLen: Add<<CS::KeGroup as KeGroup>::PkLen>,
Sum<NonceLen, <CS::KeGroup as KeGroup>::PkLen>:
ArrayLength<u8> + Add<OutputSize<OprfHash<CS>>>,
Sum<Sum<NonceLen, <CS::KeGroup as KeGroup>::PkLen>, OutputSize<OprfHash<CS>>>:
ArrayLength<u8>,
{
let mut client_rng = OsRng;
let mut server_rng = OsRng;
let server_setup = ServerSetup::<CS>::new(&mut server_rng);
let client_registration_start_result =
ClientRegistration::<CS>::start(&mut client_rng, STR_PASSWORD.as_bytes())?;
let server_registration_start_result = ServerRegistration::<CS>::start(
&server_setup,
client_registration_start_result.message,
STR_CREDENTIAL_IDENTIFIER.as_bytes(),
)?;
let client_registration_finish_result = client_registration_start_result.state.finish(
&mut client_rng,
STR_PASSWORD.as_bytes(),
server_registration_start_result.message,
ClientRegistrationFinishParameters::default(),
)?;
let p_file = ServerRegistration::finish(client_registration_finish_result.message);
let client_login_start_result =
ClientLogin::<CS>::start(&mut client_rng, STR_PASSWORD.as_bytes())?;
let server_login_start_result = ServerLogin::<CS>::start(
&mut server_rng,
&server_setup,
Some(p_file),
client_login_start_result.message,
STR_CREDENTIAL_IDENTIFIER.as_bytes(),
ServerLoginStartParameters::default(),
)?;
let client_login_finish_result = client_login_start_result.state.finish(
STR_PASSWORD.as_bytes(),
server_login_start_result.message,
ClientLoginFinishParameters::default(),
)?;
let mut state = client_login_finish_result.state;
util::drop_manually(&mut state);
util::test_zeroized(&mut state.oprf_client);
util::test_zeroized(&mut state.ke1_state);
util::test_zeroized(&mut state.credential_request.ke1_message.client_nonce);
Ok(())
}
#[cfg(feature = "ristretto255")]
inner::<Ristretto255>()?;
#[cfg(feature = "ristretto255")]
inner::<Ristretto255P256>()?;
#[cfg(feature = "ristretto255")]
inner::<Ristretto255P384>()?;
inner::<P256>()?;
inner::<P256P384>()?;
#[cfg(feature = "ristretto255")]
inner::<P256Ristretto255>()?;
inner::<P384>()?;
inner::<P384P256>()?;
#[cfg(feature = "ristretto255")]
inner::<P384Ristretto255>()?;
#[cfg(feature = "curve25519")]
inner::<Curve25519P256>()?;
#[cfg(feature = "curve25519")]
inner::<Curve25519P384>()?;
#[cfg(all(feature = "curve25519", feature = "ristretto255"))]
inner::<Curve25519Ristretto255>()?;
Ok(())
}
#[test]
fn test_zeroize_server_login_finish() -> Result<(), ProtocolError> {
fn inner<CS: CipherSuite>() -> Result<(), ProtocolError>
where
<OprfHash<CS> as OutputSizeUser>::OutputSize:
IsLess<U256> + IsLessOrEqual<<OprfHash<CS> as BlockSizeUser>::BlockSize>,
OprfHash<CS>: Hash,
<OprfHash<CS> as CoreProxy>::Core: ProxyHash,
<<OprfHash<CS> as CoreProxy>::Core as BlockSizeUser>::BlockSize: IsLess<U256>,
Le<<<OprfHash<CS> as CoreProxy>::Core as BlockSizeUser>::BlockSize, U256>: NonZero,
// MaskedResponse: (Nonce + Hash) + KePk
NonceLen: Add<OutputSize<OprfHash<CS>>>,
Sum<NonceLen, OutputSize<OprfHash<CS>>>:
ArrayLength<u8> + Add<<CS::KeGroup as KeGroup>::PkLen>,
MaskedResponseLen<CS>: ArrayLength<u8>,
{
let mut client_rng = OsRng;
let mut server_rng = OsRng;
let server_setup = ServerSetup::<CS>::new(&mut server_rng);
let client_registration_start_result =
ClientRegistration::<CS>::start(&mut client_rng, STR_PASSWORD.as_bytes())?;
let server_registration_start_result = ServerRegistration::<CS>::start(
&server_setup,
client_registration_start_result.message,
STR_CREDENTIAL_IDENTIFIER.as_bytes(),
)?;
let client_registration_finish_result = client_registration_start_result.state.finish(
&mut client_rng,
STR_PASSWORD.as_bytes(),
server_registration_start_result.message,
ClientRegistrationFinishParameters::default(),
)?;
let p_file = ServerRegistration::finish(client_registration_finish_result.message);
let client_login_start_result =
ClientLogin::<CS>::start(&mut client_rng, STR_PASSWORD.as_bytes())?;
let server_login_start_result = ServerLogin::<CS>::start(
&mut server_rng,
&server_setup,
Some(p_file),
client_login_start_result.message,
STR_CREDENTIAL_IDENTIFIER.as_bytes(),
ServerLoginStartParameters::default(),
)?;
let client_login_finish_result = client_login_start_result.state.finish(
STR_PASSWORD.as_bytes(),
server_login_start_result.message,
ClientLoginFinishParameters::default(),
)?;
let server_login_finish_result = server_login_start_result
.state
.finish(client_login_finish_result.message)?;
let mut state = server_login_finish_result.state;
unsafe { ptr::drop_in_place(&mut state) };
for byte in state.serialize() {
assert_eq!(byte, 0);
}
Ok(())
}
#[cfg(feature = "ristretto255")]
inner::<Ristretto255>()?;
#[cfg(feature = "ristretto255")]
inner::<Ristretto255P256>()?;
#[cfg(feature = "ristretto255")]
inner::<Ristretto255P384>()?;
inner::<P256>()?;
inner::<P256P384>()?;
#[cfg(feature = "ristretto255")]
inner::<P256Ristretto255>()?;
inner::<P384>()?;
inner::<P384P256>()?;
#[cfg(feature = "ristretto255")]
inner::<P384Ristretto255>()?;
#[cfg(feature = "curve25519")]
inner::<Curve25519P256>()?;
#[cfg(feature = "curve25519")]
inner::<Curve25519P384>()?;
#[cfg(all(feature = "curve25519", feature = "ristretto255"))]
inner::<Curve25519Ristretto255>()?;
Ok(())
}
#[test]
fn test_scalar_always_nonzero() -> Result<(), ProtocolError> {
fn inner<CS: CipherSuite>() -> Result<(), ProtocolError>
where
<OprfHash<CS> as OutputSizeUser>::OutputSize:
IsLess<U256> + IsLessOrEqual<<OprfHash<CS> as BlockSizeUser>::BlockSize>,
OprfHash<CS>: Hash,
<OprfHash<CS> as CoreProxy>::Core: ProxyHash,
<<OprfHash<CS> as CoreProxy>::Core as BlockSizeUser>::BlockSize: IsLess<U256>,
Le<<<OprfHash<CS> as CoreProxy>::Core as BlockSizeUser>::BlockSize, U256>: NonZero,
{
// Start out with a bunch of zeros to force resampling of scalar
let mut client_registration_rng = CycleRng::new([vec![0u8; 128], vec![1u8; 128]].concat());
let client_registration_start_result =
ClientRegistration::<CS>::start(&mut client_registration_rng, STR_PASSWORD.as_bytes())?;
assert!(!bool::from(
OprfGroup::<CS>::identity_elem().ct_eq(
&client_registration_start_result
.message
.get_blinded_element_for_testing()
.value(),
)
));
// Start out with a bunch of zeros to force resampling of scalar
let mut client_login_rng = CycleRng::new([vec![0u8; 128], vec![1u8; 128]].concat());
let client_login_start_result =
ClientLogin::<CS>::start(&mut client_login_rng, STR_PASSWORD.as_bytes())?;
assert!(!bool::from(
OprfGroup::<CS>::identity_elem().ct_eq(
&client_login_start_result
.message
.get_blinded_element_for_testing()
.value(),
)
));
Ok(())
}
#[cfg(feature = "ristretto255")]
inner::<Ristretto255>()?;
#[cfg(feature = "ristretto255")]
inner::<Ristretto255P256>()?;
#[cfg(feature = "ristretto255")]
inner::<Ristretto255P384>()?;
inner::<P256>()?;
inner::<P256P384>()?;
#[cfg(feature = "ristretto255")]
inner::<P256Ristretto255>()?;
inner::<P384>()?;
inner::<P384P256>()?;
#[cfg(feature = "ristretto255")]
inner::<P384Ristretto255>()?;
#[cfg(feature = "curve25519")]
inner::<Curve25519P256>()?;
#[cfg(feature = "curve25519")]
inner::<Curve25519P384>()?;
#[cfg(all(feature = "curve25519", feature = "ristretto255"))]
inner::<Curve25519Ristretto255>()?;
Ok(())
}
#[test]
fn test_reflected_value_error_registration() -> Result<(), ProtocolError> {
fn inner<CS: CipherSuite>() -> Result<(), ProtocolError>
where
<OprfHash<CS> as OutputSizeUser>::OutputSize:
IsLess<U256> + IsLessOrEqual<<OprfHash<CS> as BlockSizeUser>::BlockSize>,
OprfHash<CS>: Hash,
<OprfHash<CS> as CoreProxy>::Core: ProxyHash,
<<OprfHash<CS> as CoreProxy>::Core as BlockSizeUser>::BlockSize: IsLess<U256>,
Le<<<OprfHash<CS> as CoreProxy>::Core as BlockSizeUser>::BlockSize, U256>: NonZero,
{
let credential_identifier = b"credentialIdentifier";
let password = b"password";
let mut client_rng = OsRng;
let mut server_rng = OsRng;
let server_setup = ServerSetup::<CS>::new(&mut server_rng);
let client_registration_start_result =
ClientRegistration::<CS>::start(&mut client_rng, password)?;
let alpha = client_registration_start_result
.message
.get_blinded_element_for_testing()
.value();
let server_registration_start_result = ServerRegistration::<CS>::start(
&server_setup,
client_registration_start_result.message,
credential_identifier,
)?;
let reflected_registration_response = server_registration_start_result
.message
.set_evaluation_element_for_testing(alpha);
let client_registration_finish_result = client_registration_start_result.state.finish(
&mut client_rng,
password,
reflected_registration_response,
ClientRegistrationFinishParameters::default(),
);
assert!(matches!(
client_registration_finish_result,
Err(ProtocolError::ReflectedValueError)
));
Ok(())
}
#[cfg(feature = "ristretto255")]
inner::<Ristretto255>()?;
#[cfg(feature = "ristretto255")]
inner::<Ristretto255P256>()?;
#[cfg(feature = "ristretto255")]
inner::<Ristretto255P384>()?;
inner::<P256>()?;
inner::<P256P384>()?;
#[cfg(feature = "ristretto255")]
inner::<P256Ristretto255>()?;
inner::<P384>()?;
inner::<P384P256>()?;
#[cfg(feature = "ristretto255")]
inner::<P384Ristretto255>()?;
#[cfg(feature = "curve25519")]
inner::<Curve25519P256>()?;
#[cfg(feature = "curve25519")]
inner::<Curve25519P384>()?;
#[cfg(all(feature = "curve25519", feature = "ristretto255"))]
inner::<Curve25519Ristretto255>()?;
Ok(())
}
#[test]
fn test_reflected_value_error_login() -> Result<(), ProtocolError> {
fn inner<CS: CipherSuite>() -> Result<(), ProtocolError>
where
<OprfHash<CS> as OutputSizeUser>::OutputSize:
IsLess<U256> + IsLessOrEqual<<OprfHash<CS> as BlockSizeUser>::BlockSize>,
OprfHash<CS>: Hash,
<OprfHash<CS> as CoreProxy>::Core: ProxyHash,
<<OprfHash<CS> as CoreProxy>::Core as BlockSizeUser>::BlockSize: IsLess<U256>,
Le<<<OprfHash<CS> as CoreProxy>::Core as BlockSizeUser>::BlockSize, U256>: NonZero,
// MaskedResponse: (Nonce + Hash) + KePk
NonceLen: Add<OutputSize<OprfHash<CS>>>,
Sum<NonceLen, OutputSize<OprfHash<CS>>>:
ArrayLength<u8> + Add<<CS::KeGroup as KeGroup>::PkLen>,
MaskedResponseLen<CS>: ArrayLength<u8>,
{
let credential_identifier = b"credentialIdentifier";
let password = b"password";
let mut client_rng = OsRng;
let mut server_rng = OsRng;
let server_setup = ServerSetup::<CS>::new(&mut server_rng);
let client_registration_start_result =
ClientRegistration::<CS>::start(&mut client_rng, password)?;
let server_registration_start_result = ServerRegistration::<CS>::start(
&server_setup,
client_registration_start_result.message,
credential_identifier,
)?;
let client_registration_finish_result = client_registration_start_result.state.finish(
&mut client_rng,
password,
server_registration_start_result.message,
ClientRegistrationFinishParameters::default(),
)?;
let p_file = ServerRegistration::finish(client_registration_finish_result.message);
let client_login_start_result = ClientLogin::<CS>::start(&mut client_rng, password)?;
let alpha = client_login_start_result
.message
.get_blinded_element_for_testing()
.value();
let server_login_start_result = ServerLogin::<CS>::start(
&mut server_rng,
&server_setup,
Some(p_file),
client_login_start_result.message,
credential_identifier,
ServerLoginStartParameters::default(),
)?;
let reflected_credential_response = server_login_start_result
.message
.set_evaluation_element_for_testing(alpha);
let client_login_result = client_login_start_result.state.finish(
password,
reflected_credential_response,
ClientLoginFinishParameters::default(),
);
assert!(matches!(
client_login_result,
Err(ProtocolError::ReflectedValueError)
));
Ok(())
}
#[cfg(feature = "ristretto255")]
inner::<Ristretto255>()?;
#[cfg(feature = "ristretto255")]
inner::<Ristretto255P256>()?;
#[cfg(feature = "ristretto255")]
inner::<Ristretto255P384>()?;
inner::<P256>()?;
inner::<P256P384>()?;
#[cfg(feature = "ristretto255")]
inner::<P256Ristretto255>()?;
inner::<P384>()?;
inner::<P384P256>()?;
#[cfg(feature = "ristretto255")]
inner::<P384Ristretto255>()?;
#[cfg(feature = "curve25519")]
inner::<Curve25519P256>()?;
#[cfg(feature = "curve25519")]
inner::<Curve25519P384>()?;
#[cfg(all(feature = "curve25519", feature = "ristretto255"))]
inner::<Curve25519Ristretto255>()?;
Ok(())
}