diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 85de51c..a9b630e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -27,7 +27,7 @@ jobs: - target: x86_64-unknown-linux-gnu steps: - uses: actions/checkout@v3 - - uses: dtolnay/rust-toolchain@stable + - uses: dtolnay/rust-toolchain@1.91.1 - run: cargo --version - run: cargo test --all-features @@ -35,14 +35,14 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - - uses: dtolnay/rust-toolchain@stable + - uses: dtolnay/rust-toolchain@1.91.1 - run: cargo fmt --all -- --check clippy: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - - uses: dtolnay/rust-toolchain@stable + - uses: dtolnay/rust-toolchain@1.91.1 with: components: clippy - run: cargo clippy --all-features -- -D warnings @@ -55,14 +55,14 @@ jobs: - uses: actions/checkout@v3 - uses: dtolnay/rust-toolchain@master with: - toolchain: stable + toolchain: "1.91.1" targets: thumbv7em-none-eabi - uses: taiki-e/install-action@cargo-hack # No default features build - name: no_std / no feat run: cargo build --target thumbv7em-none-eabi --release --no-default-features - name: no_std / cargo hack - run: cargo hack build --target thumbv7em-none-eabi --release --each-feature --exclude-features default,std + run: cargo hack build --target thumbv7em-none-eabi --release --each-feature --exclude-features default,kat msrv: name: rust-version is MSRV @@ -70,7 +70,7 @@ jobs: continue-on-error: true steps: - uses: actions/checkout@v4 - - uses: dtolnay/rust-toolchain@stable + - uses: dtolnay/rust-toolchain@1.91.1 - run: cargo +nightly install cargo-msrv --no-default-features - run: cargo +nightly msrv --version - run: cargo +nightly msrv verify --all-features diff --git a/CHANGELOG.md b/CHANGELOG.md index e42af0d..9aa4f60 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,10 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## Unrelease + +* Renamed `std` feature to `kat`. Not breaking bc this is only used in testing + ## [0.11.0] - 2025-11-24 * Removed `std` flag from all but testing use diff --git a/Cargo.lock b/Cargo.lock index 39c29a0..239cfdd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -98,18 +98,18 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.51" +version = "4.5.54" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c26d721170e0295f191a69bd9a1f93efcdb0aff38684b61ab5750468972e5f5" +checksum = "c6e6ff9dcd79cff5cd969a17a545d79e84ab086e444102a591e288a8aa3ce394" dependencies = [ "clap_builder", ] [[package]] name = "clap_builder" -version = "4.5.51" +version = "4.5.54" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75835f0c7bf681bfd05abe44e965760fea999a5286c6eb2d59883634fd02011a" +checksum = "fa42cf4d2b7a41bc8f663a7cab4031ebafa1bf3875705bfaf8466dc60ab52c00" dependencies = [ "anstyle", "clap_lex", @@ -117,9 +117,9 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.7.6" +version = "0.7.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1d728cc89cf3aee9ff92b05e62b19ee65a02b5702cff7d5a377e32c6ae29d8d" +checksum = "c3e64b0cc0439b12df2fa678eae89a1c56a529fd067a9115f7827f1fffd22b32" [[package]] name = "cpufeatures" @@ -132,25 +132,22 @@ dependencies = [ [[package]] name = "criterion" -version = "0.5.1" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2b12d017a929603d80db1831cd3a24082f8137ce19c69e6447f54f5fc8d692f" +checksum = "e1c047a62b0cc3e145fa84415a3191f628e980b194c2755aa12300a4e6cbd928" dependencies = [ "anes", "cast", "ciborium", "clap", "criterion-plot", - "is-terminal", "itertools", "num-traits", - "once_cell", "oorandom", "plotters", "rayon", "regex", "serde", - "serde_derive", "serde_json", "tinytemplate", "walkdir", @@ -158,9 +155,9 @@ dependencies = [ [[package]] name = "criterion-plot" -version = "0.5.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b50826342786a51a89e2da3a28f1c32b06e387201bc2d19791f622c673706b1" +checksum = "9b1bcc0dc7dfae599d84ad0b1a55f80cde8af3725da8313b528da95ef783e338" dependencies = [ "cast", "itertools", @@ -205,13 +202,14 @@ checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" [[package]] name = "getrandom" -version = "0.2.16" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" +checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" dependencies = [ "cfg-if", "libc", - "wasi", + "r-efi", + "wasip2", ] [[package]] @@ -225,43 +223,26 @@ dependencies = [ "zerocopy", ] -[[package]] -name = "hermit-abi" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" - [[package]] name = "hex" version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" -[[package]] -name = "is-terminal" -version = "0.4.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3640c1c38b8e4e43584d8df18be5fc6b0aa314ce6ebf51b53313d4306cca8e46" -dependencies = [ - "hermit-abi", - "libc", - "windows-sys", -] - [[package]] name = "itertools" -version = "0.10.5" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" dependencies = [ "either", ] [[package]] name = "itoa" -version = "1.0.15" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" +checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2" [[package]] name = "js-sys" @@ -284,9 +265,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.177" +version = "0.2.180" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976" +checksum = "bcc35a38544a891a5f7c865aca548a982ccb3b8650a5b06d0fd33a10283c56fc" [[package]] name = "memchr" @@ -354,38 +335,43 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.103" +version = "1.0.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.42" +version = "1.0.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a338cc41d27e6cc6dce6cefc13a0729dfbb81c262b1f519331575dd80ef3067f" +checksum = "21b2ebcf727b7760c461f091f9f0f539b77b8e87f2fd88131e7f1b433b3cece4" dependencies = [ "proc-macro2", ] +[[package]] +name = "r-efi" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" + [[package]] name = "rand" -version = "0.8.5" +version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" dependencies = [ - "libc", "rand_chacha", "rand_core", ] [[package]] name = "rand_chacha" -version = "0.3.1" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" dependencies = [ "ppv-lite86", "rand_core", @@ -393,9 +379,9 @@ dependencies = [ [[package]] name = "rand_core" -version = "0.6.4" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c" dependencies = [ "getrandom", ] @@ -455,12 +441,6 @@ version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" -[[package]] -name = "ryu" -version = "1.0.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" - [[package]] name = "same-file" version = "1.0.6" @@ -511,15 +491,15 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.145" +version = "1.0.149" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c" +checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" dependencies = [ "itoa", "memchr", - "ryu", "serde", "serde_core", + "zmij", ] [[package]] @@ -548,9 +528,9 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "syn" -version = "2.0.110" +version = "2.0.114" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a99801b5bd34ede4cf3fc688c5919368fea4e4814a4664359503e6015b280aea" +checksum = "d4d107df263a3013ef9b1879b0df87d706ff80f65a86ea879bd9c31f9b307c2a" dependencies = [ "proc-macro2", "quote", @@ -584,10 +564,13 @@ dependencies = [ ] [[package]] -name = "wasi" -version = "0.11.1+wasi-snapshot-preview1" +name = "wasip2" +version = "1.0.2+wasi-0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" +checksum = "9517f9239f02c069db75e65f174b3da828fe5f5b945c4dd26bd25d89c03ebcf5" +dependencies = [ + "wit-bindgen", +] [[package]] name = "wasm-bindgen" @@ -668,20 +651,26 @@ dependencies = [ "windows-link", ] +[[package]] +name = "wit-bindgen" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" + [[package]] name = "zerocopy" -version = "0.8.27" +version = "0.8.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0894878a5fa3edfd6da3f88c4805f4c8558e2b996227a3d864f47fe11e38282c" +checksum = "668f5168d10b9ee831de31933dc111a459c97ec93225beb307aed970d1372dfd" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.27" +version = "0.8.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88d2b8d9c68ad2b9e4340d7832716a4d21a22a1154777ad56ea55c51a9cf3831" +checksum = "2c7962b26b0a8685668b671ee4b54d007a67d4eaf05fda79ac0ecf41e32270f1" dependencies = [ "proc-macro2", "quote", @@ -707,3 +696,9 @@ dependencies = [ "quote", "syn", ] + +[[package]] +name = "zmij" +version = "1.0.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfcd145825aace48cff44a8844de64bf75feec3080e0aa5cdbde72961ae51a65" diff --git a/Cargo.toml b/Cargo.toml index adf71a0..5659a17 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,7 +14,7 @@ rust-version = "1.81" [features] default = [] -std = [] +kat = [] asm = ["keccak/asm"] serialize_secret_state = ["serde", "serde-big-array"] @@ -31,9 +31,9 @@ subtle = { version = "2.6", default-features = false } zeroize = { version = "1.8", features = ["derive"] } [dev-dependencies] -criterion = { version = "0.5", features = ["html_reports"] } +criterion = { version = "0.7", features = ["html_reports"] } hex = "0.4" -rand = "0.8.5" +rand = "0.9.2" serde_json = "1" # Criteron benches diff --git a/README.md b/README.md index c66e1b0..3df6179 100644 --- a/README.md +++ b/README.md @@ -17,50 +17,47 @@ A simple [example](https://github.com/rozbb/strobe-rs/blob/master/examples/basic ```rust use strobe_rs::{SecParam, Strobe}; - use rand::RngCore; // NOTE: This is just a simple authenticated encryption scheme. For a robust AEAD construction, // see the example at https://strobe.sourceforge.io/examples/aead/ -fn main() { - let mut rng = rand::thread_rng(); - - // Sender and receiver - let mut tx = Strobe::new(b"correctnesstest", SecParam::B256); - let mut rx = Strobe::new(b"correctnesstest", SecParam::B256); - - // Key both sides with a predetermined key - let k = b"the-combination-on-my-luggage"; - tx.key(k, false); - rx.key(k, false); - - // Have the transmitter sample and send a nonce (192 bits) in the clear - let mut nonce = [0u8; 24]; - rng.fill_bytes(&mut nonce); - rx.recv_clr(&nonce, false); - tx.send_clr(&nonce, false); - - // Have the transmitter send an authenticated ciphertext (with a 256 bit MAC) - let orig_msg = b"groceries: kaymac, ajvar, cream, diced onion, red pepper, grilled meat"; - let mut msg_buf = *orig_msg; - tx.send_enc(&mut msg_buf, false); - let mut mac = [0u8; 32]; - tx.send_mac(&mut mac, false); - - // Rename for clarity. `msg_buf` has been encrypted in-place. - let mut ciphertext = msg_buf; - - // Have the receiver receive the ciphertext and MAC - rx.recv_enc(ciphertext.as_mut_slice(), false); - let res = rx.recv_mac(&mac); - - // Check that the MAC verifies - assert!(res.is_ok()); - // Check that the decrypted ciphertext equals the original plaintext - let round_trip_msg = ciphertext; - assert_eq!(&round_trip_msg, orig_msg); -} +let mut rng = rand::rng(); + +// Sender and receiver +let mut tx = Strobe::new(b"correctnesstest", SecParam::B256); +let mut rx = Strobe::new(b"correctnesstest", SecParam::B256); + +// Key both sides with a predetermined key +let k = b"the-combination-on-my-luggage"; +tx.key(k, false); +rx.key(k, false); + +// Have the transmitter sample and send a nonce (192 bits) in the clear +let mut nonce = [0u8; 24]; +rng.fill_bytes(&mut nonce); +rx.recv_clr(&nonce, false); +tx.send_clr(&nonce, false); + +// Have the transmitter send an authenticated ciphertext (with a 256 bit MAC) +let orig_msg = b"groceries: kaymac, ajvar, cream, diced onion, red pepper, grilled meat"; +let mut msg_buf = *orig_msg; +tx.send_enc(&mut msg_buf, false); +let mut mac = [0u8; 32]; +tx.send_mac(&mut mac, false); + +// Rename for clarity. `msg_buf` has been encrypted in-place. +let mut ciphertext = msg_buf; + +// Have the receiver receive the ciphertext and MAC +rx.recv_enc(ciphertext.as_mut_slice(), false); +let res = rx.recv_mac(&mac); + +// Check that the MAC verifies +assert!(res.is_ok()); +// Check that the decrypted ciphertext equals the original plaintext +let round_trip_msg = ciphertext; +assert_eq!(&round_trip_msg, orig_msg); ``` Features @@ -72,7 +69,7 @@ Feature flag list: * `asm` — Enables optimized assembly for the Keccak permutation, if available. Assembly currently only exists for ARMv8. * `serialize_secret_state` — Implements `serde`'s `Serialize` and `Deserialize` traits for the `Strobe` struct. **SECURITY NOTE**: Serializing Strobe state outputs security sensitive data that MUST be kept private. Treat the data as you would a private encryption/decryption key. -* `std` — Required for running known-answer tests. Use only when testing. +* `kat` — Required for running known-answer tests. Use only when testing. For info on how to omit or include feature flags, see the [cargo docs on features](https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#choosing-features). diff --git a/examples/basic.rs b/examples/basic.rs index 8f734d4..92e103c 100644 --- a/examples/basic.rs +++ b/examples/basic.rs @@ -6,7 +6,7 @@ use rand::RngCore; // see the example at https://strobe.sourceforge.io/examples/aead/ fn main() { - let mut rng = rand::thread_rng(); + let mut rng = rand::rng(); // Sender and receiver let mut tx = Strobe::new(b"correctnesstest", SecParam::B256); diff --git a/src/basic_tests.rs b/src/basic_tests.rs index 3cc7084..11dce8f 100644 --- a/src/basic_tests.rs +++ b/src/basic_tests.rs @@ -96,7 +96,7 @@ s.send_mac() print("[{}]".format(', '.join(map("0x{:02x}".format, s.st)))) */ -#[cfg(feature = "std")] +#[cfg(feature = "kat")] #[test] fn test_seq() { let mut s = Strobe::new(b"seqtest", SecParam::B256); @@ -163,7 +163,7 @@ m += s.send_enc("pt", meta_flags=A|T|M, metadata="meta3") print("accumulated metadata == [{}]".format(', '.join(map("0x{:02x}".format, m)))) print("state == [{}]".format(', '.join(map("0x{:02x}".format, s.st)))) */ -#[cfg(feature = "std")] +#[cfg(feature = "kat")] #[test] fn test_metadata() { // We will accumulate output over 3 operations and 3 meta-operations @@ -310,7 +310,7 @@ fn test_long_inputs() { } // Test that streaming in data using the `more` flag works as expected -#[cfg(feature = "std")] +#[cfg(feature = "kat")] #[test] fn test_streaming_correctness() { // Compute a few things without breaking up their inputs diff --git a/src/lib.rs b/src/lib.rs index 3279c2a..8f58d7d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,12 +1,11 @@ -#![allow(clippy::needless_doctest_main)] #![doc = include_str!("../README.md")] // The doc_auto_cfg feature is only available in nightly. It auto-marks items in documentation as // dependent on specific features. -#![cfg_attr(docsrs, feature(doc_auto_cfg))] +#![cfg_attr(docsrs, feature(doc_cfg))] //-------- no_std stuff --------// #![no_std] -#[cfg(all(test, feature = "std"))] +#[cfg(all(test, feature = "kat"))] #[macro_use] extern crate std; @@ -14,8 +13,7 @@ extern crate std; #[cfg(test)] mod basic_tests; -// kat_tests requires std -#[cfg(all(test, feature = "std"))] +#[cfg(all(test, feature = "kat"))] mod kat_tests; //-------- Modules and exports--------// diff --git a/src/strobe.rs b/src/strobe.rs index 357574c..81fbeb4 100644 --- a/src/strobe.rs +++ b/src/strobe.rs @@ -90,20 +90,16 @@ impl core::fmt::Display for AuthError { /// ```rust /// # extern crate strobe_rs; /// # use strobe_rs::{SecParam, Strobe}; -/// # fn main() { /// # let mut s = Strobe::new(b"example-of-more", SecParam::B128); /// s.ad(b"hello world", false); -/// # } /// ``` /// is equivalent to /// ```rust /// # extern crate strobe_rs; /// # use strobe_rs::{SecParam, Strobe}; -/// # fn main() { /// # let mut s = Strobe::new(b"example-of-more", SecParam::B128); /// s.ad(b"hello ", false); /// s.ad(b"world", true); -/// # } /// ``` /// /// **NOTE:** If you try to set the `more` flag for an operation that is not preceded by the same @@ -117,7 +113,7 @@ impl core::fmt::Display for AuthError { pub struct Strobe { /// Internal Keccak state pub(crate) st: AlignedKeccakState, - /// Security parameter (128 or 256) + /// Security parameter (128 or 256 bits) #[zeroize(skip)] sec: SecParam, /// This is the `R` parameter in the Strobe spec @@ -199,9 +195,10 @@ impl Strobe { strobe } - /// Returns a bytestring of the form `Strobe-Keccak-SEC/B-vVER` where `SEC` is the bits of - /// security (128 or 256), `B` is the block size (in bits) of the Keccak permutation function, - /// and `VER` is the protocol version. + /// Returns a bytestring of the form `Strobe-Keccak-SEC/B-vVER` where `SEC` is the + /// bits of security (128 or 256), `B` is the block size (in bits) of the Keccak + /// permutation function (currently this can only be 1600), and `VER` is the protocol + /// version. pub fn version_str(&self) -> [u8; TEMPLATE_VERSION_STR.len()] { let mut buf = TEMPLATE_VERSION_STR; @@ -515,7 +512,9 @@ impl Strobe { self.zero_state(num_bytes_to_zero); } - /// Ratchets the internal state forward in an irreversible way by zeroing bytes. + /// Ratchets the internal state forward in an irreversible way by zeroing bytes. If + /// the security parameter is 128, then `num_bytes_to_zero = 16` is sufficient. If + /// it's 256, then `num_bytes_to_zero = 32` is sufficient. /// /// Takes a `usize` argument specifying the number of bytes of public state to zero. If the /// size exceeds `self.rate`, Keccak-f will be called before more bytes are zeroed.