diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 049934c..628dcde 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -12,7 +12,7 @@ jobs: name: Rustfmt runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Cache cargo uses: Swatinem/rust-cache@v1 - uses: IronCoreLabs/rust-toolchain@v1 @@ -50,7 +50,7 @@ jobs: - os: windows-2019 target: x86_64-pc-windows-msvc steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Cache cargo uses: Swatinem/rust-cache@v1 - uses: IronCoreLabs/rust-toolchain@v1 @@ -75,7 +75,7 @@ jobs: - 1.70.0 #MSRV fail-fast: false steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Cache cargo uses: Swatinem/rust-cache@v1 - uses: IronCoreLabs/rust-toolchain@v1 @@ -98,7 +98,7 @@ jobs: - name: base ref: ${{ github.base_ref }} steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 with: ref: ${{ matrix.ref }} - name: Cache cargo @@ -128,7 +128,7 @@ jobs: name: Upload benchmark results runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Cache cargo uses: Swatinem/rust-cache@v1 - name: Retrieve benchmark results diff --git a/CHANGELOG.md b/CHANGELOG.md index 9f5b42d..d01ff52 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,10 @@ # Changelog -## Unreleased +## 0.14.0 (2024-12-03) +- [[#184](https://github.com/IronCoreLabs/recrypt-rs/pull/188)] + - Switch from `ed25519-dalek-fiat` to `ed25519-dalek`. + - Remove `u64_backend` and `u32_backend` features. - [[#184](https://github.com/IronCoreLabs/recrypt-rs/pull/184)] - Change MSRV to Rust 1.70.0 - [[#177](https://github.com/IronCoreLabs/recrypt-rs/pull/177)] diff --git a/Cargo.toml b/Cargo.toml index 544205e..00766cf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "recrypt" -version = "0.13.1" +version = "0.14.0" authors = ["IronCore Labs "] readme = "README.md" license = "AGPL-3.0-only" @@ -23,7 +23,7 @@ cfg-if = "1" clear_on_drop = "0.2" derivative = "2.1" # Disable all features for ed25519 and enable the proper ones down in the [features] section below -ed25519-dalek = {version = "=0.1.0", default-features = false, features = ["std"], package = "ed25519-dalek-fiat"} +ed25519-dalek = {version = "2.1.1", default-features = false, features = ["std", "rand_core"]} # Explicit dependency so we can pass the wasm-bindgen flag to it getrandom = {version = "0.2", optional = true} gridiron = "0.10" @@ -55,10 +55,7 @@ debug = false lto = true [features] -default = ["u64_backend"] -u64_backend = ["ed25519-dalek/u64_backend"] -u32_backend = ["ed25519-dalek/u32_backend"] -wasm = ["u32_backend", "clear_on_drop/no_cc", "getrandom/js"] +wasm = ["clear_on_drop/no_cc", "getrandom/js"] #Can be used to disable the automatic mlock detection for architectures. disable_memlock = [] diff --git a/flake.lock b/flake.lock index d95d56a..605f5f5 100644 --- a/flake.lock +++ b/flake.lock @@ -5,11 +5,11 @@ "systems": "systems" }, "locked": { - "lastModified": 1710146030, - "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=", + "lastModified": 1726560853, + "narHash": "sha256-X6rJYSESBVr3hBoH0WbKE5KvhPU5bloyZ2L4K60/fPQ=", "owner": "numtide", "repo": "flake-utils", - "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a", + "rev": "c1dfcf08411b08f6b8615f7d8971a2bfa81d5e8a", "type": "github" }, "original": { @@ -20,11 +20,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1725432240, - "narHash": "sha256-+yj+xgsfZaErbfYM3T+QvEE2hU7UuE+Jf0fJCJ8uPS0=", + "lastModified": 1729880355, + "narHash": "sha256-RP+OQ6koQQLX5nw0NmcDrzvGL8HDLnyXt/jHhL1jwjM=", "owner": "nixos", "repo": "nixpkgs", - "rev": "ad416d066ca1222956472ab7d0555a6946746a80", + "rev": "18536bf04cd71abd345f9579158841376fdd0c5a", "type": "github" }, "original": { @@ -36,11 +36,11 @@ }, "nixpkgs_2": { "locked": { - "lastModified": 1718428119, - "narHash": "sha256-WdWDpNaq6u1IPtxtYHHWpl5BmabtpmLnMAx0RdJ/vo8=", + "lastModified": 1728538411, + "narHash": "sha256-f0SBJz1eZ2yOuKUr5CA9BHULGXVSn6miBuUWdTyhUhU=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "e6cea36f83499eb4e9cd184c8a8e823296b50ad5", + "rev": "b69de56fac8c2b6f8fd27f2eca01dcda8e0a4221", "type": "github" }, "original": { @@ -62,11 +62,11 @@ "nixpkgs": "nixpkgs_2" }, "locked": { - "lastModified": 1725589472, - "narHash": "sha256-+OB00N6Yql/ZRQQkQ0PNnxfW2tH89DHnv29hBS7tXMM=", + "lastModified": 1730255392, + "narHash": "sha256-9pydem8OVxa0TwjUai1PJe0yHAJw556CWCEwyoAq8Ik=", "owner": "oxalica", "repo": "rust-overlay", - "rev": "2b00881d2ff72174cffdc007238cb6bedd6e1d8e", + "rev": "7509d76ce2b3d22b40bd25368b45c0a9f7f36c89", "type": "github" }, "original": { diff --git a/rust-toolchain.toml b/rust-toolchain.toml index 2cb44b1..1a07338 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,3 +1,3 @@ [toolchain] profile = "default" -channel = "1.80.1" +channel = "1.82.0" diff --git a/src/api.rs b/src/api.rs index 3075f99..8a73d78 100644 --- a/src/api.rs +++ b/src/api.rs @@ -51,7 +51,7 @@ impl Recrypt> { Recrypt::new_with_rand(ReseedingRng::new( rand_chacha::ChaChaCore::from_entropy(), BYTES_BEFORE_RESEEDING, - rand::rngs::OsRng::default(), + rand::rngs::OsRng, )) } } diff --git a/src/api_480.rs b/src/api_480.rs index de231d7..98cd25a 100644 --- a/src/api_480.rs +++ b/src/api_480.rs @@ -50,7 +50,7 @@ impl Recrypt480> { Recrypt480::new_with_rand(ReseedingRng::new( rand_chacha::ChaChaCore::from_entropy(), BYTES_BEFORE_RESEEDING, - rand::rngs::OsRng::default(), + rand::rngs::OsRng, )) } } @@ -934,13 +934,13 @@ impl SixtyBytes { impl fmt::Debug for SixtyBytes { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{:?}", self.0.to_vec()) + write!(f, "{:?}", self.0) } } impl fmt::LowerHex for SixtyBytes { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", hex::encode(self.0.to_vec())) + write!(f, "{}", hex::encode(self.0)) } } diff --git a/src/internal/ed25519.rs b/src/internal/ed25519.rs index 34c1f4d..948b177 100644 --- a/src/internal/ed25519.rs +++ b/src/internal/ed25519.rs @@ -5,7 +5,6 @@ use crate::internal::ByteVector; use crate::internal::{array_split_64, take_lock}; use clear_on_drop::clear::Clear; use ed25519_dalek; -use ed25519_dalek::PublicKey; use quick_error::quick_error; use rand; use std; @@ -64,10 +63,10 @@ impl From for [u8; 64] { impl SigningKeypair { const ENCODED_SIZE_BYTES: usize = 64; pub fn new(rng: &Mutex) -> SigningKeypair { - let keypair = ed25519_dalek::Keypair::generate::(&mut *take_lock(rng)); + let signing_key = ed25519_dalek::SigningKey::generate::(&mut *take_lock(rng)); //Unchecked is safe because the public is on the curve and the size is statically guaranteed. - SigningKeypair::new_unchecked(keypair.to_bytes()) + SigningKeypair::new_unchecked(signing_key.to_keypair_bytes()) } /// ///Create a SigningKeypair from a byte array slice. If the array is not the right length or if the public @@ -94,10 +93,10 @@ impl SigningKeypair { /// pub fn from_bytes(sized_bytes: &[u8; 64]) -> Result { let (priv_key, pub_key) = array_split_64(sized_bytes); - //This can't fail because it's statically guaranteed to be 32 bytes long. - let ed25519_dalek_secret = ed25519_dalek::SecretKey::from_bytes(&priv_key).unwrap(); + let ed25519_dalek_secret = ed25519_dalek::SigningKey::from_bytes(&priv_key); //Calculate the public key to check that the value passed in is correct. - let ed25519_dalek_pub = ed25519_dalek::PublicKey::from(&ed25519_dalek_secret); + + let ed25519_dalek_pub = ed25519_dalek::VerifyingKey::from(&ed25519_dalek_secret); if ed25519_dalek_pub.to_bytes() == pub_key { Ok(SigningKeypair::new_unchecked(*sized_bytes)) } else { @@ -151,9 +150,8 @@ pub struct Ed25519; impl Ed25519Signing for Ed25519 { fn sign(&self, t: &T, signing_key: &SigningKeypair) -> Ed25519Signature { use ed25519_dalek::Signer; - //This unwrap cannot fail. The only thing that the `from_bytes` does for validation is that the - //value is 64 bytes long, which we guarantee statically. - let key_pair = ed25519_dalek::Keypair::from_bytes(&signing_key.bytes[..]).unwrap(); + let (priv_key, _) = array_split_64(&signing_key.bytes); + let key_pair = ed25519_dalek::SigningKey::from_bytes(&priv_key); let sig = key_pair.sign(&t.to_bytes()[..]); Ed25519Signature::new(sig.to_bytes()) @@ -166,10 +164,10 @@ impl Ed25519Signing for Ed25519 { ) -> bool { use ed25519_dalek::Verifier; - PublicKey::from_bytes(&public_key.bytes[..]) + ed25519_dalek::VerifyingKey::from_bytes(&public_key.bytes) .and_then(|pk| { - TryFrom::try_from(&signature.bytes[..]) - .and_then(|sig| pk.verify(&t.to_bytes()[..], &sig)) + let sig = ed25519_dalek::Signature::from_bytes(&signature.bytes); + pk.verify(&t.to_bytes()[..], &sig) }) .map(|_| true) .unwrap_or(false) @@ -197,7 +195,6 @@ pub trait Ed25519Signing { pub(crate) mod test { use super::*; use crate::internal::array_concat_32; - use ed25519_dalek::SecretKey; pub fn good_signing_keypair() -> SigningKeypair { SigningKeypair::new_unchecked([ @@ -209,18 +206,13 @@ pub(crate) mod test { #[test] fn real_ed25519_matches_verify_good_message() { - let sec_key = SecretKey::from_bytes(&[1; 32]).unwrap(); - let dalek_pub_key = ed25519_dalek::PublicKey::from(&sec_key); - let priv_key = SigningKeypair { - bytes: array_concat_32(&sec_key.to_bytes(), &dalek_pub_key.to_bytes()), + let sec_key = ed25519_dalek::SigningKey::from_bytes(&[1; 32]); + let keypair = SigningKeypair { + bytes: sec_key.to_keypair_bytes(), }; let message = [100u8; 32].to_vec(); - let result = Ed25519.sign(&message, &priv_key); - let verify_result = Ed25519.verify( - &message, - &result, - &PublicSigningKey::new(dalek_pub_key.to_bytes()), - ); + let result = Ed25519.sign(&message, &keypair); + let verify_result = Ed25519.verify(&message, &result, &keypair.public_key()); assert!(verify_result); } @@ -238,10 +230,9 @@ pub(crate) mod test { #[test] fn signing_keypair_into_bytes() { - let sec_key = SecretKey::from_bytes(&[1; 32]).unwrap(); - let dalek_pub_key = ed25519_dalek::PublicKey::from(&sec_key); + let dalek_pub_key = ed25519_dalek::VerifyingKey::from_bytes(&[1u8; 32]).unwrap(); let key_pair = SigningKeypair { - bytes: array_concat_32(&sec_key.to_bytes(), &dalek_pub_key.to_bytes()), + bytes: array_concat_32(&[1u8; 32], &dalek_pub_key.to_bytes()), }; let key_pair_bytes = key_pair.bytes().clone(); let bytes: [u8; 64] = key_pair.into(); diff --git a/src/lib.rs b/src/lib.rs index a69b7aa..c29ed0c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,4 +1,3 @@ -#![cfg_attr(feature = "unstable", feature(test))] #![doc(html_no_source)] // use github for source browsing //! Recrypt implements a set of cryptographic primitives for building a