Adding i2osp error checking condition
This commit is contained in:
+7
-7
@@ -32,7 +32,7 @@ const NONCE_LEN: usize = 32;
|
||||
fn build_inner_envelope_internal<CS: CipherSuite>(
|
||||
random_pwd: &[u8],
|
||||
nonce: &[u8],
|
||||
) -> Result<PublicKey<CS::Group>, InternalPakeError> {
|
||||
) -> Result<PublicKey<CS::Group>, ProtocolError> {
|
||||
let h = Hkdf::<CS::Hash>::new(None, random_pwd);
|
||||
let mut keypair_seed = vec![0u8; <PrivateKey<CS::Group> as SizedBytes>::Len::to_usize()];
|
||||
h.expand(&[nonce, STR_PRIVATE_KEY].concat(), &mut keypair_seed)
|
||||
@@ -48,7 +48,7 @@ fn build_inner_envelope_internal<CS: CipherSuite>(
|
||||
fn recover_keys_internal<CS: CipherSuite>(
|
||||
random_pwd: &[u8],
|
||||
nonce: &[u8],
|
||||
) -> Result<KeyPair<CS::Group>, InternalPakeError> {
|
||||
) -> Result<KeyPair<CS::Group>, ProtocolError> {
|
||||
let h = Hkdf::<CS::Hash>::new(None, random_pwd);
|
||||
let mut keypair_seed = vec![0u8; <PrivateKey<CS::Group> as SizedBytes>::Len::to_usize()];
|
||||
h.expand(&[nonce, STR_PRIVATE_KEY].concat(), &mut keypair_seed)
|
||||
@@ -188,7 +188,7 @@ impl<CS: CipherSuite> Envelope<CS> {
|
||||
PublicKey<CS::Group>,
|
||||
GenericArray<u8, <CS::Hash as Digest>::OutputSize>,
|
||||
),
|
||||
InternalPakeError,
|
||||
ProtocolError,
|
||||
> {
|
||||
let mut nonce = vec![0u8; NONCE_LEN];
|
||||
rng.fill_bytes(&mut nonce);
|
||||
@@ -199,7 +199,7 @@ impl<CS: CipherSuite> Envelope<CS> {
|
||||
);
|
||||
|
||||
let (id_u, id_s) =
|
||||
bytestrings_from_identifiers(&optional_ids, &client_s_pk.to_arr(), server_s_pk);
|
||||
bytestrings_from_identifiers(&optional_ids, &client_s_pk.to_arr(), server_s_pk)?;
|
||||
let aad = construct_aad(&id_u, &id_s, server_s_pk);
|
||||
|
||||
let (envelope, export_key) = Self::seal_raw(key, &nonce, &aad, mode)?;
|
||||
@@ -246,10 +246,10 @@ impl<CS: CipherSuite> Envelope<CS> {
|
||||
key: &[u8],
|
||||
server_s_pk: &[u8],
|
||||
optional_ids: &Option<Identifiers>,
|
||||
) -> Result<OpenedEnvelope<CS>, InternalPakeError> {
|
||||
) -> Result<OpenedEnvelope<CS>, ProtocolError> {
|
||||
let client_static_keypair = match self.mode {
|
||||
InnerEnvelopeMode::Zero => {
|
||||
return Err(InternalPakeError::IncompatibleEnvelopeModeError)
|
||||
return Err(InternalPakeError::IncompatibleEnvelopeModeError.into())
|
||||
}
|
||||
InnerEnvelopeMode::Internal => recover_keys_internal::<CS>(key, &self.nonce)?,
|
||||
};
|
||||
@@ -258,7 +258,7 @@ impl<CS: CipherSuite> Envelope<CS> {
|
||||
optional_ids,
|
||||
&client_static_keypair.public().to_arr(),
|
||||
server_s_pk,
|
||||
);
|
||||
)?;
|
||||
let aad = construct_aad(&id_u, &id_s, server_s_pk);
|
||||
|
||||
let opened = self.open_raw(key, &aad)?;
|
||||
|
||||
@@ -86,7 +86,7 @@ impl<D: Hash, G: Group> KeyExchange<D, G> for TripleDH {
|
||||
|
||||
let mut transcript_hasher = D::new()
|
||||
.chain(STR_RFC)
|
||||
.chain(&serialize(&context, 2))
|
||||
.chain(&serialize(&context, 2)?)
|
||||
.chain(&id_u)
|
||||
.chain(&serialized_credential_request[..])
|
||||
.chain(&id_s)
|
||||
@@ -141,7 +141,7 @@ 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(&serialize(&context, 2)?)
|
||||
.chain(&id_u)
|
||||
.chain(&serialized_credential_request)
|
||||
.chain(&id_s)
|
||||
@@ -522,9 +522,9 @@ fn hkdf_expand_label_extracted<D: Hash>(
|
||||
let mut opaque_label: Vec<u8> = Vec::new();
|
||||
opaque_label.extend_from_slice(STR_OPAQUE);
|
||||
opaque_label.extend_from_slice(label);
|
||||
hkdf_label.extend_from_slice(&serialize(&opaque_label, 1));
|
||||
hkdf_label.extend_from_slice(&serialize(&opaque_label, 1)?);
|
||||
|
||||
hkdf_label.extend_from_slice(&serialize(context, 1));
|
||||
hkdf_label.extend_from_slice(&serialize(context, 1)?);
|
||||
|
||||
hkdf.expand(&hkdf_label, &mut okm)
|
||||
.map_err(|_| InternalPakeError::HkdfError)?;
|
||||
|
||||
+16
-19
@@ -6,7 +6,7 @@
|
||||
//! Defines the GroupWithMapToCurve trait to specify how to map a password to a
|
||||
//! curve point
|
||||
|
||||
use crate::errors::InternalPakeError;
|
||||
use crate::errors::{InternalPakeError, ProtocolError};
|
||||
use crate::group::Group;
|
||||
use crate::hash::Hash;
|
||||
use crate::serialization::i2osp;
|
||||
@@ -22,16 +22,15 @@ pub trait GroupWithMapToCurve: Group {
|
||||
const SUITE_ID: usize;
|
||||
|
||||
/// transforms a password and domain separation tag (DST) into a curve point
|
||||
fn map_to_curve<H: Hash>(msg: &[u8], dst: &[u8]) -> Result<Self, InternalPakeError>;
|
||||
fn map_to_curve<H: Hash>(msg: &[u8], dst: &[u8]) -> Result<Self, ProtocolError>;
|
||||
|
||||
/// Hashes a slice of pseudo-random bytes to a scalar
|
||||
fn hash_to_scalar<H: Hash>(input: &[u8], dst: &[u8])
|
||||
-> Result<Self::Scalar, InternalPakeError>;
|
||||
fn hash_to_scalar<H: Hash>(input: &[u8], dst: &[u8]) -> Result<Self::Scalar, ProtocolError>;
|
||||
|
||||
/// Generates the contextString parameter as defined in
|
||||
/// <https://www.ietf.org/archive/id/draft-irtf-cfrg-voprf-05.txt>
|
||||
fn get_context_string(mode: u8) -> Vec<u8> {
|
||||
[i2osp(mode as usize, 1), i2osp(Self::SUITE_ID, 2)].concat()
|
||||
fn get_context_string(mode: u8) -> Result<Vec<u8>, ProtocolError> {
|
||||
Ok([i2osp(mode as usize, 1)?, i2osp(Self::SUITE_ID, 2)?].concat())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,16 +39,14 @@ impl GroupWithMapToCurve for RistrettoPoint {
|
||||
|
||||
// Implements the hash_to_ristretto255() function from
|
||||
// https://www.ietf.org/archive/id/draft-irtf-cfrg-hash-to-curve-10.txt
|
||||
fn map_to_curve<H: Hash>(msg: &[u8], dst: &[u8]) -> Result<Self, InternalPakeError> {
|
||||
fn map_to_curve<H: Hash>(msg: &[u8], dst: &[u8]) -> Result<Self, ProtocolError> {
|
||||
let uniform_bytes =
|
||||
expand_message_xmd::<H>(msg, dst, <H as Digest>::OutputSize::to_usize())?;
|
||||
<Self as Group>::hash_to_curve(&GenericArray::clone_from_slice(&uniform_bytes[..]))
|
||||
.map_err(ProtocolError::from)
|
||||
}
|
||||
|
||||
fn hash_to_scalar<H: Hash>(
|
||||
input: &[u8],
|
||||
dst: &[u8],
|
||||
) -> Result<Self::Scalar, InternalPakeError> {
|
||||
fn hash_to_scalar<H: Hash>(input: &[u8], dst: &[u8]) -> Result<Self::Scalar, ProtocolError> {
|
||||
const LEN_IN_BYTES: usize = 64;
|
||||
let uniform_bytes = expand_message_xmd::<H>(input, dst, LEN_IN_BYTES)?;
|
||||
let mut bits = [0u8; LEN_IN_BYTES];
|
||||
@@ -79,24 +76,24 @@ pub fn expand_message_xmd<H: Hash>(
|
||||
msg: &[u8],
|
||||
dst: &[u8],
|
||||
len_in_bytes: usize,
|
||||
) -> Result<Vec<u8>, InternalPakeError> {
|
||||
) -> Result<Vec<u8>, ProtocolError> {
|
||||
let b_in_bytes = <H as Digest>::OutputSize::to_usize();
|
||||
let r_in_bytes = <H as BlockInput>::BlockSize::to_usize();
|
||||
|
||||
let ell = div_ceil(len_in_bytes, b_in_bytes);
|
||||
if ell > 255 {
|
||||
return Err(InternalPakeError::HashToCurveError);
|
||||
return Err(InternalPakeError::HashToCurveError.into());
|
||||
}
|
||||
let dst_prime = [dst, &i2osp(dst.len(), 1)].concat();
|
||||
let z_pad = i2osp(0, r_in_bytes);
|
||||
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 dst_prime = [dst, &i2osp(dst.len(), 1)?].concat();
|
||||
let z_pad = i2osp(0, r_in_bytes)?;
|
||||
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 mut b: Vec<Vec<u8>> = vec![H::digest(&msg_prime).to_vec()]; // b[0]
|
||||
|
||||
let mut h = H::new();
|
||||
h.update(&b[0]);
|
||||
h.update(&i2osp(1, 1));
|
||||
h.update(&i2osp(1, 1)?);
|
||||
h.update(&dst_prime);
|
||||
b.push(h.finalize_reset().to_vec()); // b[1]
|
||||
|
||||
@@ -105,7 +102,7 @@ pub fn expand_message_xmd<H: Hash>(
|
||||
|
||||
for i in 2..(ell + 1) {
|
||||
h.update(xor(&b[0], &b[i - 1])?);
|
||||
h.update(&i2osp(i, 1));
|
||||
h.update(&i2osp(i, 1)?);
|
||||
h.update(&dst_prime);
|
||||
b.push(h.finalize_reset().to_vec()); // b[i]
|
||||
uniform_bytes.extend_from_slice(&b[i]);
|
||||
|
||||
+18
-16
@@ -174,17 +174,17 @@ pub(crate) fn bytestrings_from_identifiers(
|
||||
ids: &Option<Identifiers>,
|
||||
client_s_pk: &[u8],
|
||||
server_s_pk: &[u8],
|
||||
) -> (Vec<u8>, Vec<u8>) {
|
||||
) -> Result<(Vec<u8>, Vec<u8>), ProtocolError> {
|
||||
let (client_identity, server_identity): (Vec<u8>, Vec<u8>) = match ids {
|
||||
None => (client_s_pk.to_vec(), server_s_pk.to_vec()),
|
||||
Some(Identifiers::ClientIdentifier(id_u)) => (id_u.clone(), server_s_pk.to_vec()),
|
||||
Some(Identifiers::ServerIdentifier(id_s)) => (client_s_pk.to_vec(), id_s.clone()),
|
||||
Some(Identifiers::ClientAndServerIdentifiers(id_u, id_s)) => (id_u.clone(), id_s.clone()),
|
||||
};
|
||||
(
|
||||
serialize(&client_identity, 2),
|
||||
serialize(&server_identity, 2),
|
||||
)
|
||||
Ok((
|
||||
serialize(&client_identity, 2)?,
|
||||
serialize(&server_identity, 2)?,
|
||||
))
|
||||
}
|
||||
|
||||
/// Optional parameters for client registration finish
|
||||
@@ -413,15 +413,15 @@ impl_debug_eq_hash_for!(
|
||||
|
||||
impl<CS: CipherSuite> ClientLogin<CS> {
|
||||
/// Serialization into bytes
|
||||
pub fn serialize(&self) -> Vec<u8> {
|
||||
pub fn serialize(&self) -> Result<Vec<u8>, ProtocolError> {
|
||||
let output: Vec<u8> = [
|
||||
&CS::Group::scalar_as_bytes(self.token.blind)[..],
|
||||
&serialize(&self.serialized_credential_request, 2),
|
||||
&serialize(&self.ke1_state.to_bytes(), 2),
|
||||
&serialize(&self.serialized_credential_request, 2)?,
|
||||
&serialize(&self.ke1_state.to_bytes(), 2)?,
|
||||
&self.token.data,
|
||||
]
|
||||
.concat();
|
||||
output
|
||||
Ok(output)
|
||||
}
|
||||
|
||||
/// Deserialization from bytes
|
||||
@@ -604,8 +604,10 @@ impl<CS: CipherSuite> ClientLogin<CS> {
|
||||
let opened_envelope = &envelope
|
||||
.open(&password_derived_key, &server_s_pk_bytes, &optional_ids)
|
||||
.map_err(|e| match e {
|
||||
InternalPakeError::SealOpenHmacError => PakeError::InvalidLoginError,
|
||||
err => PakeError::from(err),
|
||||
ProtocolError::VerificationError(PakeError::CryptoError(
|
||||
InternalPakeError::SealOpenHmacError,
|
||||
)) => ProtocolError::VerificationError(PakeError::InvalidLoginError),
|
||||
err => err,
|
||||
})?;
|
||||
|
||||
let credential_response_component = CredentialResponse::<CS>::serialize_without_ke(
|
||||
@@ -767,7 +769,7 @@ impl<CS: CipherSuite> ServerLogin<CS> {
|
||||
&optional_ids,
|
||||
&client_s_pk.to_arr(),
|
||||
&server_s_pk.to_arr(),
|
||||
);
|
||||
)?;
|
||||
|
||||
let l1_bytes = &l1.serialize();
|
||||
|
||||
@@ -906,15 +908,15 @@ impl<CS: CipherSuite> Drop for ServerLogin<CS> {
|
||||
fn get_password_derived_key<G: GroupWithMapToCurve, SH: SlowHash<D>, D: Hash>(
|
||||
token: &oprf::Token<G>,
|
||||
beta: G,
|
||||
) -> Result<Vec<u8>, InternalPakeError> {
|
||||
let oprf_output = oprf::finalize::<G, D>(&token.data, &token.blind, beta);
|
||||
SH::hash(oprf_output)
|
||||
) -> Result<Vec<u8>, ProtocolError> {
|
||||
let oprf_output = oprf::finalize::<G, D>(&token.data, &token.blind, beta)?;
|
||||
SH::hash(oprf_output).map_err(ProtocolError::from)
|
||||
}
|
||||
|
||||
fn oprf_key_from_seed<G: GroupWithMapToCurve, D: Hash>(
|
||||
oprf_seed: &GenericArray<u8, D::OutputSize>,
|
||||
credential_identifier: &[u8],
|
||||
) -> Result<G::Scalar, InternalPakeError> {
|
||||
) -> Result<G::Scalar, ProtocolError> {
|
||||
let mut oprf_key_bytes = vec![0u8; <PrivateKey<G> as SizedBytes>::Len::to_usize()];
|
||||
Hkdf::<D>::from_prk(oprf_seed)
|
||||
.map_err(|_| InternalPakeError::HkdfError)?
|
||||
|
||||
+32
-23
@@ -4,7 +4,7 @@
|
||||
// LICENSE file in the root directory of this source tree.
|
||||
|
||||
use crate::{
|
||||
errors::InternalPakeError, group::Group, hash::Hash, map_to_curve::GroupWithMapToCurve,
|
||||
errors::ProtocolError, group::Group, hash::Hash, map_to_curve::GroupWithMapToCurve,
|
||||
serialization::serialize,
|
||||
};
|
||||
use digest::Digest;
|
||||
@@ -32,10 +32,10 @@ static MODE_BASE: u8 = 0x00;
|
||||
pub(crate) fn blind<R: RngCore + CryptoRng, G: GroupWithMapToCurve, H: Hash>(
|
||||
input: &[u8],
|
||||
blinding_factor_rng: &mut R,
|
||||
) -> Result<(Token<G>, G), InternalPakeError> {
|
||||
) -> Result<(Token<G>, G), ProtocolError> {
|
||||
// Choose a random scalar that must be non-zero
|
||||
let blind = G::random_nonzero_scalar(blinding_factor_rng);
|
||||
let dst = [STR_VOPRF, &G::get_context_string(MODE_BASE)].concat();
|
||||
let dst = [STR_VOPRF, &G::get_context_string(MODE_BASE)?].concat();
|
||||
let mapped_point = G::map_to_curve::<H>(input, &dst)?;
|
||||
let blind_token = mapped_point * &blind;
|
||||
Ok((
|
||||
@@ -59,7 +59,7 @@ pub(crate) fn finalize<G: GroupWithMapToCurve, H: Hash>(
|
||||
input: &[u8],
|
||||
blind: &G::Scalar,
|
||||
evaluated_element: G,
|
||||
) -> GenericArray<u8, <H as Digest>::OutputSize> {
|
||||
) -> Result<GenericArray<u8, <H as Digest>::OutputSize>, ProtocolError> {
|
||||
let unblinded_element = evaluated_element * &G::scalar_invert(blind);
|
||||
finalize_after_unblind::<G, H>(input, unblinded_element)
|
||||
}
|
||||
@@ -67,15 +67,15 @@ pub(crate) fn finalize<G: GroupWithMapToCurve, H: Hash>(
|
||||
fn finalize_after_unblind<G: GroupWithMapToCurve, H: Hash>(
|
||||
input: &[u8],
|
||||
unblinded_element: G,
|
||||
) -> GenericArray<u8, <H as Digest>::OutputSize> {
|
||||
let finalize_dst = [STR_VOPRF_FINALIZE, &G::get_context_string(MODE_BASE)].concat();
|
||||
) -> Result<GenericArray<u8, <H as Digest>::OutputSize>, ProtocolError> {
|
||||
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(&finalize_dst, 2),
|
||||
serialize(input, 2)?,
|
||||
serialize(&unblinded_element.to_arr().to_vec(), 2)?,
|
||||
serialize(&finalize_dst, 2)?,
|
||||
]
|
||||
.concat();
|
||||
<H as Digest>::digest(&hash_input)
|
||||
Ok(<H as Digest>::digest(&hash_input))
|
||||
}
|
||||
|
||||
////////////////////////
|
||||
@@ -88,7 +88,7 @@ fn finalize_after_unblind<G: GroupWithMapToCurve, H: Hash>(
|
||||
pub fn blind_shim<R: RngCore + CryptoRng, G: GroupWithMapToCurve, H: Hash>(
|
||||
input: &[u8],
|
||||
blinding_factor_rng: &mut R,
|
||||
) -> Result<(Token<G>, G), InternalPakeError> {
|
||||
) -> Result<(Token<G>, G), ProtocolError> {
|
||||
blind::<R, G, H>(input, blinding_factor_rng)
|
||||
}
|
||||
|
||||
@@ -105,8 +105,8 @@ pub fn evaluate_shim<G: Group>(point: G, oprf_key: &G::Scalar) -> G {
|
||||
pub fn finalize_shim<G: GroupWithMapToCurve, H: Hash>(
|
||||
token: &Token<G>,
|
||||
point: G,
|
||||
) -> Result<GenericArray<u8, <H as Digest>::OutputSize>, InternalPakeError> {
|
||||
Ok(finalize::<G, H>(&token.data, &token.blind, point))
|
||||
) -> Result<GenericArray<u8, <H as Digest>::OutputSize>, ProtocolError> {
|
||||
finalize::<G, H>(&token.data, &token.blind, point)
|
||||
}
|
||||
|
||||
///////////
|
||||
@@ -124,30 +124,34 @@ mod tests {
|
||||
use sha2::Sha512;
|
||||
|
||||
fn prf(input: &[u8], oprf_key: &[u8; 32]) -> GenericArray<u8, <Sha512 as Digest>::OutputSize> {
|
||||
let dst = [STR_VOPRF, &RistrettoPoint::get_context_string(MODE_BASE)].concat();
|
||||
let dst = [
|
||||
STR_VOPRF,
|
||||
&RistrettoPoint::get_context_string(MODE_BASE).unwrap(),
|
||||
]
|
||||
.concat();
|
||||
let point = RistrettoPoint::map_to_curve::<Sha512>(input, &dst).unwrap();
|
||||
let scalar =
|
||||
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).unwrap()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn oprf_retrieval() -> Result<(), InternalPakeError> {
|
||||
fn oprf_retrieval() {
|
||||
let input = b"hunter2";
|
||||
let mut rng = OsRng;
|
||||
let (token, alpha) = blind::<_, RistrettoPoint, Sha512>(&input[..], &mut rng)?;
|
||||
let (token, alpha) = blind::<_, RistrettoPoint, Sha512>(&input[..], &mut rng).unwrap();
|
||||
let oprf_key_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 oprf_key = RistrettoPoint::from_scalar_slice(&oprf_key_bytes)?;
|
||||
let oprf_key = RistrettoPoint::from_scalar_slice(&oprf_key_bytes).unwrap();
|
||||
let beta = evaluate::<RistrettoPoint>(alpha, &oprf_key);
|
||||
let res = finalize::<RistrettoPoint, sha2::Sha512>(&token.data, &token.blind, beta);
|
||||
let res =
|
||||
finalize::<RistrettoPoint, sha2::Sha512>(&token.data, &token.blind, beta).unwrap();
|
||||
let res2 = prf(&input[..], &oprf_key.as_bytes());
|
||||
assert_eq!(res, res2);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -156,11 +160,16 @@ mod tests {
|
||||
let mut input = vec![0u8; 64];
|
||||
rng.fill_bytes(&mut input);
|
||||
let (token, alpha) = blind::<_, RistrettoPoint, sha2::Sha512>(&input, &mut rng).unwrap();
|
||||
let res = finalize::<RistrettoPoint, sha2::Sha512>(&token.data, &token.blind, alpha);
|
||||
let res =
|
||||
finalize::<RistrettoPoint, sha2::Sha512>(&token.data, &token.blind, alpha).unwrap();
|
||||
|
||||
let dst = [STR_VOPRF, &RistrettoPoint::get_context_string(MODE_BASE)].concat();
|
||||
let dst = [
|
||||
STR_VOPRF,
|
||||
&RistrettoPoint::get_context_string(MODE_BASE).unwrap(),
|
||||
]
|
||||
.concat();
|
||||
let point = RistrettoPoint::map_to_curve::<Sha512>(&input, &dst).unwrap();
|
||||
let res2 = finalize_after_unblind::<RistrettoPoint, sha2::Sha512>(&input, point);
|
||||
let res2 = finalize_after_unblind::<RistrettoPoint, sha2::Sha512>(&input, point).unwrap();
|
||||
|
||||
assert_eq!(res, res2);
|
||||
}
|
||||
|
||||
@@ -6,17 +6,24 @@
|
||||
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();
|
||||
pub(crate) fn i2osp(input: usize, length: usize) -> Result<Vec<u8>, PakeError> {
|
||||
let sizeof_usize = std::mem::size_of::<usize>();
|
||||
|
||||
// Check if input >= 256^length
|
||||
if (sizeof_usize as u32 - input.leading_zeros() / 8) > length as u32 {
|
||||
return Err(PakeError::SerializationError);
|
||||
}
|
||||
|
||||
if length <= sizeof_usize {
|
||||
return Ok((&input.to_be_bytes()[sizeof_usize - length..]).to_vec());
|
||||
}
|
||||
|
||||
let mut output = vec![0u8; length];
|
||||
output.splice(
|
||||
length - std::mem::size_of::<usize>()..length,
|
||||
length - sizeof_usize..length,
|
||||
input.to_be_bytes().iter().cloned(),
|
||||
);
|
||||
output
|
||||
Ok(output)
|
||||
}
|
||||
|
||||
// Corresponds to the OS2IP() function from RFC8017
|
||||
@@ -31,8 +38,8 @@ pub(crate) fn os2ip(input: &[u8]) -> Result<usize, PakeError> {
|
||||
}
|
||||
|
||||
// Computes I2OSP(len(input), max_bytes) || input
|
||||
pub(crate) fn serialize(input: &[u8], max_bytes: usize) -> Vec<u8> {
|
||||
[&i2osp(input.len(), max_bytes), input].concat()
|
||||
pub(crate) fn serialize(input: &[u8], max_bytes: usize) -> Result<Vec<u8>, PakeError> {
|
||||
Ok([&i2osp(input.len(), max_bytes)?, input].concat())
|
||||
}
|
||||
|
||||
// Tokenizes an input of the format I2OSP(len(input), max_bytes) || input, outputting
|
||||
@@ -122,3 +129,22 @@ macro_rules! impl_serialize_and_deserialize_for {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
#[cfg(test)]
|
||||
mod unit_tests {
|
||||
use super::*;
|
||||
|
||||
// Test the error condition for I2OSP
|
||||
#[test]
|
||||
fn test_i2osp_err_check() {
|
||||
assert!(i2osp(0, 1).is_ok());
|
||||
|
||||
assert!(i2osp(255, 1).is_ok());
|
||||
assert!(i2osp(256, 1).is_err());
|
||||
assert!(i2osp(257, 1).is_err());
|
||||
|
||||
assert!(i2osp(256 * 256 - 1, 2).is_ok());
|
||||
assert!(i2osp(256 * 256, 2).is_err());
|
||||
assert!(i2osp(256 * 256 + 1, 2).is_err());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -283,13 +283,13 @@ fn client_login_roundtrip() {
|
||||
// serialization order: scalar, credential_request, ke1_state, password
|
||||
let bytes: Vec<u8> = [
|
||||
&sc.as_bytes()[..],
|
||||
&serialize(&serialized_credential_request, 2),
|
||||
&serialize(&l1_data, 2),
|
||||
&serialize(&serialized_credential_request, 2).unwrap(),
|
||||
&serialize(&l1_data, 2).unwrap(),
|
||||
&pw[..],
|
||||
]
|
||||
.concat();
|
||||
let reg = ClientLogin::<Default>::deserialize(&bytes[..]).unwrap();
|
||||
let reg_bytes = reg.serialize();
|
||||
let reg_bytes = reg.serialize().unwrap();
|
||||
assert_eq!(reg_bytes, bytes);
|
||||
}
|
||||
|
||||
@@ -350,7 +350,7 @@ 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);
|
||||
assert_eq!(i2osp(os2ip(&bytes)?, bytes.len())?, bytes);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -368,7 +368,11 @@ fn generate_parameters<CS: CipherSuite>() -> TestVectorParameters {
|
||||
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().to_vec();
|
||||
let client_login_state = client_login_start_result.state.serialize().to_vec();
|
||||
let client_login_state = client_login_start_result
|
||||
.state
|
||||
.serialize()
|
||||
.unwrap()
|
||||
.to_vec();
|
||||
|
||||
let mut server_e_sk_and_nonce_rng = CycleRng::new(
|
||||
[
|
||||
@@ -594,7 +598,7 @@ fn test_credential_request() -> Result<(), ProtocolError> {
|
||||
);
|
||||
assert_eq!(
|
||||
hex::encode(¶meters.client_login_state),
|
||||
hex::encode(client_login_start_result.state.serialize())
|
||||
hex::encode(client_login_start_result.state.serialize()?)
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -63,7 +63,7 @@ fn populate_test_vectors(values: &Value) -> VOPRFTestVectorParameters {
|
||||
|
||||
// Tests input -> blind, blinded_element
|
||||
#[test]
|
||||
fn test_blind() -> Result<(), PakeError> {
|
||||
fn test_blind() -> Result<(), ProtocolError> {
|
||||
for tv in OPRF_RISTRETTO255_SHA512 {
|
||||
let parameters = populate_test_vectors(&serde_json::from_str(tv).unwrap());
|
||||
let mut rng = CycleRng::new(parameters.blind.to_vec());
|
||||
@@ -106,7 +106,7 @@ fn test_evaluate() -> Result<(), PakeError> {
|
||||
|
||||
// Tests input, blind, evaluation_element -> output
|
||||
#[test]
|
||||
fn test_finalize() -> Result<(), PakeError> {
|
||||
fn test_finalize() -> Result<(), ProtocolError> {
|
||||
for tv in OPRF_RISTRETTO255_SHA512 {
|
||||
let parameters = populate_test_vectors(&serde_json::from_str(tv).unwrap());
|
||||
|
||||
@@ -116,7 +116,7 @@ fn test_finalize() -> Result<(), PakeError> {
|
||||
RistrettoPoint::from_element_slice(GenericArray::from_slice(
|
||||
¶meters.evaluation_element,
|
||||
))?,
|
||||
);
|
||||
)?;
|
||||
|
||||
assert_eq!(¶meters.output, &output.to_vec());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user