Compare commits
3
Commits
v1.0.0-rc.0
...
v0.7.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8bb96820d9 | ||
|
|
902a605b9c | ||
|
|
1012439d2f |
@@ -17,7 +17,7 @@ jobs:
|
||||
- u32_backend
|
||||
toolchain:
|
||||
- nightly
|
||||
- 1.41.0
|
||||
- 1.56.0
|
||||
name: test
|
||||
steps:
|
||||
- name: Checkout sources
|
||||
@@ -94,7 +94,7 @@ jobs:
|
||||
matrix:
|
||||
toolchain:
|
||||
- nightly
|
||||
- 1.41.0
|
||||
- 1.56.0
|
||||
name: test simple_login command-line example
|
||||
steps:
|
||||
- name: install expect
|
||||
@@ -118,7 +118,7 @@ jobs:
|
||||
matrix:
|
||||
toolchain:
|
||||
- nightly
|
||||
- 1.41.0
|
||||
- 1.51.0
|
||||
name: test digital_locker command-line example
|
||||
steps:
|
||||
- name: install expect
|
||||
@@ -135,26 +135,6 @@ jobs:
|
||||
- name: Run expect (which then runs cargo run)
|
||||
run: expect -f scripts/digital_locker.exp
|
||||
|
||||
benches:
|
||||
name: cargo bench compilation
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout sources
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Install stable toolchain
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
profile: minimal
|
||||
toolchain: stable
|
||||
override: true
|
||||
|
||||
- name: Run cargo bench --no-run
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: bench
|
||||
args: --features "bench" --no-run
|
||||
|
||||
clippy:
|
||||
name: cargo clippy
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
@@ -1,5 +1,14 @@
|
||||
# Changelog
|
||||
|
||||
## 0.7.0 (May 13, 2023)
|
||||
|
||||
* Update zeroize dependency to allow for beyond version 1.5
|
||||
* Increase MSRV to 1.56
|
||||
|
||||
## 0.6.1 (January 25, 2022)
|
||||
|
||||
* Fix `zeroize` implementing `Drop` on `enum`s now
|
||||
|
||||
## 0.6.0 (June 30, 2021)
|
||||
|
||||
* Synced implementation with draft-irtf-cfrg-opaque-05, which changes
|
||||
|
||||
+4
-10
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "opaque-ke"
|
||||
version = "0.6.0"
|
||||
version = "0.7.0"
|
||||
repository = "https://github.com/novifinancial/opaque-ke"
|
||||
keywords = ["cryptography", "crypto", "opaque", "passwords", "authentication"]
|
||||
description = "An implementation of the OPAQUE password-authenticated key exchange protocol"
|
||||
@@ -31,22 +31,16 @@ rand = "0.8"
|
||||
serde = { version = "1", features = ["derive"], optional = true }
|
||||
subtle = { version = "2.3.0", default-features = false }
|
||||
thiserror = "1.0.22"
|
||||
zeroize = { version = "1.1.1", features = ["zeroize_derive"] }
|
||||
zeroize = { version = "1.5", features = ["zeroize_derive"] }
|
||||
|
||||
[dev-dependencies]
|
||||
anyhow = "1.0.35"
|
||||
base64 = "0.13.0"
|
||||
bincode = "1"
|
||||
chacha20poly1305 = "0.7.1"
|
||||
criterion = "0.3.3"
|
||||
hex = "0.4.2"
|
||||
lazy_static = "1.4.0"
|
||||
serde_json = "1.0.60"
|
||||
sha2 = "0.9.2"
|
||||
proptest = "0.10.1"
|
||||
rustyline = "6.3.0"
|
||||
|
||||
[[bench]]
|
||||
name = "oprf"
|
||||
harness = false
|
||||
required-features = ["bench"]
|
||||
proptest = "0.3"
|
||||
rustyline = "1"
|
||||
|
||||
@@ -22,7 +22,7 @@ Installation
|
||||
Add the following line to the dependencies of your `Cargo.toml`:
|
||||
|
||||
```
|
||||
opaque-ke = "0.6.0"
|
||||
opaque-ke = "0.7.0"
|
||||
```
|
||||
|
||||
Resources
|
||||
|
||||
@@ -1,68 +0,0 @@
|
||||
// Copyright (c) Facebook, Inc. and its affiliates.
|
||||
//
|
||||
// This source code is licensed under the MIT license found in the
|
||||
// LICENSE file in the root directory of this source tree.
|
||||
|
||||
#[macro_use]
|
||||
extern crate criterion;
|
||||
|
||||
use criterion::Criterion;
|
||||
use curve25519_dalek::ristretto::RistrettoPoint;
|
||||
use generic_array::arr;
|
||||
use opaque_ke::{
|
||||
group::Group,
|
||||
oprf::{blind_shim, evaluate_shim, finalize_shim},
|
||||
};
|
||||
use rand::{prelude::ThreadRng, thread_rng};
|
||||
use sha2::Sha512;
|
||||
|
||||
fn oprf1(c: &mut Criterion) {
|
||||
let mut csprng: ThreadRng = thread_rng();
|
||||
let input = b"hunter2";
|
||||
|
||||
c.bench_function("blind with Ristretto", move |b| {
|
||||
b.iter(|| {
|
||||
blind_shim::<_, RistrettoPoint, Sha512>(&input[..], &mut csprng).unwrap();
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
fn oprf2(c: &mut Criterion) {
|
||||
let mut csprng: ThreadRng = thread_rng();
|
||||
let input = b"hunter2";
|
||||
|
||||
let (_, alpha) = blind_shim::<_, RistrettoPoint, Sha512>(&input[..], &mut csprng).unwrap();
|
||||
let salt_bytes = arr![
|
||||
u8; 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
|
||||
24, 25, 26, 27, 28, 29, 30, 31, 32,
|
||||
];
|
||||
let salt = RistrettoPoint::from_scalar_slice(&salt_bytes).unwrap();
|
||||
|
||||
c.bench_function("evaluate with Ristretto", move |b| {
|
||||
b.iter(|| {
|
||||
let _beta = evaluate_shim::<RistrettoPoint>(alpha, &salt);
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
fn oprf3(c: &mut Criterion) {
|
||||
let mut csprng: ThreadRng = thread_rng();
|
||||
let input = b"hunter2";
|
||||
|
||||
let (token, alpha) = blind_shim::<_, RistrettoPoint, Sha512>(&input[..], &mut csprng).unwrap();
|
||||
let salt_bytes = arr![
|
||||
u8; 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
|
||||
24, 25, 26, 27, 28, 29, 30, 31, 32,
|
||||
];
|
||||
let salt = RistrettoPoint::from_scalar_slice(&salt_bytes).unwrap();
|
||||
let beta = evaluate_shim::<RistrettoPoint>(alpha, &salt);
|
||||
|
||||
c.bench_function("finalize with Ristretto", move |b| {
|
||||
b.iter(|| {
|
||||
let _res = finalize_shim::<RistrettoPoint, Sha512>(&token, beta).unwrap();
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
criterion_group!(oprf_benches, oprf1, oprf2, oprf3);
|
||||
criterion_main!(oprf_benches);
|
||||
+2
-2
@@ -61,7 +61,7 @@ fn recover_keys_internal<CS: CipherSuite>(
|
||||
Ok(client_static_keypair)
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, Zeroize)]
|
||||
#[derive(Clone, Debug, Eq, Hash, PartialEq, Zeroize)]
|
||||
#[zeroize(drop)]
|
||||
pub(crate) enum InnerEnvelopeMode {
|
||||
Zero = 0,
|
||||
@@ -98,7 +98,7 @@ pub(crate) struct Envelope<CS: CipherSuite> {
|
||||
impl<CS: CipherSuite> Clone for Envelope<CS> {
|
||||
fn clone(&self) -> Self {
|
||||
Self {
|
||||
mode: self.mode,
|
||||
mode: self.mode.clone(),
|
||||
nonce: self.nonce.clone(),
|
||||
hmac: self.hmac.clone(),
|
||||
}
|
||||
|
||||
@@ -86,13 +86,13 @@ impl<D: Hash, G: Group> KeyExchange<D, G> for TripleDH {
|
||||
|
||||
let mut transcript_hasher = D::new()
|
||||
.chain(STR_RFC)
|
||||
.chain(&serialize(&context, 2))
|
||||
.chain(&id_u)
|
||||
.chain(serialize(&context, 2))
|
||||
.chain(id_u)
|
||||
.chain(&serialized_credential_request[..])
|
||||
.chain(&id_s)
|
||||
.chain(id_s)
|
||||
.chain(&l2_bytes[..])
|
||||
.chain(&server_nonce[..])
|
||||
.chain(&server_e_kp.public().to_arr());
|
||||
.chain(server_e_kp.public().to_arr());
|
||||
|
||||
let (session_key, km2, km3) = derive_3dh_keys::<D, G>(
|
||||
TripleDHComponents {
|
||||
@@ -141,12 +141,12 @@ impl<D: Hash, G: Group> KeyExchange<D, G> for TripleDH {
|
||||
) -> Result<(Vec<u8>, Self::KE3Message), ProtocolError> {
|
||||
let mut transcript_hasher = D::new()
|
||||
.chain(STR_RFC)
|
||||
.chain(&serialize(&context, 2))
|
||||
.chain(&id_u)
|
||||
.chain(&serialized_credential_request)
|
||||
.chain(&id_s)
|
||||
.chain(serialize(&context, 2))
|
||||
.chain(id_u)
|
||||
.chain(serialized_credential_request)
|
||||
.chain(id_s)
|
||||
.chain(&l2_component[..])
|
||||
.chain(&ke2_message.to_bytes_without_info_or_mac());
|
||||
.chain(ke2_message.to_bytes_without_info_or_mac());
|
||||
|
||||
let (session_key, km2, km3) = derive_3dh_keys::<D, G>(
|
||||
TripleDHComponents {
|
||||
@@ -170,7 +170,7 @@ impl<D: Hash, G: Group> KeyExchange<D, G> for TripleDH {
|
||||
));
|
||||
}
|
||||
|
||||
transcript_hasher.update(ke2_message.mac.to_vec());
|
||||
transcript_hasher.update(ke2_message.mac);
|
||||
|
||||
let mut client_mac =
|
||||
Hmac::<D>::new_from_slice(&km3).map_err(|_| InternalPakeError::HmacError)?;
|
||||
|
||||
+8
-8
@@ -144,10 +144,10 @@ impl<G: Group + Debug> KeyPair<G> {
|
||||
fn uniform_keypair_strategy() -> BoxedStrategy<Self> {
|
||||
// The no_shrink is because keypairs should be fixed -- shrinking would cause a different
|
||||
// keypair to be generated, which appears to not be very useful.
|
||||
any::<[u8; 32]>()
|
||||
.prop_filter_map("valid random keypair", |seed| {
|
||||
prop::array::uniform32(0_u8..)
|
||||
.prop_map(|seed| {
|
||||
let mut rng = StdRng::from_seed(seed);
|
||||
Some(Self::generate_random(&mut rng))
|
||||
Self::generate_random(&mut rng)
|
||||
})
|
||||
.no_shrink()
|
||||
.boxed()
|
||||
@@ -281,21 +281,21 @@ mod tests {
|
||||
|
||||
proptest! {
|
||||
#[test]
|
||||
fn test_ristretto_check(kp in KeyPair::<RistrettoPoint>::uniform_keypair_strategy()) {
|
||||
fn test_ristretto_check(ref kp in KeyPair::<RistrettoPoint>::uniform_keypair_strategy()) {
|
||||
let pk = kp.public();
|
||||
prop_assert!(KeyPair::<RistrettoPoint>::check_public_key(pk.clone()).is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_ristretto_pub_from_priv(kp in KeyPair::<RistrettoPoint>::uniform_keypair_strategy()) {
|
||||
fn test_ristretto_pub_from_priv(ref kp in KeyPair::<RistrettoPoint>::uniform_keypair_strategy()) {
|
||||
let pk = kp.public();
|
||||
let sk = kp.private();
|
||||
prop_assert_eq!(&KeyPair::<RistrettoPoint>::public_from_private(sk), pk);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_ristretto_dh(kp1 in KeyPair::<RistrettoPoint>::uniform_keypair_strategy(),
|
||||
kp2 in KeyPair::<RistrettoPoint>::uniform_keypair_strategy()) {
|
||||
fn test_ristretto_dh(ref kp1 in KeyPair::<RistrettoPoint>::uniform_keypair_strategy(),
|
||||
ref kp2 in KeyPair::<RistrettoPoint>::uniform_keypair_strategy()) {
|
||||
|
||||
let dh1 = KeyPair::<RistrettoPoint>::diffie_hellman(kp1.public().clone(), kp2.private().clone())?;
|
||||
let dh2 = KeyPair::<RistrettoPoint>::diffie_hellman(kp2.public().clone(), kp1.private().clone())?;
|
||||
@@ -304,7 +304,7 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_private_key_slice(kp in KeyPair::<RistrettoPoint>::uniform_keypair_strategy()) {
|
||||
fn test_private_key_slice(ref kp in KeyPair::<RistrettoPoint>::uniform_keypair_strategy()) {
|
||||
let sk_bytes = kp.private().to_vec();
|
||||
|
||||
let kp2 = KeyPair::<RistrettoPoint>::from_private_key_slice(&sk_bytes)?;
|
||||
|
||||
@@ -747,6 +747,10 @@ compile_error!(
|
||||
please enable one of: u64_backend, u32_backend"
|
||||
);
|
||||
|
||||
#[cfg(test)]
|
||||
#[macro_use]
|
||||
extern crate proptest;
|
||||
|
||||
// Error types
|
||||
pub mod errors;
|
||||
|
||||
|
||||
+3
-3
@@ -71,7 +71,7 @@ fn finalize_after_unblind<G: GroupWithMapToCurve, H: Hash>(
|
||||
let finalize_dst = [STR_VOPRF_FINALIZE, &G::get_context_string(MODE_BASE)].concat();
|
||||
let hash_input = [
|
||||
serialize(input, 2),
|
||||
serialize(&unblinded_element.to_arr().to_vec(), 2),
|
||||
serialize(&unblinded_element.to_arr(), 2),
|
||||
serialize(&finalize_dst, 2),
|
||||
]
|
||||
.concat();
|
||||
@@ -130,7 +130,7 @@ mod tests {
|
||||
RistrettoPoint::from_scalar_slice(GenericArray::from_slice(&oprf_key[..])).unwrap();
|
||||
let res = point * scalar;
|
||||
|
||||
finalize_after_unblind::<RistrettoPoint, sha2::Sha512>(&input, res)
|
||||
finalize_after_unblind::<RistrettoPoint, sha2::Sha512>(input, res)
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -145,7 +145,7 @@ mod tests {
|
||||
let oprf_key = RistrettoPoint::from_scalar_slice(&oprf_key_bytes)?;
|
||||
let beta = evaluate::<RistrettoPoint>(alpha, &oprf_key);
|
||||
let res = finalize::<RistrettoPoint, sha2::Sha512>(&token.data, &token.blind, beta);
|
||||
let res2 = prf(&input[..], &oprf_key.as_bytes());
|
||||
let res2 = prf(&input[..], oprf_key.as_bytes());
|
||||
assert_eq!(res, res2);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ use crate::errors::PakeError;
|
||||
// Corresponds to the I2OSP() function from RFC8017
|
||||
pub(crate) fn i2osp(input: usize, length: usize) -> Vec<u8> {
|
||||
if length <= std::mem::size_of::<usize>() {
|
||||
return (&input.to_be_bytes()[std::mem::size_of::<usize>() - length..]).to_vec();
|
||||
return input.to_be_bytes()[std::mem::size_of::<usize>() - length..].to_vec();
|
||||
}
|
||||
|
||||
let mut output = vec![0u8; length];
|
||||
|
||||
+51
-47
@@ -104,12 +104,12 @@ fn registration_request_roundtrip() {
|
||||
let identity = RistrettoPoint::identity();
|
||||
let identity_bytes = identity.to_arr().to_vec();
|
||||
|
||||
assert!(
|
||||
match RegistrationRequest::<Default>::deserialize(identity_bytes.as_slice()) {
|
||||
Err(ProtocolError::VerificationError(PakeError::IdentityGroupElementError)) => true,
|
||||
_ => false,
|
||||
}
|
||||
);
|
||||
assert!(matches!(
|
||||
RegistrationRequest::<Default>::deserialize(identity_bytes.as_slice()),
|
||||
Err(ProtocolError::VerificationError(
|
||||
PakeError::IdentityGroupElementError
|
||||
))
|
||||
));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -122,7 +122,7 @@ fn registration_response_roundtrip() {
|
||||
|
||||
let mut input = Vec::new();
|
||||
input.extend_from_slice(beta_bytes.as_slice());
|
||||
input.extend_from_slice(&pubkey_bytes.as_slice());
|
||||
input.extend_from_slice(pubkey_bytes.as_slice());
|
||||
|
||||
let r2 = RegistrationResponse::<Default>::deserialize(input.as_slice()).unwrap();
|
||||
let r2_bytes = r2.serialize();
|
||||
@@ -132,12 +132,14 @@ fn registration_response_roundtrip() {
|
||||
let identity = RistrettoPoint::identity();
|
||||
let identity_bytes = identity.to_arr().to_vec();
|
||||
|
||||
assert!(match RegistrationResponse::<Default>::deserialize(
|
||||
&[identity_bytes, pubkey_bytes.to_vec()].concat()
|
||||
) {
|
||||
Err(ProtocolError::VerificationError(PakeError::IdentityGroupElementError)) => true,
|
||||
_ => false,
|
||||
});
|
||||
assert!(matches!(
|
||||
RegistrationResponse::<Default>::deserialize(
|
||||
&[identity_bytes, pubkey_bytes.to_vec()].concat()
|
||||
),
|
||||
Err(ProtocolError::VerificationError(
|
||||
PakeError::IdentityGroupElementError
|
||||
))
|
||||
));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -179,7 +181,7 @@ fn credential_request_roundtrip() {
|
||||
let mut client_nonce = vec![0u8; NonceLen::to_usize()];
|
||||
rng.fill_bytes(&mut client_nonce);
|
||||
|
||||
let ke1m: Vec<u8> = [&client_nonce[..], &client_e_kp.public()].concat();
|
||||
let ke1m: Vec<u8> = [&client_nonce[..], client_e_kp.public()].concat();
|
||||
|
||||
let mut input = Vec::new();
|
||||
input.extend_from_slice(&alpha_bytes);
|
||||
@@ -193,12 +195,12 @@ fn credential_request_roundtrip() {
|
||||
let identity = RistrettoPoint::identity();
|
||||
let identity_bytes = identity.to_arr().to_vec();
|
||||
|
||||
assert!(match CredentialRequest::<Default>::deserialize(
|
||||
&[identity_bytes, ke1m.to_vec()].concat()
|
||||
) {
|
||||
Err(ProtocolError::VerificationError(PakeError::IdentityGroupElementError)) => true,
|
||||
_ => false,
|
||||
});
|
||||
assert!(matches!(
|
||||
CredentialRequest::<Default>::deserialize(&[identity_bytes, ke1m.to_vec()].concat()),
|
||||
Err(ProtocolError::VerificationError(
|
||||
PakeError::IdentityGroupElementError
|
||||
))
|
||||
));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -221,7 +223,7 @@ fn credential_response_roundtrip() {
|
||||
let mut server_nonce = vec![0u8; NonceLen::to_usize()];
|
||||
rng.fill_bytes(&mut server_nonce);
|
||||
|
||||
let ke2m: Vec<u8> = [&server_nonce[..], &server_e_kp.public(), &mac[..]].concat();
|
||||
let ke2m: Vec<u8> = [&server_nonce[..], server_e_kp.public(), &mac[..]].concat();
|
||||
|
||||
let mut input = Vec::new();
|
||||
input.extend_from_slice(pt_bytes.as_slice());
|
||||
@@ -237,18 +239,20 @@ fn credential_response_roundtrip() {
|
||||
let identity = RistrettoPoint::identity();
|
||||
let identity_bytes = identity.to_arr().to_vec();
|
||||
|
||||
assert!(match CredentialResponse::<Default>::deserialize(
|
||||
&[
|
||||
identity_bytes,
|
||||
masking_nonce.to_vec(),
|
||||
masked_response,
|
||||
ke2m.to_vec()
|
||||
]
|
||||
.concat()
|
||||
) {
|
||||
Err(ProtocolError::VerificationError(PakeError::IdentityGroupElementError)) => true,
|
||||
_ => false,
|
||||
});
|
||||
assert!(matches!(
|
||||
CredentialResponse::<Default>::deserialize(
|
||||
&[
|
||||
identity_bytes,
|
||||
masking_nonce.to_vec(),
|
||||
masked_response,
|
||||
ke2m.to_vec()
|
||||
]
|
||||
.concat()
|
||||
),
|
||||
Err(ProtocolError::VerificationError(
|
||||
PakeError::IdentityGroupElementError
|
||||
))
|
||||
));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -298,7 +302,7 @@ fn ke1_message_roundtrip() {
|
||||
let mut client_nonce = vec![0u8; NonceLen::to_usize()];
|
||||
rng.fill_bytes(&mut client_nonce);
|
||||
|
||||
let ke1m: Vec<u8> = [&client_nonce[..], &client_e_kp.public()].concat();
|
||||
let ke1m: Vec<u8> = [&client_nonce[..], client_e_kp.public()].concat();
|
||||
let reg = <TripleDH as KeyExchange<sha2::Sha512, RistrettoPoint>>::KE1Message::from_bytes::<
|
||||
Default,
|
||||
>(&ke1m[..])
|
||||
@@ -317,7 +321,7 @@ fn ke2_message_roundtrip() {
|
||||
let mut server_nonce = vec![0u8; NonceLen::to_usize()];
|
||||
rng.fill_bytes(&mut server_nonce);
|
||||
|
||||
let ke2m: Vec<u8> = [&server_nonce[..], &server_e_kp.public(), &mac[..]].concat();
|
||||
let ke2m: Vec<u8> = [&server_nonce[..], server_e_kp.public(), &mac[..]].concat();
|
||||
|
||||
let reg = <TripleDH as KeyExchange<sha2::Sha512, RistrettoPoint>>::KE2Message::from_bytes::<
|
||||
Default,
|
||||
@@ -346,57 +350,57 @@ fn ke3_message_roundtrip() {
|
||||
proptest! {
|
||||
|
||||
#[test]
|
||||
fn test_i2osp_os2ip(bytes in vec(any::<u8>(), 0..std::mem::size_of::<usize>())) {
|
||||
assert_eq!(i2osp(os2ip(&bytes)?, bytes.len()), bytes);
|
||||
fn test_i2osp_os2ip(ref bytes in vec(prop::num::u8::ANY, 0..std::mem::size_of::<usize>())) {
|
||||
assert_eq!(&i2osp(os2ip(bytes)?, bytes.len()), bytes);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_nocrash_registration_request(bytes in vec(any::<u8>(), 0..200)) {
|
||||
fn test_nocrash_registration_request(ref bytes in vec(prop::num::u8::ANY, 0..200)) {
|
||||
RegistrationRequest::<Default>::deserialize(&bytes[..]).map_or(true, |_| true);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_nocrash_registration_response(bytes in vec(any::<u8>(), 0..200)) {
|
||||
fn test_nocrash_registration_response(ref bytes in vec(prop::num::u8::ANY, 0..200)) {
|
||||
RegistrationResponse::<Default>::deserialize(&bytes[..]).map_or(true, |_| true);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_nocrash_registration_upload(bytes in vec(any::<u8>(), 0..200)) {
|
||||
fn test_nocrash_registration_upload(ref bytes in vec(prop::num::u8::ANY, 0..200)) {
|
||||
RegistrationUpload::<Default>::deserialize(&bytes[..]).map_or(true, |_| true);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_nocrash_credential_request(bytes in vec(any::<u8>(), 0..500)) {
|
||||
fn test_nocrash_credential_request(ref bytes in vec(prop::num::u8::ANY, 0..500)) {
|
||||
CredentialRequest::<Default>::deserialize(&bytes[..]).map_or(true, |_| true);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_nocrash_credential_response(bytes in vec(any::<u8>(), 0..500)) {
|
||||
fn test_nocrash_credential_response(ref bytes in vec(prop::num::u8::ANY, 0..500)) {
|
||||
CredentialResponse::<Default>::deserialize(&bytes[..]).map_or(true, |_| true);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_nocrash_credential_finalization(bytes in vec(any::<u8>(), 0..500)) {
|
||||
fn test_nocrash_credential_finalization(ref bytes in vec(prop::num::u8::ANY, 0..500)) {
|
||||
CredentialFinalization::<Default>::deserialize(&bytes[..]).map_or(true, |_| true);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_nocrash_client_registration(bytes in vec(any::<u8>(), 0..700)) {
|
||||
fn test_nocrash_client_registration(ref bytes in vec(prop::num::u8::ANY, 0..700)) {
|
||||
ClientRegistration::<Default>::deserialize(&bytes[..]).map_or(true, |_| true);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_nocrash_server_registration(bytes in vec(any::<u8>(), 0..700)) {
|
||||
fn test_nocrash_server_registration(ref bytes in vec(prop::num::u8::ANY, 0..700)) {
|
||||
ServerRegistration::<Default>::deserialize(&bytes[..]).map_or(true, |_| true);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_nocrash_client_login(bytes in vec(any::<u8>(), 0..700)) {
|
||||
fn test_nocrash_client_login(ref bytes in vec(prop::num::u8::ANY, 0..700)) {
|
||||
ClientLogin::<Default>::deserialize(&bytes[..]).map_or(true, |_| true);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_nocrash_server_login(bytes in vec(any::<u8>(), 0..700)) {
|
||||
fn test_nocrash_server_login(ref bytes in vec(prop::num::u8::ANY, 0..700)) {
|
||||
ServerLogin::<Default>::deserialize(&bytes[..]).map_or(true, |_| true);
|
||||
}
|
||||
|
||||
|
||||
+41
-41
@@ -111,45 +111,43 @@ static TEST_VECTOR: &str = r#"
|
||||
"#;
|
||||
|
||||
fn decode(values: &Value, key: &str) -> Option<Vec<u8>> {
|
||||
values[key]
|
||||
.as_str()
|
||||
.and_then(|s| hex::decode(&s.to_string()).ok())
|
||||
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(),
|
||||
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(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -550,7 +548,7 @@ fn test_registration_upload() -> Result<(), ProtocolError> {
|
||||
);
|
||||
assert_eq!(
|
||||
hex::encode(parameters.export_key),
|
||||
hex::encode(result.export_key.to_vec())
|
||||
hex::encode(result.export_key)
|
||||
);
|
||||
|
||||
Ok(())
|
||||
@@ -665,7 +663,7 @@ fn test_credential_finalization() -> Result<(), ProtocolError> {
|
||||
|
||||
assert_eq!(
|
||||
hex::encode(¶meters.server_s_pk),
|
||||
hex::encode(&client_login_finish_result.server_s_pk.to_arr().to_vec())
|
||||
hex::encode(client_login_finish_result.server_s_pk.to_arr())
|
||||
);
|
||||
assert_eq!(
|
||||
hex::encode(¶meters.session_key),
|
||||
@@ -758,10 +756,12 @@ fn test_complete_flow(
|
||||
hex::encode(client_login_finish_result.export_key)
|
||||
);
|
||||
} else {
|
||||
assert!(match client_login_result {
|
||||
Err(ProtocolError::VerificationError(PakeError::InvalidLoginError)) => true,
|
||||
_ => false,
|
||||
});
|
||||
assert!(matches!(
|
||||
client_login_result,
|
||||
Err(ProtocolError::VerificationError(
|
||||
PakeError::InvalidLoginError
|
||||
))
|
||||
));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
||||
@@ -48,7 +48,7 @@ impl RngCore for CycleRng {
|
||||
#[inline]
|
||||
fn fill_bytes(&mut self, dest: &mut [u8]) {
|
||||
let len = min(self.v.len(), dest.len());
|
||||
(&mut dest[..len]).copy_from_slice(&self.v[..len]);
|
||||
dest[..len].copy_from_slice(&self.v[..len]);
|
||||
rotate_left(&mut self.v, len);
|
||||
}
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ impl CipherSuite for Ristretto255Sha512NoSlowHash {
|
||||
type SlowHash = NoOpHash;
|
||||
}
|
||||
|
||||
#[derive(PartialEq)]
|
||||
#[derive(PartialEq, Eq)]
|
||||
pub enum EnvelopeMode {
|
||||
Base,
|
||||
CustomIdentifier,
|
||||
@@ -421,11 +421,11 @@ fn rfc_to_json(input: &str) -> String {
|
||||
json.push(format!(" \"{}\": \"{}", key, val));
|
||||
} else {
|
||||
let s = line.trim().to_string();
|
||||
if s.contains("~") || s.contains("#") {
|
||||
if s.contains('~') || s.contains('#') {
|
||||
// Ignore comment lines
|
||||
continue;
|
||||
}
|
||||
if s.len() > 0 {
|
||||
if !s.is_empty() {
|
||||
json.push(s);
|
||||
}
|
||||
}
|
||||
@@ -435,9 +435,7 @@ fn rfc_to_json(input: &str) -> String {
|
||||
}
|
||||
|
||||
fn decode(values: &Value, key: &str) -> Option<Vec<u8>> {
|
||||
values[key]
|
||||
.as_str()
|
||||
.and_then(|s| hex::decode(&s.to_string()).ok())
|
||||
values[key].as_str().and_then(|s| hex::decode(s).ok())
|
||||
}
|
||||
|
||||
fn populate_test_vectors(values: &Value) -> TestVectorParameters {
|
||||
@@ -573,7 +571,7 @@ fn test_registration_upload() -> Result<(), ProtocolError> {
|
||||
);
|
||||
assert_eq!(
|
||||
hex::encode(parameters.export_key),
|
||||
hex::encode(result.export_key.to_vec())
|
||||
hex::encode(result.export_key)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -45,19 +45,17 @@ static OPRF_RISTRETTO255_SHA512: &[&str] = &[
|
||||
];
|
||||
|
||||
fn decode(values: &Value, key: &str) -> Option<Vec<u8>> {
|
||||
values[key]
|
||||
.as_str()
|
||||
.and_then(|s| hex::decode(&s.to_string()).ok())
|
||||
values[key].as_str().and_then(|s| hex::decode(s).ok())
|
||||
}
|
||||
|
||||
fn populate_test_vectors(values: &Value) -> VOPRFTestVectorParameters {
|
||||
VOPRFTestVectorParameters {
|
||||
sksm: decode(&values, "sksm").unwrap(),
|
||||
input: decode(&values, "input").unwrap(),
|
||||
blind: decode(&values, "blind").unwrap(),
|
||||
blinded_element: decode(&values, "blinded_element").unwrap(),
|
||||
evaluation_element: decode(&values, "evaluation_element").unwrap(),
|
||||
output: decode(&values, "output").unwrap(),
|
||||
sksm: decode(values, "sksm").unwrap(),
|
||||
input: decode(values, "input").unwrap(),
|
||||
blind: decode(values, "blind").unwrap(),
|
||||
blinded_element: decode(values, "blinded_element").unwrap(),
|
||||
evaluation_element: decode(values, "evaluation_element").unwrap(),
|
||||
output: decode(values, "output").unwrap(),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user