no_std support (#225)

* No std implementation

* Run tests with std

* Adding wasm32-unknown-unknown target

Co-authored-by: Kevin Lewi <[email protected]>
This commit is contained in:
daxpedda
2021-08-11 21:25:07 -07:00
committed by GitHub
co-authored by Kevin Lewi
parent 88673d8e05
commit 8a7bcf9097
23 changed files with 179 additions and 128 deletions
+33 -20
View File
@@ -41,6 +41,12 @@ jobs:
command: test command: test
args: --no-default-features --features ${{ matrix.backend_feature }} args: --no-default-features --features ${{ matrix.backend_feature }}
- name: Run cargo test with std
uses: actions-rs/cargo@v1
with:
command: test
args: --no-default-features --features std --features ${{ matrix.backend_feature }}
cross-test: cross-test:
name: Test on ${{ matrix.target }} (using cross) name: Test on ${{ matrix.target }} (using cross)
runs-on: ubuntu-latest runs-on: ubuntu-latest
@@ -61,10 +67,10 @@ jobs:
# Note: just use `cross` as you would `cargo`, but always # Note: just use `cross` as you would `cargo`, but always
# pass the `--target=${{ matrix.target }}` arg. (Yes, really). # pass the `--target=${{ matrix.target }}` arg. (Yes, really).
- run: cross test --verbose --target=${{ matrix.target }} --no-default-features --features ${{ matrix.backend_feature }} - run: cross test --verbose --target=${{ matrix.target }} --no-default-features --features ${{ matrix.backend_feature }}
- run: cross test --verbose --target=${{ matrix.target }} --no-default-features --features std --features ${{ matrix.backend_feature }}
feature-test:
slow-hash-test: name: Test on ${{ matrix.target }} with ${{ matrix.frontend_feature }}
name: Test on ${{ matrix.target }} with slow hash
runs-on: ubuntu-latest runs-on: ubuntu-latest
strategy: strategy:
fail-fast: false fail-fast: false
@@ -73,26 +79,14 @@ jobs:
- u64_backend - u64_backend
- u32_backend - u32_backend
- p256,u64_backend - p256,u64_backend
frontend_feature:
- slow-hash
- serialize
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
- uses: hecrj/setup-rust-action@v1 - uses: hecrj/setup-rust-action@v1
- run: cargo test --verbose --features slow-hash --no-default-features --features ${{ matrix.backend_feature }} - run: cargo test --verbose --features ${{ matrix.frontend_feature }} --no-default-features --features ${{ matrix.backend_feature }}
- run: cargo test --verbose --features ${{ matrix.frontend_feature }},std --no-default-features --features ${{ matrix.backend_feature }}
serde-test:
name: Test on ${{ matrix.target }} with serde support
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
backend_feature:
- u64_backend
- u32_backend
- p256,u64_backend
steps:
- uses: actions/checkout@v2
- uses: hecrj/setup-rust-action@v1
- run: cargo test --verbose --features serialize --no-default-features --features ${{ matrix.backend_feature }}
simple-login-test: simple-login-test:
runs-on: ubuntu-latest runs-on: ubuntu-latest
@@ -142,6 +136,25 @@ jobs:
- name: Run expect (which then runs cargo run) - name: Run expect (which then runs cargo run)
run: expect -f scripts/digital_locker.exp run: expect -f scripts/digital_locker.exp
build-no-std:
name: Build with no-std on ${{ matrix.target }}
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
target:
# for wasm
- wasm32-unknown-unknown
backend_feature:
- u64_backend
- u32_backend
- p256,u64_backend
steps:
- uses: actions/checkout@v2
- uses: hecrj/setup-rust-action@v1
- run: rustup target add ${{ matrix.target }}
- run: cargo build --verbose --target=${{ matrix.target }} --no-default-features --features ${{ matrix.backend_feature }}
benches: benches:
name: cargo bench compilation name: cargo bench compilation
runs-on: ubuntu-latest runs-on: ubuntu-latest
+5 -3
View File
@@ -3,6 +3,7 @@ name = "opaque-ke"
version = "2.0.0-pre.1" version = "2.0.0-pre.1"
repository = "https://github.com/novifinancial/opaque-ke" repository = "https://github.com/novifinancial/opaque-ke"
keywords = ["cryptography", "crypto", "opaque", "passwords", "authentication"] keywords = ["cryptography", "crypto", "opaque", "passwords", "authentication"]
categories = ["no-std"]
description = "An implementation of the OPAQUE password-authenticated key exchange protocol" description = "An implementation of the OPAQUE password-authenticated key exchange protocol"
authors = ["Kevin Lewi <[email protected]>", "François Garillot <[email protected]>"] authors = ["Kevin Lewi <[email protected]>", "François Garillot <[email protected]>"]
license = "MIT" license = "MIT"
@@ -16,17 +17,19 @@ p256 = ["num-bigint", "num-integer", "num-traits", "once_cell", "p256_"]
bench = [] bench = []
u64_backend = ["curve25519-dalek/u64_backend"] u64_backend = ["curve25519-dalek/u64_backend"]
u32_backend = ["curve25519-dalek/u32_backend"] u32_backend = ["curve25519-dalek/u32_backend"]
std = ["curve25519-dalek/std"]
serialize = ["serde", "base64", "generic-array/serde", "curve25519-dalek/serde"] serialize = ["serde", "base64", "generic-array/serde", "curve25519-dalek/serde"]
[dependencies] [dependencies]
argon2 = { version = "0.2", optional = true } argon2 = { version = "0.2", optional = true }
base64 = { version = "0.13", optional = true } base64 = { version = "0.13", optional = true }
constant_time_eq = "0.1" constant_time_eq = "0.1"
curve25519-dalek = { version = "3", default-features = false, features = ["std"] } curve25519-dalek = { version = "3", default-features = false }
digest = "0.9" digest = "0.9"
displaydoc = "0.2" displaydoc = "0.2"
generic-array = "0.14" generic-array = "0.14"
generic-bytes = { version = "0.1" } generic-bytes = { version = "0.1" }
getrandom = { version = "0.2", features = ["js"] }
hkdf = "0.11" hkdf = "0.11"
hmac = "0.11" hmac = "0.11"
num-bigint = { version = "0.4", optional = true } num-bigint = { version = "0.4", optional = true }
@@ -34,14 +37,13 @@ num-integer = { version = "0.1", optional = true }
num-traits = { version = "0.2", optional = true } num-traits = { version = "0.2", optional = true }
once_cell = { version = "1", optional = true } once_cell = { version = "1", optional = true }
p256_ = { package = "p256", version = "0.9", optional = true } p256_ = { package = "p256", version = "0.9", optional = true }
rand = "0.8" rand = { version = "0.8", default-features = false }
serde = { version = "1", features = ["derive"], optional = true } serde = { version = "1", features = ["derive"], optional = true }
subtle = { version = "2.3", default-features = false } subtle = { version = "2.3", default-features = false }
thiserror = "1" thiserror = "1"
zeroize = { version = "1", features = ["zeroize_derive"] } zeroize = { version = "1", features = ["zeroize_derive"] }
[dev-dependencies] [dev-dependencies]
anyhow = "1"
base64 = "0.13" base64 = "0.13"
bincode = "1" bincode = "1"
chacha20poly1305 = "0.8" chacha20poly1305 = "0.8"
+3 -1
View File
@@ -11,13 +11,15 @@ use crate::{
keypair::{KeyPair, PrivateKey, PublicKey}, keypair::{KeyPair, PrivateKey, PublicKey},
opaque::{bytestrings_from_identifiers, Identifiers}, opaque::{bytestrings_from_identifiers, Identifiers},
}; };
use alloc::vec;
use alloc::vec::Vec;
use core::convert::TryFrom;
use digest::Digest; use digest::Digest;
use generic_array::{typenum::Unsigned, GenericArray}; use generic_array::{typenum::Unsigned, GenericArray};
use generic_bytes::SizedBytes; use generic_bytes::SizedBytes;
use hkdf::Hkdf; use hkdf::Hkdf;
use hmac::{Hmac, Mac, NewMac}; use hmac::{Hmac, Mac, NewMac};
use rand::{CryptoRng, RngCore}; use rand::{CryptoRng, RngCore};
use std::convert::TryFrom;
use zeroize::Zeroize; use zeroize::Zeroize;
// Constant string used as salt for HKDF computation // Constant string used as salt for HKDF computation
+11 -7
View File
@@ -4,9 +4,10 @@
// LICENSE file in the root directory of this source tree. // LICENSE file in the root directory of this source tree.
//! A list of error types which are produced during an execution of the protocol //! A list of error types which are produced during an execution of the protocol
use std::convert::Infallible; use core::convert::Infallible;
use core::fmt::Debug;
#[cfg(feature = "std")]
use std::error::Error; use std::error::Error;
use std::fmt::Debug;
use displaydoc::Display; use displaydoc::Display;
@@ -61,7 +62,7 @@ pub enum InternalPakeError<T = Infallible> {
} }
impl<T: Debug> Debug for InternalPakeError<T> { impl<T: Debug> Debug for InternalPakeError<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self { match self {
Self::Custom(custom) => f.debug_tuple("InvalidByteSequence").field(custom).finish(), Self::Custom(custom) => f.debug_tuple("InvalidByteSequence").field(custom).finish(),
Self::InvalidByteSequence => f.debug_tuple("InvalidByteSequence").finish(), Self::InvalidByteSequence => f.debug_tuple("InvalidByteSequence").finish(),
@@ -98,6 +99,7 @@ impl<T: Debug> Debug for InternalPakeError<T> {
} }
} }
#[cfg(feature = "std")]
impl<T: Error> Error for InternalPakeError<T> {} impl<T: Error> Error for InternalPakeError<T> {}
impl InternalPakeError { impl InternalPakeError {
@@ -157,7 +159,7 @@ pub enum PakeError<T = Infallible> {
} }
impl<T: Debug> Debug for PakeError<T> { impl<T: Debug> Debug for PakeError<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self { match self {
Self::CryptoError(internal_pake_error) => f Self::CryptoError(internal_pake_error) => f
.debug_tuple("CryptoError") .debug_tuple("CryptoError")
@@ -177,6 +179,7 @@ impl<T: Debug> Debug for PakeError<T> {
} }
} }
#[cfg(feature = "std")]
impl<T: Error> Error for PakeError<T> {} impl<T: Error> Error for PakeError<T> {}
// This is meant to express future(ly) non-trivial ways of converting the // This is meant to express future(ly) non-trivial ways of converting the
@@ -230,7 +233,7 @@ pub enum ProtocolError<T = Infallible> {
} }
impl<T: Debug> Debug for ProtocolError<T> { impl<T: Debug> Debug for ProtocolError<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self { match self {
Self::VerificationError(pake_error) => f Self::VerificationError(pake_error) => f
.debug_tuple("VerificationError") .debug_tuple("VerificationError")
@@ -247,6 +250,7 @@ impl<T: Debug> Debug for ProtocolError<T> {
} }
} }
#[cfg(feature = "std")]
impl<T: Error> Error for ProtocolError<T> {} impl<T: Error> Error for ProtocolError<T> {}
// This is meant to express future(ly) non-trivial ways of converting the // This is meant to express future(ly) non-trivial ways of converting the
@@ -268,8 +272,8 @@ impl<T> From<InternalPakeError<T>> for ProtocolError<T> {
// See https://github.com/rust-lang/rust/issues/64715 and remove this when // See https://github.com/rust-lang/rust/issues/64715 and remove this when
// merged, and https://github.com/dtolnay/thiserror/issues/62 for why this // merged, and https://github.com/dtolnay/thiserror/issues/62 for why this
// comes up in our doc tests. // comes up in our doc tests.
impl<T> From<::std::convert::Infallible> for ProtocolError<T> { impl<T> From<::core::convert::Infallible> for ProtocolError<T> {
fn from(_: ::std::convert::Infallible) -> Self { fn from(_: ::core::convert::Infallible) -> Self {
unreachable!() unreachable!()
} }
} }
+3 -2
View File
@@ -6,6 +6,7 @@
use crate::errors::{InternalPakeError, ProtocolError}; use crate::errors::{InternalPakeError, ProtocolError};
use crate::hash::Hash; use crate::hash::Hash;
use crate::serialization::i2osp; use crate::serialization::i2osp;
use alloc::vec::Vec;
use digest::{BlockInput, Digest}; use digest::{BlockInput, Digest};
use generic_array::typenum::Unsigned; use generic_array::typenum::Unsigned;
@@ -42,7 +43,7 @@ pub fn expand_message_xmd<H: Hash>(
let l_i_b_str = i2osp(len_in_bytes, 2)?; let l_i_b_str = i2osp(len_in_bytes, 2)?;
let msg_prime = [&z_pad, msg, &l_i_b_str, &i2osp(0, 1)?, &dst_prime].concat(); let msg_prime = [&z_pad, msg, &l_i_b_str, &i2osp(0, 1)?, &dst_prime].concat();
let mut b: Vec<Vec<u8>> = vec![H::digest(&msg_prime).to_vec()]; // b[0] let mut b: Vec<Vec<u8>> = alloc::vec![H::digest(&msg_prime).to_vec()]; // b[0]
let mut h = H::new(); let mut h = H::new();
h.update(&b[0]); h.update(&b[0]);
@@ -76,7 +77,7 @@ mod tests {
#[test] #[test]
fn test_expand_message_xmd() { fn test_expand_message_xmd() {
// Test vectors taken from Section K.1 of https://www.ietf.org/archive/id/draft-irtf-cfrg-hash-to-curve-10.txt // Test vectors taken from Section K.1 of https://www.ietf.org/archive/id/draft-irtf-cfrg-hash-to-curve-10.txt
let test_vectors: Vec<Params> = vec![ let test_vectors: alloc::vec::Vec<Params> = alloc::vec![
Params { Params {
msg: "", msg: "",
len_in_bytes: 0x20, len_in_bytes: 0x20,
+2 -2
View File
@@ -14,9 +14,9 @@ mod x25519;
use crate::errors::{InternalPakeError, ProtocolError}; use crate::errors::{InternalPakeError, ProtocolError};
use crate::hash::Hash; use crate::hash::Hash;
use core::ops::Mul;
use generic_array::{ArrayLength, GenericArray}; use generic_array::{ArrayLength, GenericArray};
use rand::{CryptoRng, RngCore}; use rand::{CryptoRng, RngCore};
use std::ops::Mul;
use zeroize::Zeroize; use zeroize::Zeroize;
/// A prime-order subgroup of a base field (EC, prime-order field ...). This /// A prime-order subgroup of a base field (EC, prime-order field ...). This
@@ -34,7 +34,7 @@ pub trait Group: Copy + Sized + for<'a> Mul<&'a <Self as Group>::Scalar, Output
/// Generates the contextString parameter as defined in /// Generates the contextString parameter as defined in
/// <https://www.ietf.org/archive/id/draft-irtf-cfrg-voprf-05.txt> /// <https://www.ietf.org/archive/id/draft-irtf-cfrg-voprf-05.txt>
fn get_context_string(mode: u8) -> Result<Vec<u8>, ProtocolError> { fn get_context_string(mode: u8) -> Result<alloc::vec::Vec<u8>, ProtocolError> {
use crate::serialization::i2osp; use crate::serialization::i2osp;
Ok([i2osp(mode as usize, 1)?, i2osp(Self::SUITE_ID, 2)?].concat()) Ok([i2osp(mode as usize, 1)?, i2osp(Self::SUITE_ID, 2)?].concat())
+3 -3
View File
@@ -11,6 +11,8 @@
use super::Group; use super::Group;
use crate::errors::{InternalPakeError, ProtocolError}; use crate::errors::{InternalPakeError, ProtocolError};
use crate::hash::Hash; use crate::hash::Hash;
use core::ops::{Add, Div, Mul, Neg, Sub};
use core::str::FromStr;
use generic_array::typenum::{U32, U33}; use generic_array::typenum::{U32, U33};
use generic_array::{ArrayLength, GenericArray}; use generic_array::{ArrayLength, GenericArray};
use num_bigint::{BigInt, Sign}; use num_bigint::{BigInt, Sign};
@@ -24,8 +26,6 @@ use p256_::elliptic_curve::subtle::ConstantTimeEq;
use p256_::elliptic_curve::Field; use p256_::elliptic_curve::Field;
use p256_::{AffinePoint, EncodedPoint, ProjectivePoint}; use p256_::{AffinePoint, EncodedPoint, ProjectivePoint};
use rand::{CryptoRng, RngCore}; use rand::{CryptoRng, RngCore};
use std::ops::{Add, Div, Mul, Neg, Sub};
use std::str::FromStr;
// https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-11#section-8.2 // https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-11#section-8.2
// `p: 2^256 - 2^224 + 2^192 + 2^96 - 1` // `p: 2^256 - 2^224 + 2^192 + 2^96 - 1`
@@ -411,7 +411,7 @@ mod tests {
#[test] #[test]
fn map_to_curve_simple_swu() { fn map_to_curve_simple_swu() {
// Test vectors taken from https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-11#appendix-J.1.1 // Test vectors taken from https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-11#appendix-J.1.1
let test_vectors: Vec<Params> = vec![ let test_vectors = alloc::vec![
Params { Params {
msg: "", msg: "",
px: "2c15230b26dbc6fc9a37051158c95b79656e17a1a920b11394ca91c44247d3e4", px: "2c15230b26dbc6fc9a37051158c95b79656e17a1a920b11394ca91c44247d3e4",
+1 -1
View File
@@ -6,6 +6,7 @@
use super::Group; use super::Group;
use crate::errors::{InternalPakeError, ProtocolError}; use crate::errors::{InternalPakeError, ProtocolError};
use crate::hash::Hash; use crate::hash::Hash;
use core::convert::TryInto;
use curve25519_dalek::{ use curve25519_dalek::{
constants::RISTRETTO_BASEPOINT_POINT, constants::RISTRETTO_BASEPOINT_POINT,
ristretto::{CompressedRistretto, RistrettoPoint}, ristretto::{CompressedRistretto, RistrettoPoint},
@@ -14,7 +15,6 @@ use curve25519_dalek::{
}; };
use generic_array::{typenum::U32, GenericArray}; use generic_array::{typenum::U32, GenericArray};
use rand::{CryptoRng, RngCore}; use rand::{CryptoRng, RngCore};
use std::convert::TryInto;
use subtle::ConstantTimeEq; use subtle::ConstantTimeEq;
/// The implementation of such a subgroup for Ristretto /// The implementation of such a subgroup for Ristretto
+16 -16
View File
@@ -5,10 +5,10 @@
macro_rules! impl_debug_eq_hash_for { macro_rules! impl_debug_eq_hash_for {
(struct $name:ident$(<$($gen:ident$(: $bound:tt)?),+$(,)?>)?, [$field1:ident$(, $field2:ident)*$(,)?]$(, )?$([$($type:ty),+$(,)?]$(,)?)?) => { (struct $name:ident$(<$($gen:ident$(: $bound:tt)?),+$(,)?>)?, [$field1:ident$(, $field2:ident)*$(,)?]$(, )?$([$($type:ty),+$(,)?]$(,)?)?) => {
impl$(<$($gen$(: $bound)?),+>)? std::fmt::Debug for $name$(<$($gen),+>)? impl$(<$($gen$(: $bound)?),+>)? core::fmt::Debug for $name$(<$($gen),+>)?
$(where $($type: std::fmt::Debug,)+)? $(where $($type: core::fmt::Debug,)+)?
{ {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("$name") f.debug_struct("$name")
.field("$field1", &self.$field1) .field("$field1", &self.$field1)
$(.field("$field2", &self.$field2))* $(.field("$field2", &self.$field2))*
@@ -29,20 +29,20 @@ macro_rules! impl_debug_eq_hash_for {
} }
} }
impl$(<$($gen$(: $bound)?),+>)? std::hash::Hash for $name$(<$($gen),+>)? impl$(<$($gen$(: $bound)?),+>)? core::hash::Hash for $name$(<$($gen),+>)?
$(where $($type: std::hash::Hash,)+)? $(where $($type: core::hash::Hash,)+)?
{ {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) { fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
std::hash::Hash::hash(&self.$field1, state); core::hash::Hash::hash(&self.$field1, state);
$(std::hash::Hash::hash(&self.$field2, state);)* $(core::hash::Hash::hash(&self.$field2, state);)*
} }
} }
}; };
(tuple $name:ident$(<$($gen:ident$(: $bound:tt)?),+$(,)?>)?, [$field1:tt$(, $field2:tt)*$(,)?]$(, )?$([$($type:ty),+$(,)?]$(,)?)?) => { (tuple $name:ident$(<$($gen:ident$(: $bound:tt)?),+$(,)?>)?, [$field1:tt$(, $field2:tt)*$(,)?]$(, )?$([$($type:ty),+$(,)?]$(,)?)?) => {
impl$(<$($gen$(: $bound)?),+>)? std::fmt::Debug for $name$(<$($gen),+>)? impl$(<$($gen$(: $bound)?),+>)? core::fmt::Debug for $name$(<$($gen),+>)?
$(where $($type: std::fmt::Debug,)+)? $(where $($type: core::fmt::Debug,)+)?
{ {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_tuple("$name") f.debug_tuple("$name")
.field(&self.$field1) .field(&self.$field1)
$(.field(&self.$field2))* $(.field(&self.$field2))*
@@ -63,12 +63,12 @@ macro_rules! impl_debug_eq_hash_for {
} }
} }
impl$(<$($gen$(: $bound)?),+>)? std::hash::Hash for $name$(<$($gen),+>)? impl$(<$($gen$(: $bound)?),+>)? core::hash::Hash for $name$(<$($gen),+>)?
$(where $($type: std::hash::Hash,)+)? $(where $($type: core::hash::Hash,)+)?
{ {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) { fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
std::hash::Hash::hash(&self.$field1, state); core::hash::Hash::hash(&self.$field1, state);
$(std::hash::Hash::hash(&self.$field2, state);)* $(core::hash::Hash::hash(&self.$field2, state);)*
} }
} }
}; };
+1
View File
@@ -10,6 +10,7 @@ use crate::{
hash::Hash, hash::Hash,
keypair::{PrivateKey, PublicKey, SecretKey}, keypair::{PrivateKey, PublicKey, SecretKey},
}; };
use alloc::vec::Vec;
use rand::{CryptoRng, RngCore}; use rand::{CryptoRng, RngCore};
use zeroize::Zeroize; use zeroize::Zeroize;
+3 -1
View File
@@ -18,6 +18,9 @@ use crate::{
keypair::{KeyPair, PrivateKey, PublicKey, SecretKey, SizedBytesExt}, keypair::{KeyPair, PrivateKey, PublicKey, SecretKey, SizedBytesExt},
serialization::serialize, serialization::serialize,
}; };
use alloc::vec;
use alloc::vec::Vec;
use core::convert::TryFrom;
use digest::{Digest, FixedOutput}; use digest::{Digest, FixedOutput};
use generic_array::{ use generic_array::{
typenum::{Unsigned, U32}, typenum::{Unsigned, U32},
@@ -27,7 +30,6 @@ use generic_bytes::SizedBytes;
use hkdf::Hkdf; use hkdf::Hkdf;
use hmac::{Hmac, Mac, NewMac}; use hmac::{Hmac, Mac, NewMac};
use rand::{CryptoRng, RngCore}; use rand::{CryptoRng, RngCore};
use std::convert::TryFrom;
use zeroize::Zeroize; use zeroize::Zeroize;
pub(crate) type NonceLen = U32; pub(crate) type NonceLen = U32;
+40 -34
View File
@@ -9,17 +9,19 @@
use crate::errors::{InternalPakeError, ProtocolError}; use crate::errors::{InternalPakeError, ProtocolError};
use crate::group::Group; use crate::group::Group;
use alloc::borrow::ToOwned;
use alloc::vec::Vec;
use core::fmt::Debug;
use core::ops::Deref;
#[cfg(test)] #[cfg(test)]
use generic_array::typenum::Unsigned; use generic_array::typenum::Unsigned;
use generic_array::{ArrayLength, GenericArray}; use generic_array::{ArrayLength, GenericArray};
use generic_bytes::{SizedBytes, TryFromSizedBytesError}; use generic_bytes::{SizedBytes, TryFromSizedBytesError};
#[cfg(test)] #[cfg(all(test, feature = "std"))]
use proptest::prelude::*; use proptest::prelude::*;
#[cfg(test)] #[cfg(all(test, feature = "std"))]
use rand::{rngs::StdRng, SeedableRng}; use rand::{rngs::StdRng, SeedableRng};
use rand::{CryptoRng, RngCore}; use rand::{CryptoRng, RngCore};
use std::fmt::Debug;
use std::ops::Deref;
use zeroize::Zeroize; use zeroize::Zeroize;
/// Convenience extension trait of SizedBytes /// Convenience extension trait of SizedBytes
@@ -57,7 +59,7 @@ impl<G: Group, S: SecretKey<G>> Clone for KeyPair<G, S> {
} }
impl<G: Group, S: SecretKey<G> + Debug> Debug for KeyPair<G, S> { impl<G: Group, S: SecretKey<G> + Debug> Debug for KeyPair<G, S> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("KeyPair") f.debug_struct("KeyPair")
.field("pk", &self.pk) .field("pk", &self.pk)
.field("sk", &self.sk) .field("sk", &self.sk)
@@ -73,8 +75,8 @@ impl<G: Group, S: SecretKey<G> + PartialEq> PartialEq for KeyPair<G, S> {
impl<G: Group, S: SecretKey<G> + Eq> Eq for KeyPair<G, S> {} impl<G: Group, S: SecretKey<G> + Eq> Eq for KeyPair<G, S> {}
impl<G: Group, S: SecretKey<G> + std::hash::Hash> std::hash::Hash for KeyPair<G, S> { impl<G: Group, S: SecretKey<G> + core::hash::Hash> core::hash::Hash for KeyPair<G, S> {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) { fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
self.pk.hash(state); self.pk.hash(state);
self.sk.hash(state); self.sk.hash(state);
} }
@@ -139,14 +141,14 @@ impl<G: Group> KeyPair<G> {
#[cfg(test)] #[cfg(test)]
pub fn as_byte_ptrs(&self) -> Vec<(*const u8, usize)> { pub fn as_byte_ptrs(&self) -> Vec<(*const u8, usize)> {
vec![ alloc::vec![
(self.pk.as_ptr(), G::ElemLen::to_usize()), (self.pk.as_ptr(), G::ElemLen::to_usize()),
(self.sk.as_ptr(), G::ScalarLen::to_usize()), (self.sk.as_ptr(), G::ScalarLen::to_usize()),
] ]
} }
} }
#[cfg(test)] #[cfg(all(test, feature = "std"))]
impl<G: Group + Debug> KeyPair<G> { impl<G: Group + Debug> KeyPair<G> {
/// Test-only strategy returning a proptest Strategy based on /// Test-only strategy returning a proptest Strategy based on
/// generate_random /// generate_random
@@ -179,7 +181,7 @@ impl<L: ArrayLength<u8>> Clone for Key<L> {
} }
impl<L: ArrayLength<u8>> Debug for Key<L> { impl<L: ArrayLength<u8>> Debug for Key<L> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_tuple("Key").field(&self.0).finish() f.debug_tuple("Key").field(&self.0).finish()
} }
} }
@@ -192,8 +194,8 @@ impl<L: ArrayLength<u8>> PartialEq for Key<L> {
} }
} }
impl<L: ArrayLength<u8>> std::hash::Hash for Key<L> { impl<L: ArrayLength<u8>> core::hash::Hash for Key<L> {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) { fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
self.0.hash(state); self.0.hash(state);
} }
} }
@@ -297,7 +299,7 @@ pub trait SecretKey<G: Group>: Clone + Sized + Zeroize {
} }
impl<G: Group> SecretKey<G> for PrivateKey<G> { impl<G: Group> SecretKey<G> for PrivateKey<G> {
type Error = std::convert::Infallible; type Error = core::convert::Infallible;
fn diffie_hellman(&self, pk: PublicKey<G>) -> Result<Vec<u8>, InternalPakeError> { fn diffie_hellman(&self, pk: PublicKey<G>) -> Result<Vec<u8>, InternalPakeError> {
let pk_data = GenericArray::<u8, G::ElemLen>::from_slice(&pk.0[..]); let pk_data = GenericArray::<u8, G::ElemLen>::from_slice(&pk.0[..]);
@@ -373,19 +375,20 @@ impl<G: Group> SizedBytes for PublicKey<G> {
mod tests { mod tests {
use super::*; use super::*;
use crate::errors::*; use crate::errors::*;
use core::slice::from_raw_parts;
use curve25519_dalek::ristretto::RistrettoPoint; use curve25519_dalek::ristretto::RistrettoPoint;
use generic_array::typenum::Unsigned; use generic_array::typenum::Unsigned;
use rand::rngs::OsRng; use rand::rngs::OsRng;
use std::slice::from_raw_parts;
#[test] #[test]
fn test_zeroize_key() -> Result<(), ProtocolError> { fn test_zeroize_key() -> Result<(), ProtocolError> {
let key_len = <RistrettoPoint as Group>::ElemLen::to_usize(); let key_len = <RistrettoPoint as Group>::ElemLen::to_usize();
let mut key = let mut key = Key::<<RistrettoPoint as Group>::ElemLen>(GenericArray::clone_from_slice(
Key::<<RistrettoPoint as Group>::ElemLen>(GenericArray::clone_from_slice(&vec![ &alloc::vec![
1u8; 1u8;
key_len key_len
])); ],
));
let ptr = key.as_ptr(); let ptr = key.as_ptr();
key.zeroize(); key.zeroize();
@@ -412,6 +415,7 @@ mod tests {
Ok(()) Ok(())
} }
#[cfg(feature = "std")]
proptest! { proptest! {
#[test] #[test]
fn test_ristretto_check(kp in KeyPair::<RistrettoPoint>::uniform_keypair_strategy()) { fn test_ristretto_check(kp in KeyPair::<RistrettoPoint>::uniform_keypair_strategy()) {
@@ -448,7 +452,7 @@ mod tests {
} }
#[test] #[test]
fn remote_key() -> anyhow::Result<()> { fn remote_key() {
use crate::{ use crate::{
CipherSuite, ClientLogin, ClientLoginFinishParameters, ClientLoginFinishResult, CipherSuite, ClientLogin, ClientLoginFinishParameters, ClientLoginFinishResult,
ClientLoginStartResult, ClientRegistration, ClientRegistrationFinishParameters, ClientLoginStartResult, ClientRegistration, ClientRegistrationFinishParameters,
@@ -473,7 +477,7 @@ mod tests {
struct RemoteKey(PrivateKey<RistrettoPoint>); struct RemoteKey(PrivateKey<RistrettoPoint>);
impl SecretKey<RistrettoPoint> for RemoteKey { impl SecretKey<RistrettoPoint> for RemoteKey {
type Error = std::convert::Infallible; type Error = core::convert::Infallible;
fn diffie_hellman( fn diffie_hellman(
&self, &self,
@@ -502,27 +506,29 @@ mod tests {
let sk = RistrettoPoint::random_nonzero_scalar(&mut OsRng); let sk = RistrettoPoint::random_nonzero_scalar(&mut OsRng);
let sk_bytes = RistrettoPoint::scalar_as_bytes(sk); let sk_bytes = RistrettoPoint::scalar_as_bytes(sk);
let sk = RemoteKey(PrivateKey::from_arr(&sk_bytes).unwrap()); let sk = RemoteKey(PrivateKey::from_arr(&sk_bytes).unwrap());
let keypair = KeyPair::from_private_key(sk)?; let keypair = KeyPair::from_private_key(sk).unwrap();
let server_setup = ServerSetup::<Default, RemoteKey>::new_with_key(&mut OsRng, keypair); let server_setup = ServerSetup::<Default, RemoteKey>::new_with_key(&mut OsRng, keypair);
let ClientRegistrationStartResult { let ClientRegistrationStartResult {
message, message,
state: client, state: client,
} = ClientRegistration::<Default>::start(&mut OsRng, PASSWORD.as_bytes())?; } = ClientRegistration::<Default>::start(&mut OsRng, PASSWORD.as_bytes()).unwrap();
let ServerRegistrationStartResult { message, .. } = let ServerRegistrationStartResult { message, .. } =
ServerRegistration::start(&server_setup, message, &[])?; ServerRegistration::start(&server_setup, message, &[]).unwrap();
let ClientRegistrationFinishResult { message, .. } = client.finish( let ClientRegistrationFinishResult { message, .. } = client
&mut OsRng, .finish(
message, &mut OsRng,
ClientRegistrationFinishParameters::Default, message,
)?; ClientRegistrationFinishParameters::Default,
)
.unwrap();
let file = ServerRegistration::finish(message); let file = ServerRegistration::finish(message);
let ClientLoginStartResult { let ClientLoginStartResult {
message, message,
state: client, state: client,
} = ClientLogin::<Default>::start(&mut OsRng, PASSWORD.as_bytes())?; } = ClientLogin::<Default>::start(&mut OsRng, PASSWORD.as_bytes()).unwrap();
let ServerLoginStartResult { let ServerLoginStartResult {
message, message,
state: server, state: server,
@@ -534,11 +540,11 @@ mod tests {
message, message,
&[], &[],
ServerLoginStartParameters::default(), ServerLoginStartParameters::default(),
)?; )
let ClientLoginFinishResult { message, .. } = .unwrap();
client.finish(message, ClientLoginFinishParameters::Default)?; let ClientLoginFinishResult { message, .. } = client
server.finish(message)?; .finish(message, ClientLoginFinishParameters::Default)
.unwrap();
Ok(()) server.finish(message).unwrap();
} }
} }
+3
View File
@@ -824,6 +824,7 @@
#![cfg_attr(not(feature = "bench"), deny(missing_docs))] #![cfg_attr(not(feature = "bench"), deny(missing_docs))]
#![deny(unsafe_code)] #![deny(unsafe_code)]
#![cfg_attr(not(feature = "std"), no_std)]
#[cfg(not(any(feature = "u64_backend", feature = "u32_backend",)))] #[cfg(not(any(feature = "u64_backend", feature = "u32_backend",)))]
compile_error!( compile_error!(
@@ -831,6 +832,8 @@ compile_error!(
please enable one of: u64_backend, u32_backend" please enable one of: u64_backend, u32_backend"
); );
extern crate alloc;
// Error types // Error types
pub mod errors; pub mod errors;
+2 -1
View File
@@ -17,6 +17,7 @@ use crate::{
keypair::{KeyPair, PublicKey, SecretKey, SizedBytesExt}, keypair::{KeyPair, PublicKey, SecretKey, SizedBytesExt},
opaque::ServerSetup, opaque::ServerSetup,
}; };
use alloc::vec::Vec;
use digest::Digest; use digest::Digest;
use generic_array::{typenum::Unsigned, GenericArray}; use generic_array::{typenum::Unsigned, GenericArray};
use generic_bytes::SizedBytes; use generic_bytes::SizedBytes;
@@ -197,7 +198,7 @@ impl<CS: CipherSuite> RegistrationUpload<CS> {
rng: &mut R, rng: &mut R,
server_setup: &ServerSetup<CS, S>, server_setup: &ServerSetup<CS, S>,
) -> Self { ) -> Self {
let mut masking_key = vec![0u8; <CS::Hash as Digest>::OutputSize::to_usize()]; let mut masking_key = alloc::vec![0u8; <CS::Hash as Digest>::OutputSize::to_usize()];
rng.fill_bytes(&mut masking_key); rng.fill_bytes(&mut masking_key);
Self { Self {
+3 -1
View File
@@ -19,12 +19,14 @@ use crate::{
CredentialFinalization, CredentialRequest, CredentialResponse, RegistrationRequest, CredentialFinalization, CredentialRequest, CredentialResponse, RegistrationRequest,
RegistrationResponse, RegistrationUpload, RegistrationResponse, RegistrationUpload,
}; };
use alloc::vec;
use alloc::vec::Vec;
use core::marker::PhantomData;
use digest::Digest; use digest::Digest;
use generic_array::{typenum::Unsigned, GenericArray}; use generic_array::{typenum::Unsigned, GenericArray};
use generic_bytes::SizedBytes; use generic_bytes::SizedBytes;
use hkdf::Hkdf; use hkdf::Hkdf;
use rand::{CryptoRng, RngCore}; use rand::{CryptoRng, RngCore};
use std::marker::PhantomData;
use zeroize::Zeroize; use zeroize::Zeroize;
const STR_CREDENTIAL_RESPONSE_PAD: &[u8] = b"CredentialResponsePad"; const STR_CREDENTIAL_RESPONSE_PAD: &[u8] = b"CredentialResponsePad";
+2 -2
View File
@@ -11,7 +11,7 @@ use rand::{CryptoRng, RngCore};
/// Used to store the OPRF input and blinding factor /// Used to store the OPRF input and blinding factor
#[cfg_attr(feature = "serialize", derive(serde::Deserialize, serde::Serialize))] #[cfg_attr(feature = "serialize", derive(serde::Deserialize, serde::Serialize))]
pub struct Token<Grp: Group> { pub struct Token<Grp: Group> {
pub(crate) data: Vec<u8>, pub(crate) data: alloc::vec::Vec<u8>,
pub(crate) blind: Grp::Scalar, pub(crate) blind: Grp::Scalar,
} }
@@ -154,7 +154,7 @@ mod tests {
#[test] #[test]
fn oprf_inversion_unsalted() { fn oprf_inversion_unsalted() {
let mut rng = OsRng; let mut rng = OsRng;
let mut input = vec![0u8; 64]; let mut input = alloc::vec![0u8; 64];
rng.fill_bytes(&mut input); rng.fill_bytes(&mut input);
let (token, alpha) = blind::<_, RistrettoPoint, sha2::Sha512>(&input, &mut rng).unwrap(); let (token, alpha) = blind::<_, RistrettoPoint, sha2::Sha512>(&input, &mut rng).unwrap();
let res = let res =
+16 -15
View File
@@ -4,10 +4,11 @@
// LICENSE file in the root directory of this source tree. // LICENSE file in the root directory of this source tree.
use crate::errors::PakeError; use crate::errors::PakeError;
use alloc::vec::Vec;
// Corresponds to the I2OSP() function from RFC8017 // Corresponds to the I2OSP() function from RFC8017
pub(crate) fn i2osp(input: usize, length: usize) -> Result<Vec<u8>, PakeError> { pub(crate) fn i2osp(input: usize, length: usize) -> Result<alloc::vec::Vec<u8>, PakeError> {
let sizeof_usize = std::mem::size_of::<usize>(); let sizeof_usize = core::mem::size_of::<usize>();
// Check if input >= 256^length // Check if input >= 256^length
if (sizeof_usize as u32 - input.leading_zeros() / 8) > length as u32 { if (sizeof_usize as u32 - input.leading_zeros() / 8) > length as u32 {
@@ -18,7 +19,7 @@ pub(crate) fn i2osp(input: usize, length: usize) -> Result<Vec<u8>, PakeError> {
return Ok((&input.to_be_bytes()[sizeof_usize - length..]).to_vec()); return Ok((&input.to_be_bytes()[sizeof_usize - length..]).to_vec());
} }
let mut output = vec![0u8; length]; let mut output = alloc::vec![0u8; length];
output.splice( output.splice(
length - sizeof_usize..length, length - sizeof_usize..length,
input.to_be_bytes().iter().cloned(), input.to_be_bytes().iter().cloned(),
@@ -28,12 +29,12 @@ pub(crate) fn i2osp(input: usize, length: usize) -> Result<Vec<u8>, PakeError> {
// Corresponds to the OS2IP() function from RFC8017 // Corresponds to the OS2IP() function from RFC8017
pub(crate) fn os2ip(input: &[u8]) -> Result<usize, PakeError> { pub(crate) fn os2ip(input: &[u8]) -> Result<usize, PakeError> {
if input.len() > std::mem::size_of::<usize>() { if input.len() > core::mem::size_of::<usize>() {
return Err(PakeError::SerializationError); return Err(PakeError::SerializationError);
} }
let mut output_array = [0u8; std::mem::size_of::<usize>()]; let mut output_array = [0u8; core::mem::size_of::<usize>()];
output_array[std::mem::size_of::<usize>() - input.len()..].copy_from_slice(input); output_array[core::mem::size_of::<usize>() - input.len()..].copy_from_slice(input);
Ok(usize::from_be_bytes(output_array)) Ok(usize::from_be_bytes(output_array))
} }
@@ -45,7 +46,7 @@ pub(crate) fn serialize(input: &[u8], max_bytes: usize) -> Result<Vec<u8>, PakeE
// Tokenizes an input of the format I2OSP(len(input), max_bytes) || input, outputting // Tokenizes an input of the format I2OSP(len(input), max_bytes) || input, outputting
// (input, remainder) // (input, remainder)
pub(crate) fn tokenize(input: &[u8], size_bytes: usize) -> Result<(Vec<u8>, Vec<u8>), PakeError> { pub(crate) fn tokenize(input: &[u8], size_bytes: usize) -> Result<(Vec<u8>, Vec<u8>), PakeError> {
if size_bytes > std::mem::size_of::<usize>() || input.len() < size_bytes { if size_bytes > core::mem::size_of::<usize>() || input.len() < size_bytes {
return Err(PakeError::SerializationError); return Err(PakeError::SerializationError);
} }
@@ -89,17 +90,17 @@ macro_rules! impl_serialize_and_deserialize_for {
.map_err(serde::de::Error::custom) .map_err(serde::de::Error::custom)
} else { } else {
struct ByteVisitor<CS: CipherSuite> { struct ByteVisitor<CS: CipherSuite> {
marker: std::marker::PhantomData<CS>, marker: core::marker::PhantomData<CS>,
} }
impl<'de, CS: CipherSuite> serde::de::Visitor<'de> for ByteVisitor<CS> { impl<'de, CS: CipherSuite> serde::de::Visitor<'de> for ByteVisitor<CS> {
type Value = $t<CS>; type Value = $t<CS>;
fn expecting( fn expecting(
&self, &self,
formatter: &mut std::fmt::Formatter, formatter: &mut core::fmt::Formatter,
) -> std::fmt::Result { ) -> core::fmt::Result {
formatter.write_str(std::concat!( formatter.write_str(core::concat!(
"the byte representation of a ", "the byte representation of a ",
std::stringify!($t) core::stringify!($t)
)) ))
} }
@@ -110,16 +111,16 @@ macro_rules! impl_serialize_and_deserialize_for {
$t::<CS>::deserialize(value).map_err(|_| { $t::<CS>::deserialize(value).map_err(|_| {
serde::de::Error::invalid_value( serde::de::Error::invalid_value(
serde::de::Unexpected::Bytes(value), serde::de::Unexpected::Bytes(value),
&std::concat!( &core::concat!(
"invalid byte sequence for ", "invalid byte sequence for ",
std::stringify!($t) core::stringify!($t)
), ),
) )
}) })
} }
} }
deserializer.deserialize_bytes(ByteVisitor::<CS> { deserializer.deserialize_bytes(ByteVisitor::<CS> {
marker: std::marker::PhantomData, marker: core::marker::PhantomData,
}) })
} }
} }
+6 -2
View File
@@ -16,6 +16,10 @@ use crate::{
serialization::{i2osp, os2ip, serialize}, serialization::{i2osp, os2ip, serialize},
*, *,
}; };
#[cfg(test)]
use alloc::vec;
#[cfg(test)]
use alloc::vec::Vec;
use curve25519_dalek::{ristretto::RistrettoPoint, traits::Identity}; use curve25519_dalek::{ristretto::RistrettoPoint, traits::Identity};
use generic_array::typenum::Unsigned; use generic_array::typenum::Unsigned;
@@ -351,8 +355,8 @@ fn ke3_message_roundtrip() {
proptest! { proptest! {
#[test] #[test]
fn test_i2osp_os2ip(bytes in vec(any::<u8>(), 0..std::mem::size_of::<usize>())) { fn test_i2osp_os2ip(bytes in vec(any::<u8>(), 0..core::mem::size_of::<usize>())) {
assert_eq!(i2osp(os2ip(&bytes)?, bytes.len())?, bytes); assert_eq!(i2osp(os2ip(&bytes).unwrap(), bytes.len()).unwrap(), bytes);
} }
#[test] #[test]
+2 -1
View File
@@ -6,6 +6,7 @@
//! Trait specifying a slow hashing function //! Trait specifying a slow hashing function
use crate::{errors::InternalPakeError, hash::Hash}; use crate::{errors::InternalPakeError, hash::Hash};
use alloc::vec::Vec;
use digest::Digest; use digest::Digest;
#[cfg(feature = "slow-hash")] #[cfg(feature = "slow-hash")]
use generic_array::typenum::Unsigned; use generic_array::typenum::Unsigned;
@@ -36,7 +37,7 @@ impl<D: Hash> SlowHash<D> for argon2::Argon2<'_> {
input: GenericArray<u8, <D as Digest>::OutputSize>, input: GenericArray<u8, <D as Digest>::OutputSize>,
) -> Result<Vec<u8>, InternalPakeError> { ) -> Result<Vec<u8>, InternalPakeError> {
let params = argon2::Argon2::default(); let params = argon2::Argon2::default();
let mut output = vec![0u8; <D as Digest>::OutputSize::to_usize()]; let mut output = alloc::vec![0u8; <D as Digest>::OutputSize::to_usize()];
params params
.hash_password_into( .hash_password_into(
argon2::Algorithm::Argon2id, argon2::Algorithm::Argon2id,
+16 -14
View File
@@ -6,22 +6,17 @@
#![allow(unsafe_code)] #![allow(unsafe_code)]
use crate::{ use crate::{
ciphersuite::CipherSuite, ciphersuite::CipherSuite, errors::*, key_exchange::tripledh::TripleDH, opaque::*,
errors::*, slow_hash::NoOpHash, tests::mock_rng::CycleRng, *,
group::Group,
key_exchange::tripledh::{NonceLen, TripleDH},
keypair::KeyPair,
opaque::*,
slow_hash::NoOpHash,
tests::mock_rng::CycleRng,
*,
}; };
use alloc::string::ToString;
use alloc::vec;
use alloc::vec::Vec;
use core::slice::from_raw_parts;
use curve25519_dalek::{ristretto::RistrettoPoint, traits::Identity}; use curve25519_dalek::{ristretto::RistrettoPoint, traits::Identity};
use generic_array::typenum::Unsigned;
use generic_bytes::SizedBytes; use generic_bytes::SizedBytes;
use rand::{rngs::OsRng, RngCore}; use rand::rngs::OsRng;
use serde_json::Value; use serde_json::Value;
use std::slice::from_raw_parts;
use zeroize::Zeroize; use zeroize::Zeroize;
// Tests // Tests
@@ -154,8 +149,9 @@ fn populate_test_vectors(values: &Value) -> TestVectorParameters {
} }
} }
fn stringify_test_vectors(p: &TestVectorParameters) -> String { #[cfg(feature = "std")]
let mut s = String::new(); fn stringify_test_vectors(p: &TestVectorParameters) -> alloc::string::String {
let mut s = alloc::string::String::new();
s.push_str("{\n"); 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_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_s_sk\": \"{}\",\n", hex::encode(&p.client_s_sk)).as_str());
@@ -277,7 +273,12 @@ fn stringify_test_vectors(p: &TestVectorParameters) -> String {
s s
} }
#[cfg(feature = "std")]
fn generate_parameters<CS: CipherSuite>() -> TestVectorParameters { fn generate_parameters<CS: CipherSuite>() -> TestVectorParameters {
use crate::{group::Group, key_exchange::tripledh::NonceLen, keypair::KeyPair};
use generic_array::typenum::Unsigned;
use rand::RngCore;
let mut rng = OsRng; let mut rng = OsRng;
// Inputs // Inputs
@@ -447,6 +448,7 @@ fn generate_parameters<CS: CipherSuite>() -> TestVectorParameters {
} }
} }
#[cfg(feature = "std")]
#[test] #[test]
fn generate_test_vectors() { fn generate_test_vectors() {
let parameters = generate_parameters::<RistrettoSha5123dhNoSlowHash>(); let parameters = generate_parameters::<RistrettoSha5123dhNoSlowHash>();
+2 -1
View File
@@ -3,8 +3,9 @@
// This source code is licensed under the MIT license found in the // This source code is licensed under the MIT license found in the
// LICENSE file in the root directory of this source tree. // LICENSE file in the root directory of this source tree.
use alloc::vec::Vec;
use core::cmp::min;
use rand::{CryptoRng, Error, RngCore}; use rand::{CryptoRng, Error, RngCore};
use std::cmp::min;
/// A simple implementation of `RngCore` for testing purposes. /// A simple implementation of `RngCore` for testing purposes.
/// ///
+4 -1
View File
@@ -7,6 +7,9 @@ use crate::{
ciphersuite::CipherSuite, errors::*, key_exchange::tripledh::TripleDH, keypair::PrivateKey, ciphersuite::CipherSuite, errors::*, key_exchange::tripledh::TripleDH, keypair::PrivateKey,
opaque::*, slow_hash::NoOpHash, tests::mock_rng::CycleRng, *, opaque::*, slow_hash::NoOpHash, tests::mock_rng::CycleRng, *,
}; };
use alloc::string::ToString;
use alloc::vec::Vec;
use alloc::{format, vec};
use curve25519_dalek::ristretto::RistrettoPoint; use curve25519_dalek::ristretto::RistrettoPoint;
use generic_array::typenum::Unsigned; use generic_array::typenum::Unsigned;
use generic_bytes::SizedBytes; use generic_bytes::SizedBytes;
@@ -711,7 +714,7 @@ macro_rules! rfc_to_params {
}; };
} }
fn rfc_to_json(input: &str) -> String { fn rfc_to_json(input: &str) -> alloc::string::String {
let mut json = vec![]; let mut json = vec![];
for line in input.lines() { for line in input.lines() {
// If line contains colon, then // If line contains colon, then
+2
View File
@@ -7,6 +7,8 @@ use crate::group::Group;
use crate::hash::Hash; use crate::hash::Hash;
use crate::tests::mock_rng::CycleRng; use crate::tests::mock_rng::CycleRng;
use crate::{errors::*, oprf}; use crate::{errors::*, oprf};
use alloc::string::ToString;
use alloc::vec::Vec;
use curve25519_dalek::ristretto::RistrettoPoint; use curve25519_dalek::ristretto::RistrettoPoint;
use generic_array::GenericArray; use generic_array::GenericArray;
use serde_json::Value; use serde_json::Value;