Skip to content

Commit

Permalink
Run cargo fmt
Browse files Browse the repository at this point in the history
  • Loading branch information
quexten committed Dec 2, 2024
1 parent 041769b commit fdde35c
Show file tree
Hide file tree
Showing 2 changed files with 79 additions and 35 deletions.
18 changes: 14 additions & 4 deletions crates/bitwarden-crypto/benches/ciphers.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
use bitwarden_crypto::chacha20::{decrypt_xchacha20_poly1305_blake3_ctx, encrypt_xchacha20_poly1305_blake3_ctx};
use bitwarden_crypto::chacha20::{
decrypt_xchacha20_poly1305_blake3_ctx, encrypt_xchacha20_poly1305_blake3_ctx,
};
use criterion::{black_box, criterion_group, criterion_main, Criterion};

pub fn criterion_benchmark(c: &mut Criterion) {
Expand All @@ -9,11 +11,19 @@ pub fn criterion_benchmark(c: &mut Criterion) {
let authenticated_data = authenticated_data.as_slice();

c.bench_function("encrypt_xchacha20_poly1305_blake3_ctx", |b| {
b.iter(|| encrypt_xchacha20_poly1305_blake3_ctx(black_box(&key), black_box(plaintext_secret_data), black_box(authenticated_data)))
b.iter(|| {
encrypt_xchacha20_poly1305_blake3_ctx(
black_box(&key),
black_box(plaintext_secret_data),
black_box(authenticated_data),
)
})
});

let encrypted = encrypt_xchacha20_poly1305_blake3_ctx(&key, plaintext_secret_data, authenticated_data).unwrap();

let encrypted =
encrypt_xchacha20_poly1305_blake3_ctx(&key, plaintext_secret_data, authenticated_data)
.unwrap();

c.bench_function("encrypt_xchacha20_poly1305_blake3_ctx", |b| {
b.iter(|| decrypt_xchacha20_poly1305_blake3_ctx(black_box(&key), black_box(&encrypted)))
});
Expand Down
96 changes: 65 additions & 31 deletions crates/bitwarden-crypto/src/chacha20.rs
Original file line number Diff line number Diff line change
@@ -1,23 +1,21 @@
/**
* Note:
* XChaCha20Poly1305-CTX encrypts data, and authenticates associated data using XChaCha20Poly1305
* Specifically, this uses the CTX construction, proposed here: https://par.nsf.gov/servlets/purl/10391723
* using blake3 as the cryptographic hash function. This provides not only key-commitment, but full-commitment.
* In total, this scheme prevents attacks such as invisible salamanders.
*/

use crate::CryptoError;
use chacha20poly1305::AeadCore;
use chacha20poly1305::AeadInPlace;
use chacha20poly1305::KeyInit;
use chacha20poly1305::XChaCha20Poly1305;
use chacha20::XChaCha20;
use chacha20::{
cipher::{KeyIvInit, StreamCipher},
XChaCha20,
};
use chacha20poly1305::{AeadCore, AeadInPlace, KeyInit, XChaCha20Poly1305};
use generic_array::GenericArray;
use poly1305::Poly1305;
use poly1305::{universal_hash::UniversalHash, Poly1305};
use subtle::ConstantTimeEq;
use chacha20::cipher::{KeyIvInit, StreamCipher};

use poly1305::universal_hash::UniversalHash;
/**
* Note:
* XChaCha20Poly1305-CTX encrypts data, and authenticates associated data using
* XChaCha20Poly1305 Specifically, this uses the CTX construction, proposed here: https://par.nsf.gov/servlets/purl/10391723
* using blake3 as the cryptographic hash function. This provides not only key-commitment,
* but full-commitment. In total, this scheme prevents attacks such as invisible
* salamanders.
*/
use crate::CryptoError;

pub struct XChaCha20Poly1305CTXCiphetext {
nonce: [u8; 24],
Expand All @@ -32,7 +30,12 @@ pub fn encrypt_xchacha20_poly1305_blake3_ctx(
plaintext_secret_data: &[u8],
authenticated_data: &[u8],
) -> Result<XChaCha20Poly1305CTXCiphetext, CryptoError> {
encrypt_xchacha20_poly1305_blake3_ctx_internal(rand::thread_rng(), key, plaintext_secret_data, authenticated_data)
encrypt_xchacha20_poly1305_blake3_ctx_internal(
rand::thread_rng(),
key,
plaintext_secret_data,
authenticated_data,
)
}

#[allow(dead_code)]
Expand All @@ -45,11 +48,21 @@ fn encrypt_xchacha20_poly1305_blake3_ctx_internal(
let mut buffer = Vec::from(plaintext_secret_data);
let cipher = XChaCha20Poly1305::new(&GenericArray::from_slice(key));
let nonce = XChaCha20Poly1305::generate_nonce(rng);

let poly1305_tag = cipher.encrypt_in_place_detached(&nonce, associated_data, &mut buffer).map_err(|_| CryptoError::InvalidKey)?;


let poly1305_tag = cipher
.encrypt_in_place_detached(&nonce, associated_data, &mut buffer)
.map_err(|_| CryptoError::InvalidKey)?;

// T* = H(K, N, A, T )
let ctx_tag = blake3::hash(&[key, nonce.as_slice(), associated_data, poly1305_tag.as_slice()].concat());
let ctx_tag = blake3::hash(
&[
key,
nonce.as_slice(),
associated_data,
poly1305_tag.as_slice(),
]
.concat(),
);
let ctx_tag = ctx_tag.as_bytes();

Ok(XChaCha20Poly1305CTXCiphetext {
Expand All @@ -69,26 +82,45 @@ pub fn decrypt_xchacha20_poly1305_blake3_ctx(
let associated_data = ctx.authenticated_data.as_slice();

// First, get the original polynomial tag, since this is required to calculate the ctx_tag
let poly1305_tag = get_tag_expected_for_xchacha20_poly1305_ctx(key, &ctx.nonce, associated_data, &buffer);

let ctx_tag = blake3::hash(&[key, ctx.nonce.as_slice(), associated_data, poly1305_tag.as_slice()].concat());
let poly1305_tag =
get_tag_expected_for_xchacha20_poly1305_ctx(key, &ctx.nonce, associated_data, &buffer);

let ctx_tag = blake3::hash(
&[
key,
ctx.nonce.as_slice(),
associated_data,
poly1305_tag.as_slice(),
]
.concat(),
);
let ctx_tag = ctx_tag.as_bytes();

if ctx_tag.ct_eq(&ctx.tag).into() {
// At this point the commitment is verified, so we can decrypt the data using regular XChaCha20Poly1305
// At this point the commitment is verified, so we can decrypt the data using regular
// XChaCha20Poly1305
let cipher = XChaCha20Poly1305::new(&GenericArray::from_slice(key));
let mut buffer = ctx.ciphertext.clone();
let nonce_array = GenericArray::from_slice(&ctx.nonce);
cipher.decrypt_in_place_detached(nonce_array, associated_data, &mut buffer, &poly1305_tag)
cipher
.decrypt_in_place_detached(nonce_array, associated_data, &mut buffer, &poly1305_tag)
.map_err(|_| CryptoError::InvalidKey)?;
return Ok(buffer);
}

Err(CryptoError::InvalidKey)

Check warning on line 111 in crates/bitwarden-crypto/src/chacha20.rs

View check run for this annotation

Codecov / codecov/patch

crates/bitwarden-crypto/src/chacha20.rs#L109-L111

Added lines #L109 - L111 were not covered by tests
}

fn get_tag_expected_for_xchacha20_poly1305_ctx(key: &[u8; 32], nonce: &[u8; 24], associated_data: &[u8], buffer: &[u8]) -> chacha20poly1305::Tag {
let mut chacha20 = XChaCha20::new(GenericArray::from_slice(key), GenericArray::from_slice(nonce));
fn get_tag_expected_for_xchacha20_poly1305_ctx(
key: &[u8; 32],
nonce: &[u8; 24],
associated_data: &[u8],
buffer: &[u8],
) -> chacha20poly1305::Tag {
let mut chacha20 = XChaCha20::new(
GenericArray::from_slice(key),
GenericArray::from_slice(nonce),
);
let mut mac_key = poly1305::Key::default();
chacha20.apply_keystream(&mut *mac_key);
let mut mac = Poly1305::new(GenericArray::from_slice(&*mac_key));
Expand Down Expand Up @@ -117,8 +149,10 @@ mod tests {
let plaintext_secret_data = b"My secret data";
let authenticated_data = b"My authenticated data";

let encrypted = encrypt_xchacha20_poly1305_blake3_ctx(&key, plaintext_secret_data, authenticated_data).unwrap();
let encrypted =
encrypt_xchacha20_poly1305_blake3_ctx(&key, plaintext_secret_data, authenticated_data)
.unwrap();
let decrypted = decrypt_xchacha20_poly1305_blake3_ctx(&key, &encrypted).unwrap();
assert_eq!(plaintext_secret_data, decrypted.as_slice());
}
}
}

0 comments on commit fdde35c

Please sign in to comment.