diff --git a/Cargo.lock b/Cargo.lock index b7d61d6..d51d98d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -107,6 +107,16 @@ dependencies = [ "generic-array 0.14.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "displaydoc" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.31 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "fake-simd" version = "0.1.2" @@ -202,6 +212,7 @@ dependencies = [ "aead 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "base64 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", "curve25519-dalek 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "displaydoc 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "generic-array 0.14.2 (registry+https://github.com/rust-lang/crates.io-index)", "hex 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "hkdf 0.9.0-alpha.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -539,6 +550,7 @@ dependencies = [ "checksum curve25519-dalek 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5d85653f070353a16313d0046f173f70d1aadd5b42600a14de626f0dfb3473a5" "checksum digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5" "checksum digest 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" +"checksum displaydoc 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "e6269d127174b18c665e683e23c2c55d3735fadbec4181c7c70b0450b764bfa5" "checksum fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" "checksum fnv 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" "checksum generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c68f0274ae0e023facc3c97b2e00f076be70e254bc851d972503b328db79b2ec" diff --git a/Cargo.toml b/Cargo.toml index 0881562..ec4eccf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,6 +15,7 @@ slow-hash = ["scrypt"] [dependencies] aead = "0.3.1" curve25519-dalek = "2.1.0" +displaydoc = "0.1" generic-array = "0.14.2" hkdf = "0.9.0-alpha.0" hmac = "0.8.0" diff --git a/src/ciphersuite.rs b/src/ciphersuite.rs index ce159e2..c9db67b 100644 --- a/src/ciphersuite.rs +++ b/src/ciphersuite.rs @@ -15,15 +15,15 @@ use crate::{ use rand_core::{CryptoRng, RngCore}; /// Configures the underlying primitives used in OPAQUE -/// * `Group`: a finite cyclic group along with a point representation, along -/// with an extension trait PasswordToCurve that allows some customization on -/// how to hash a password to a curve point. See `group::Group` and -/// `map_to_curve::GroupWithMapToCurve`. -/// * `KeyFormat`: a keypair type composed of public and private components -/// * `SlowHash`: a slow hashing function, typically used for password hashing pub trait CipherSuite { + /// A finite cyclic group along with a point representation along with + /// an extension trait PasswordToCurve that allows some customization on + /// how to hash a password to a curve point. See `group::Group` and + /// `map_to_curve::GroupWithMapToCurve`. type Group: GroupWithMapToCurve; + /// A keypair type composed of public and private components type KeyFormat: KeyPair + PartialEq; + /// A slow hashing function, typically used for password hashing type SlowHash: SlowHash; /// Generating a random key pair given a cryptographic rng diff --git a/src/errors.rs b/src/errors.rs index de76ca1..6be81bf 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -4,56 +4,59 @@ // LICENSE file in the root directory of this source tree. //! A list of error types which are produced during an execution of the protocol - +use displaydoc::Display; use thiserror::Error; /// Represents an error in the manipulation of internal cryptographic data -#[derive(Debug, Error)] +#[derive(Debug, Display, Error)] pub enum InternalPakeError { - #[error("Invalid length for {name}: expected {len}, but is actually {actual_len}.")] + /// Invalid length for {name}: expected {len}, but is actually {actual_len}. SizeError { + /// name name: &'static str, + /// length len: usize, + /// actual actual_len: usize, }, - #[error("Could not decompress point.")] + /// Could not decompress point. PointError, - #[error("Key belongs to a small subgroup!")] + /// Key belongs to a small subgroup! SubGroupError, - #[error("hashing to a key failed")] + /// hashing to a key failed HashingFailure, - #[error("Computing HKDF failed while deriving subkeys")] + /// Computing HKDF failed while deriving subkeys HkdfError, - #[error("Computing HMAC failed while supplying a secret key")] + /// Computing HMAC failed while supplying a secret key HmacError, - #[error("Computing the slow hashing function failed")] + /// Computing the slow hashing function failed SlowHashError, /// This error occurs when the envelope seal fails - #[error("Constructing the envelope seal failed.")] + /// Constructing the envelope seal failed. SealError, /// This error occurs when the envelope seal open fails - #[error("Opening the envelope seal failed.")] + /// Opening the envelope seal failed. SealOpenError, /// This error occurs when the envelope seal open hmac check fails - #[error("HMAC check in seal open failed.")] + /// HMAC check in seal open failed. SealOpenHmacError, } /// Represents an error in password checking -#[derive(Debug, Error)] +#[derive(Debug, Display, Error)] pub enum PakeError { /// This error results from an internal error during PRF construction /// - #[error("Internal error during PRF verification: {0}")] + /// Internal error during PRF verification: {0} CryptoError(InternalPakeError), /// This error occurs when the server object that is being called finish() on is malformed - #[error("Incomplete set of keys passed into finish() function")] + /// Incomplete set of keys passed into finish() function IncompleteKeysError, - #[error("The provided server public key doesn't match the sealed one")] + /// The provided server public key doesn't match the sealed one IncompatibleServerStaticPublicKeyError, - #[error("Error in key exchange protocol when attempting to validate MACs")] + /// Error in key exchange protocol when attempting to validate MACs KeyExchangeMacValidationError, - #[error("Error in validating credentials")] + /// Error in validating credentials InvalidLoginError, } @@ -66,17 +69,17 @@ impl From for PakeError { } /// Represents an error in protocol handling -#[derive(Debug, Error)] +#[derive(Debug, Display, Error)] pub enum ProtocolError { /// This error results from an error during password verification /// - #[error("Internal error during password verification: {0}")] + /// Internal error during password verification: {0} VerificationError(PakeError), /// This error occurs when the server answer cannot be handled - #[error("Server response cannot be handled.")] + /// Server response cannot be handled. ServerError, /// This error occurs when the client request cannot be handled - #[error("Client request cannot be handled.")] + /// Client request cannot be handled. ClientError, } diff --git a/src/lib.rs b/src/lib.rs index 2a824eb..c96ba89 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -372,6 +372,9 @@ //! match `client_shared_secret`. Otherwise, on failure, the `finish` algorithm outputs the error `InvalidLoginError`. //! +#![deny(missing_docs)] +#![deny(unsafe_code)] + // Error types pub mod errors; diff --git a/src/opaque.rs b/src/opaque.rs index 5b306cc..b0eeb35 100644 --- a/src/opaque.rs +++ b/src/opaque.rs @@ -45,6 +45,7 @@ impl TryFrom<&[u8]> for RegisterFirstMessage { } impl RegisterFirstMessage { + /// byte representation for the registration request pub fn to_bytes(&self) -> GenericArray { self.alpha.to_arr() } @@ -81,6 +82,7 @@ impl RegisterSecondMessage where Grp: Group, { + /// byte representation for the registration response message pub fn to_bytes(&self) -> Vec { self.beta.to_arr().to_vec() } @@ -100,6 +102,7 @@ impl RegisterThirdMessage where KeyFormat: KeyPair, { + /// byte representation for the registration upload message pub fn to_bytes(&self) -> Vec { [&self.envelope.to_bytes(), &self.client_s_pk.to_arr()[..]].concat() } @@ -151,6 +154,7 @@ impl TryFrom<&[u8]> for LoginFirstMessage { } impl LoginFirstMessage { + /// byte representation for the login request pub fn to_bytes(&self) -> Vec { [&self.alpha.to_arr()[..], &self.ke1_message.to_bytes()].concat() } @@ -172,6 +176,7 @@ where Grp: Group, KeyFormat: KeyPair, { + /// byte representation for the login response pub fn to_bytes(&self) -> Vec { [ &self.beta.to_arr()[..], @@ -232,6 +237,7 @@ impl TryFrom<&[u8]> for LoginThirdMessage { } impl LoginThirdMessage { + /// byte representation for the login finalization pub fn to_bytes(&self) -> Vec { self.ke3_message.to_bytes() } @@ -265,6 +271,7 @@ impl TryFrom<&[u8]> for ClientRegistration { } impl ClientRegistration { + /// byte representation for the client's registration state pub fn to_bytes(&self) -> Vec { let output: Vec = [ &CS::Group::scalar_as_bytes(&self.blinding_factor)[..], @@ -475,6 +482,7 @@ where <::Repr as SizedBytes>::Len, >: generic_array::ArrayLength, { + /// byte representation for the server's registration state pub fn to_bytes(&self) -> Vec { let mut output: Vec = CS::Group::scalar_as_bytes(&self.oprf_key).to_vec(); match &self.client_s_pk { @@ -609,6 +617,7 @@ impl TryFrom<&[u8]> for ClientLogin { } impl ClientLogin { + /// byte representation for the client's login state pub fn to_bytes(&self) -> Vec { let output: Vec = [ &CS::Group::scalar_as_bytes(&self.blinding_factor)[..], @@ -762,6 +771,7 @@ type ServerLoginStartResult = ( ); impl ServerLogin { + /// byte representation for the server's login state pub fn to_bytes(&self) -> Vec { self.ke2_state.to_bytes() }