From df1b2129c1fc3e05173d218fe74efda14a973377 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pascal=20Eng=C3=A9libert?= Date: Wed, 9 Oct 2024 11:22:08 +0200 Subject: [PATCH] Tmp fixes --- .github/actions-rs/grcov.yml | 2 -- .github/dependabot.yml | 11 ------ .github/workflows/rust-sec.yml | 15 --------- .github/workflows/rust.yml | 60 --------------------------------- Cargo.toml | 8 ++--- LICENSE | 1 + README.md | 9 ++--- benches/double_ratchet_bench.rs | 10 +++--- src/aead.rs | 13 ++++--- src/header.rs | 4 +-- src/ratchet.rs | 12 +++---- tests/mod.rs | 26 +++++++------- 12 files changed, 41 insertions(+), 130 deletions(-) delete mode 100644 .github/actions-rs/grcov.yml delete mode 100644 .github/dependabot.yml delete mode 100644 .github/workflows/rust-sec.yml delete mode 100644 .github/workflows/rust.yml diff --git a/.github/actions-rs/grcov.yml b/.github/actions-rs/grcov.yml deleted file mode 100644 index ba299e9..0000000 --- a/.github/actions-rs/grcov.yml +++ /dev/null @@ -1,2 +0,0 @@ -ignore: - - "../*" \ No newline at end of file diff --git a/.github/dependabot.yml b/.github/dependabot.yml deleted file mode 100644 index f1d26d8..0000000 --- a/.github/dependabot.yml +++ /dev/null @@ -1,11 +0,0 @@ -# To get started with Dependabot version updates, you'll need to specify which -# package ecosystems to update and where the package manifests are located. -# Please see the documentation for all configuration options: -# https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates - -version: 2 -updates: - - package-ecosystem: "cargo" # See documentation for possible values - directory: "/" # Location of package manifests - schedule: - interval: "daily" diff --git a/.github/workflows/rust-sec.yml b/.github/workflows/rust-sec.yml deleted file mode 100644 index 8385c2b..0000000 --- a/.github/workflows/rust-sec.yml +++ /dev/null @@ -1,15 +0,0 @@ -name: Security audit -on: - push: - branches: - - "*" - schedule: - - cron: '0 0 * * *' -jobs: - security_audit: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v1 - - uses: actions-rs/audit-check@v1 - with: - token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml deleted file mode 100644 index b8f3632..0000000 --- a/.github/workflows/rust.yml +++ /dev/null @@ -1,60 +0,0 @@ -name: Rust - -on: - push - -env: - CARGO_TERM_COLOR: always - -jobs: - build-and-test-native: - - strategy: - matrix: - platform: [ubuntu-latest, macos-latest, windows-latest] - - runs-on: ${{ matrix.platform }} - - steps: - - uses: actions/checkout@v2 - # `cargo check` command here will use installed `nightly` - # as it is set as an "override" for current directory - - - name: Run cargo check - run: cargo check - - - name: Run cargo test - run: cargo test - - - name: Run cargo build - run: cargo build - - lint: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - - name: Actions-rs - uses: actions-rs/toolchain@v1 - with: - toolchain: nightly - override: true - - - name: Run Test - uses: actions-rs/cargo@v1 - with: - command: test - args: --all-features --no-fail-fast - env: - CARGO_INCREMENTAL: '0' - RUSTFLAGS: '-Zprofile -Ccodegen-units=1 -Cinline-threshold=0 -Clink-dead-code -Coverflow-checks=off -Cpanic=abort -Zpanic_abort_tests' - RUSTDOCFLAGS: '-Zprofile -Ccodegen-units=1 -Cinline-threshold=0 -Clink-dead-code -Coverflow-checks=off -Cpanic=abort -Zpanic_abort_tests' - - - id: coverage - uses: actions-rs/grcov@v0.1 - - - name: Coveralls upload - uses: coverallsapp/github-action@master - with: - github-token: ${{ secrets.GITHUB_TOKEN }} - path-to-lcov: ${{ steps.coverage.outputs.report }} diff --git a/Cargo.toml b/Cargo.toml index febf231..41c060e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,20 +1,20 @@ [package] name = "double-ratchet-rs" version = "0.4.6" -authors = ["satvrn", "Hannes Furmans"] +authors = ["satvrn", "Hannes Furmans", "Pascal Engélibert"] edition = "2021" rust-version = "1.60" description = "A pure Rust implementation of the Double Ratchet algorithm as described by Signal." documentation = "https://docs.rs/double-ratchet-rs" readme = "README.md" -homepage = "https://github.com/notsatvrn/double-ratchet-rs" -repository = "https://github.com/notsatvrn/double-ratchet-rs" +homepage = "https://git.txmn.tk/tuxmain/double-ratchet-rs" +repository = "https://git.txmn.tk/tuxmain/double-ratchet-rs" license = "MIT" keywords = ["double-ratchet", "signal"] categories = ["algorithms", "cryptography", "no-std"] [dependencies] -x25519-dalek = {version = "2.0.0-rc.3", default-features = false, features = ["serde", "static_secrets", "zeroize"]} +x25519-dalek = {version = "2", default-features = false, features = ["serde", "static_secrets", "zeroize"]} rand_core = "0.6" hkdf = "0.12" hmac = "0.12" diff --git a/LICENSE b/LICENSE index 3c6abbe..4db28bc 100644 --- a/LICENSE +++ b/LICENSE @@ -2,6 +2,7 @@ MIT License Copyright (c) 2023 satvrn Copyright (c) 2021 Hannes Furmans +Copyright (c) 2024 Pascal Engélibert Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index 150dc01..c97f16d 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,3 @@ -[![Crate](https://img.shields.io/crates/v/double-ratchet-rs)](https://crates.io/crates/double-ratchet-rs) -[![License](https://img.shields.io/github/license/notsatvrn/double-ratchet-rs)](https://github.com/notsatvrn/double-ratchet-rs/blob/main/LICENSE) -[![Coverage Status](https://coveralls.io/repos/github/notsatvrn/double-ratchet-rs/badge.svg?branch=main)](https://coveralls.io/github/notsatvrn/double-ratchet-rs?branch=main) -[![Workflow Status](https://github.com/notsatvrn/double-ratchet-rs/actions/workflows/rust.yml/badge.svg)](https://github.com/notsatvrn/double-ratchet-rs/actions/workflows/rust.yml) - # double-ratchet-rs A pure Rust implementation of the Double Ratchet algorithm as described by [Signal][1]. @@ -10,7 +5,7 @@ A pure Rust implementation of the Double Ratchet algorithm as described by [Sign This implementation follows the cryptographic recommendations provided by [Signal][2]. The AEAD algorithm uses a constant Nonce. This might be changed in the future. -Fork of [double-ratchet-2](https://github.com/Dione-Software/double-ratchet-2). +Temporary fork of [double-ratchet-rs](https://github.com/notsatvrn/double-ratchet-rs), which is published on crates.io. Use this one instead because my fork is published for a proof of concept only, not meant to stay forever. ## Examples @@ -174,7 +169,7 @@ The current MSRV is 1.60.0 without `hashbrown` and 1.64.0 with `hashbrown`. ## License -This project is licensed under the [MIT license](https://github.com/notsatvrn/double-ratchet-rs/blob/main/LICENSE). +This project is licensed under the [MIT license](https://git.txmn.tk/tuxmain/double-ratchet-rs/blob/main/LICENSE). [1]: https://signal.org/docs/specifications/doubleratchet/ [2]: https://signal.org/docs/specifications/doubleratchet/#recommended-cryptographic-algorithms diff --git a/benches/double_ratchet_bench.rs b/benches/double_ratchet_bench.rs index 82274eb..2ad5baf 100644 --- a/benches/double_ratchet_bench.rs +++ b/benches/double_ratchet_bench.rs @@ -35,9 +35,9 @@ fn ratchet_encrypt_decrypt_four() { let (mut bob_ratchet, public_key) = Ratchet::init_bob(sk); let mut alice_ratchet = Ratchet::init_alice(sk, public_key); let (header1, encrypted1, nonce1) = alice_ratchet.encrypt(&data, b""); - let _decrypted1 = bob_ratchet.decrypt(&header1, &encrypted1, &nonce1, b""); + let _decrypted1 = bob_ratchet.decrypt(&header1, &encrypted1, &nonce1, b"").unwrap(); let (header2, encrypted2, nonce2) = bob_ratchet.encrypt(&data, b""); - let _decrypted2 = alice_ratchet.decrypt(&header2, &encrypted2, &nonce2, b""); + let _decrypted2 = alice_ratchet.decrypt(&header2, &encrypted2, &nonce2, b"").unwrap(); } fn criterion_benchmark_3(c: &mut Criterion) { @@ -54,7 +54,7 @@ fn ratchet_ench_enc_single() { let mut alice_ratchet = RatchetEncHeader::init_alice(sk, public_key, shared_hka, shared_nhkb); let data = include_bytes!("../src/header.rs").to_vec(); let (header, encrypted, nonce) = alice_ratchet.encrypt(&data, b""); - let decrypted = bob_ratchet.decrypt(&header, &encrypted, &nonce, b""); + let decrypted = bob_ratchet.decrypt(&header, &encrypted, &nonce, b"").unwrap(); assert_eq!(data, decrypted) } @@ -91,9 +91,9 @@ fn ratchet_ench_decrypt_four() { let mut alice_ratchet = RatchetEncHeader::init_alice(sk, public_key, shared_hka, shared_nhkb); let data = include_bytes!("../src/dh.rs").to_vec(); let (header1, encrypted1, nonce1) = alice_ratchet.encrypt(&data, b""); - let _decrypted1 = bob_ratchet.decrypt(&header1, &encrypted1, &nonce1, b""); + let _decrypted1 = bob_ratchet.decrypt(&header1, &encrypted1, &nonce1, b"").unwrap(); let (header2, encrypted2, nonce2) = bob_ratchet.encrypt(&data, b""); - let _decrypted2 = alice_ratchet.decrypt(&header2, &encrypted2, &nonce2, b""); + let _decrypted2 = alice_ratchet.decrypt(&header2, &encrypted2, &nonce2, b"").unwrap(); } fn criterion_benchmark_6(c: &mut Criterion) { diff --git a/src/aead.rs b/src/aead.rs index 5c6e897..d15c1b1 100644 --- a/src/aead.rs +++ b/src/aead.rs @@ -22,13 +22,16 @@ pub fn encrypt(mk: &[u8; 32], data: &[u8], associated_data: &[u8]) -> (Vec, (buffer, nonce_data) } +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct InvalidAd; + pub fn decrypt( mk: &[u8; 32], enc_data: &[u8], associated_data: &[u8], nonce: &[u8; 12], -) -> Vec { - let cipher = Aes256GcmSiv::new_from_slice(mk).expect("Decryption failure {}"); +) -> Result, InvalidAd> { + let cipher = Aes256GcmSiv::new_from_slice(mk).expect("unreachable"); let nonce = Nonce::from_slice(nonce); @@ -37,9 +40,9 @@ pub fn decrypt( cipher .decrypt_in_place(nonce, associated_data, &mut buffer) - .expect("Decryption failure {}"); + .map_err(|_| InvalidAd)?; - buffer + Ok(buffer) } #[cfg(test)] @@ -53,7 +56,7 @@ mod tests { let associated_data = include_bytes!("lib.rs"); let mk = gen_mk(); let (enc_data, nonce) = encrypt(&mk, test_data, associated_data); - let data = decrypt(&mk, &enc_data, associated_data, &nonce); + let data = decrypt(&mk, &enc_data, associated_data, &nonce).unwrap(); assert_eq!(test_data, data.as_slice()) } } diff --git a/src/header.rs b/src/header.rs index 45bec21..6a59074 100644 --- a/src/header.rs +++ b/src/header.rs @@ -14,7 +14,7 @@ use alloc::vec::Vec; #[derive(Serialize, Deserialize, Debug, Zeroize, Clone, PartialEq, Eq)] #[zeroize(drop)] pub struct Header { - ad: Vec, + pub ad: Vec, pub public_key: PublicKey, pub pn: usize, pub n: usize, @@ -122,7 +122,7 @@ mod tests { let header_data = header.concat(b""); let data = include_bytes!("aead.rs"); let (encrypted, nonce) = encrypt(&mk, data, &header_data); - let decrypted = decrypt(&mk, &encrypted, &header_data, &nonce); + let decrypted = decrypt(&mk, &encrypted, &header_data, &nonce).unwrap(); assert_eq!(decrypted, data.to_vec()) } diff --git a/src/ratchet.rs b/src/ratchet.rs index b6a60e7..57c9c2b 100644 --- a/src/ratchet.rs +++ b/src/ratchet.rs @@ -1,6 +1,6 @@ //! Ratchet providing encryption and decryption. -use crate::aead::{decrypt, encrypt}; +use crate::aead::{decrypt, encrypt, InvalidAd}; use crate::dh::DhKeyPair; use crate::header::{EncryptedHeader, Header}; use crate::kdf_chain::kdf_ck; @@ -108,7 +108,7 @@ impl Ratchet { enc_data: &[u8], nonce: &[u8; 12], associated_data: &[u8], - ) -> Option> { + ) -> Option, InvalidAd>> { if self .mkskipped .contains_key(&(header.public_key.to_bytes(), header.n)) @@ -160,7 +160,7 @@ impl Ratchet { enc_data: &[u8], nonce: &[u8; 12], associated_data: &[u8], - ) -> Vec { + ) -> Result, InvalidAd> { let data = self.try_skipped_message_keys(header, enc_data, nonce, associated_data); match data { Some(d) => d, @@ -328,7 +328,7 @@ impl RatchetEncHeader { enc_data: &[u8], nonce: &[u8; 12], associated_data: &[u8], - ) -> (Option>, Option
) { + ) -> (Option, InvalidAd>>, Option
) { let ret_data = self.mkskipped.clone().into_iter().find(|e| { let header = enc_header.decrypt(&e.0 .0); match header { @@ -412,7 +412,7 @@ impl RatchetEncHeader { enc_data: &[u8], nonce: &[u8; 12], associated_data: &[u8], - ) -> Vec { + ) -> Result, InvalidAd> { let (data, _) = self.try_skipped_message_keys(enc_header, enc_data, nonce, associated_data); if let Some(d) = data { return d; @@ -438,7 +438,7 @@ impl RatchetEncHeader { enc_data: &[u8], nonce: &[u8; 12], associated_data: &[u8], - ) -> (Vec, Header) { + ) -> (Result, InvalidAd>, Header) { let (data, header) = self.try_skipped_message_keys(enc_header, enc_data, nonce, associated_data); if let Some(d) = data { diff --git a/tests/mod.rs b/tests/mod.rs index ef73951..483bd1e 100644 --- a/tests/mod.rs +++ b/tests/mod.rs @@ -20,7 +20,7 @@ fn enc_single() { let mut alice_ratchet = Ratchet::init_alice(sk, public_key); let data = include_bytes!("../src/header.rs").to_vec(); let (header, encrypted, nonce) = alice_ratchet.encrypt(&data, b""); - let decrypted = bob_ratchet.decrypt(&header, &encrypted, &nonce, b""); + let decrypted = bob_ratchet.decrypt(&header, &encrypted, &nonce, b"").unwrap(); assert_eq!(data, decrypted) } @@ -33,9 +33,9 @@ fn enc_skip() { let (header1, encrypted1, nonce1) = alice_ratchet.encrypt(&data, b""); let (header2, encrypted2, nonce2) = alice_ratchet.encrypt(&data, b""); let (header3, encrypted3, nonce3) = alice_ratchet.encrypt(&data, b""); - let decrypted3 = bob_ratchet.decrypt(&header3, &encrypted3, &nonce3, b""); - let decrypted2 = bob_ratchet.decrypt(&header2, &encrypted2, &nonce2, b""); - let decrypted1 = bob_ratchet.decrypt(&header1, &encrypted1, &nonce1, b""); + let decrypted3 = bob_ratchet.decrypt(&header3, &encrypted3, &nonce3, b"").unwrap(); + let decrypted2 = bob_ratchet.decrypt(&header2, &encrypted2, &nonce2, b"").unwrap(); + let decrypted1 = bob_ratchet.decrypt(&header1, &encrypted1, &nonce1, b"").unwrap(); let comp_res = decrypted1 == data && decrypted2 == data && decrypted3 == data; assert!(comp_res) } @@ -56,9 +56,9 @@ fn encryt_decrypt_four() { let (mut bob_ratchet, public_key) = Ratchet::init_bob(sk); let mut alice_ratchet = Ratchet::init_alice(sk, public_key); let (header1, encrypted1, nonce1) = alice_ratchet.encrypt(&data, b""); - let decrypted1 = bob_ratchet.decrypt(&header1, &encrypted1, &nonce1, b""); + let decrypted1 = bob_ratchet.decrypt(&header1, &encrypted1, &nonce1, b"").unwrap(); let (header2, encrypted2, nonce2) = bob_ratchet.encrypt(&data, b""); - let decrypted2 = alice_ratchet.decrypt(&header2, &encrypted2, &nonce2, b""); + let decrypted2 = alice_ratchet.decrypt(&header2, &encrypted2, &nonce2, b"").unwrap(); let comp_res = decrypted1 == data && decrypted2 == data; assert!(comp_res) } @@ -81,7 +81,7 @@ fn ench_enc_single() { let mut alice_ratchet = RatchetEncHeader::init_alice(sk, public_key, shared_hka, shared_nhkb); let data = include_bytes!("../src/header.rs").to_vec(); let (header, encrypted, nonce) = alice_ratchet.encrypt(&data, b""); - let decrypted = bob_ratchet.decrypt(&header, &encrypted, &nonce, b""); + let decrypted = bob_ratchet.decrypt(&header, &encrypted, &nonce, b"").unwrap(); assert_eq!(data, decrypted) } @@ -96,9 +96,9 @@ fn ench_enc_skip() { let (header1, encrypted1, nonce1) = alice_ratchet.encrypt(&data, b""); let (header2, encrypted2, nonce2) = alice_ratchet.encrypt(&data, b""); let (header3, encrypted3, nonce3) = alice_ratchet.encrypt(&data, b""); - let decrypted3 = bob_ratchet.decrypt(&header3, &encrypted3, &nonce3, b""); - let decrypted2 = bob_ratchet.decrypt(&header2, &encrypted2, &nonce2, b""); - let decrypted1 = bob_ratchet.decrypt(&header1, &encrypted1, &nonce1, b""); + let decrypted3 = bob_ratchet.decrypt(&header3, &encrypted3, &nonce3, b"").unwrap(); + let decrypted2 = bob_ratchet.decrypt(&header2, &encrypted2, &nonce2, b"").unwrap(); + let decrypted1 = bob_ratchet.decrypt(&header1, &encrypted1, &nonce1, b"").unwrap(); let comp_res = decrypted1 == data && decrypted2 == data && decrypted3 == data; assert!(comp_res) } @@ -123,9 +123,9 @@ fn ench_decrypt_four() { let mut alice_ratchet = RatchetEncHeader::init_alice(sk, public_key, shared_hka, shared_nhkb); let data = include_bytes!("../src/dh.rs").to_vec(); let (header1, encrypted1, nonce1) = alice_ratchet.encrypt(&data, b""); - let decrypted1 = bob_ratchet.decrypt(&header1, &encrypted1, &nonce1, b""); + let decrypted1 = bob_ratchet.decrypt(&header1, &encrypted1, &nonce1, b"").unwrap(); let (header2, encrypted2, nonce2) = bob_ratchet.encrypt(&data, b""); - let decrypted2 = alice_ratchet.decrypt(&header2, &encrypted2, &nonce2, b""); + let decrypted2 = alice_ratchet.decrypt(&header2, &encrypted2, &nonce2, b"").unwrap(); let comp_res = decrypted1 == data && decrypted2 == data; assert!(comp_res) } @@ -156,7 +156,7 @@ fn ench_enc_skip_panic() { let header = headers.get(idx).unwrap(); let encrypted = encrypteds.get(idx).unwrap(); let nonce = nonces.get(idx).unwrap(); - let decrypted = bob_ratchet.decrypt(header, encrypted, nonce, b""); + let decrypted = bob_ratchet.decrypt(header, encrypted, nonce, b"").unwrap(); decrypteds.push(decrypted); } }