Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds Curve448 #87

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ edition = "2018"
# and -accelerated suffix means that this resolver will be the default used by the Builder.
[features]
default = ["default-resolver"]
default-resolver = ["aes-gcm", "chacha20poly1305", "blake2", "sha2", "x25519-dalek", "rand"]
default-resolver = ["aes-gcm", "chacha20poly1305", "blake2", "sha2", "x25519-dalek", "x448","rand"]
nightly = ["blake2/simd_opt", "x25519-dalek/nightly", "subtle/nightly"]
ring-resolver = ["ring"]
ring-accelerated = ["ring-resolver", "default-resolver"]
Expand Down Expand Up @@ -47,6 +47,7 @@ blake2 = { version = "0.8", optional = true }
rand = { version = "0.7", optional = true }
sha2 = { version = "0.8", optional = true }
x25519-dalek = { version = "0.6", optional = true }
x448 = { version = "0.6", optional = true }
pqcrypto-kyber = { version = "0.6", optional = true }
pqcrypto-traits = { version = "0.3", optional = true }

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ specification.
|-----------:|:-------:|:----:|:---------:|
| CSPRNG | ✔ | ✔ | ✔ |
| 25519 | ✔ | ✔ | ✔ |
| 448 | | | |
| 448 | | | |
| AESGCM | ✔ | ✔ | |
| ChaChaPoly | ✔ | ✔ | ✔ |
| SHA256 | ✔ | ✔ | ✔ |
Expand Down
4 changes: 2 additions & 2 deletions src/params/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ impl FromStr for BaseChoice {
#[derive(PartialEq, Copy, Clone, Debug)]
pub enum DHChoice {
Curve25519,
Ed448,
Curve448,
}

impl FromStr for DHChoice {
Expand All @@ -45,7 +45,7 @@ impl FromStr for DHChoice {
use self::DHChoice::*;
match s {
"25519" => Ok(Curve25519),
"448" => Ok(Ed448),
"448" => Ok(Curve448),
_ => bail!(PatternProblem::UnsupportedDhType),
}
}
Expand Down
71 changes: 69 additions & 2 deletions src/resolvers/default.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ use pqcrypto_traits::kem::{Ciphertext, PublicKey, SecretKey, SharedSecret};
use rand::rngs::OsRng;
use sha2::{Digest, Sha256, Sha512};
use x25519_dalek as x25519;
use x448;

use super::CryptoResolver;
#[cfg(feature = "pqclean_kyber1024")]
Expand All @@ -40,7 +41,7 @@ impl CryptoResolver for DefaultResolver {
fn resolve_dh(&self, choice: &DHChoice) -> Option<Box<dyn Dh>> {
match *choice {
DHChoice::Curve25519 => Some(Box::new(Dh25519::default())),
_ => None,
DHChoice::Curve448 => Some(Box::new(Dh448::default())),
}
}

Expand Down Expand Up @@ -76,6 +77,16 @@ struct Dh25519 {
privkey: [u8; 32],
pubkey: [u8; 32],
}
/// Wraps x448 [crate-crypto].
struct Dh448 {
privkey: [u8; 56],
pubkey: [u8; 56],
}
impl Default for Dh448 {
fn default() -> Dh448 {
Dh448 { privkey: [0u8; 56], pubkey: [0u8; 56] }
}
}

/// Wraps `aes-gcm`'s AES256-GCM implementation.
#[derive(Default)]
Expand Down Expand Up @@ -163,6 +174,45 @@ impl Dh for Dh25519 {
}
}

impl Dh for Dh448 {
fn name(&self) -> &'static str {
"448"
}

fn pub_len(&self) -> usize {
56
}

fn priv_len(&self) -> usize {
56
}

fn set(&mut self, privkey: &[u8]) {
copy_slices!(privkey, &mut self.privkey);
self.pubkey = x448::x448_unchecked(self.privkey, x448::X448_BASEPOINT_BYTES);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the difference between this and the checked version? It looks like from the documentation that checked will assert that low-order points aren't used?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep that’s completely correct. I used the unchecked version for consistency between X25519 and X448

}

fn generate(&mut self, rng: &mut dyn Random) {
rng.fill_bytes(&mut self.privkey);
self.pubkey = x448::x448_unchecked(self.privkey, x448::X448_BASEPOINT_BYTES);
}

fn pubkey(&self) -> &[u8] {
&self.pubkey
}

fn privkey(&self) -> &[u8] {
&self.privkey
}

fn dh(&self, pubkey: &[u8], out: &mut [u8]) -> Result<(), ()> {
let pub_key = x448::PublicKey::from_bytes_unchecked(pubkey).unwrap();
let result = x448::x448_unchecked(self.privkey, *pub_key.as_bytes());
copy_slices!(&result, out);
Ok(())
}
}

impl Cipher for CipherAesGcm {
fn name(&self) -> &'static str {
"AESGCM"
Expand Down Expand Up @@ -529,7 +579,6 @@ mod tests {

use self::hex::FromHex;
use super::*;
use crate::types::*;

#[test]
fn test_sha256() {
Expand Down Expand Up @@ -615,6 +664,24 @@ mod tests {
== "c3da55379de9c6908e94ea4df28d084f32eccf03491c71f754b4075577a28552"
);
}
#[test]
fn test_curve448() {
// Curve448 test - draft-curves-10
let mut keypair: Dh448 = Default::default();
let scalar =
Vec::<u8>::from_hex("3d262fddf9ec8e88495266fea19a34d28882acef045104d0d1aae121700a779c984c24f8cdd78fbff44943eba368f54b29259a4f1c600ad3")
.unwrap();
copy_slices!(&scalar, &mut keypair.privkey);
let public =
Vec::<u8>::from_hex("06fce640fa3487bfda5f6cf2d5263f8aad88334cbd07437f020f08f9814dc031ddbdc38c19c6da2583fa5429db94ada18aa7a7fb4ef8a086")
.unwrap();
let mut output = [0u8; 56];
keypair.dh(&public, &mut output).unwrap();
assert_eq!(
hex::encode(&output[..]),
"ce3e4ff95a60dc6697da1db1d85e6afbdf79b50a2412d7546d5f239fe14fbaadeb445fc66a01b0779d98223961111e21766282f73dd96b6f"
);
}

#[test]
fn test_aesgcm() {
Expand Down
7 changes: 0 additions & 7 deletions tests/vectors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -259,16 +259,10 @@ fn test_vectors_from_json(json: &str) {

let mut passes = 0;
let mut fails = 0;
let mut ignored = 0;

for vector in test_vectors.vectors {
let params: NoiseParams = vector.protocol_name.parse().unwrap();

if params.dh == DHChoice::Ed448 {
ignored += 1;
continue;
}

let (init, resp) = match build_session_pair(&vector) {
Ok((init, resp)) => (init, resp),
Err(s) => {
Expand Down Expand Up @@ -299,7 +293,6 @@ fn test_vectors_from_json(json: &str) {
}

println!("\n{}/{} passed", passes, passes + fails);
println!("* ignored {} unsupported variants", ignored);
if fails > 0 {
panic!("at least one vector failed.");
}
Expand Down