Skip to content

Commit

Permalink
Fix: formatting
Browse files Browse the repository at this point in the history
  • Loading branch information
rustaceanrob committed Mar 13, 2024
1 parent 38e99f8 commit 00af8e8
Show file tree
Hide file tree
Showing 4 changed files with 113 additions and 58 deletions.
96 changes: 73 additions & 23 deletions src/chachapoly.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::chacha::ChaCha20;
use crate::error;
use error::ChaCha20Poly1305EncryptionError;
use crate::poly1305::Poly1305;
use error::ChaCha20Poly1305EncryptionError;
extern crate alloc;
pub use error::ChaCha20Poly1305DecryptionError;

Expand All @@ -16,14 +16,23 @@ impl ChaCha20Poly1305 {
ChaCha20Poly1305 { key, nonce }
}

pub fn encrypt<'a>(self, plaintext: &'a mut [u8], aad: Option<&'a [u8]>, buffer: &'a mut [u8]) -> Result<&'a [u8], ChaCha20Poly1305EncryptionError> {
pub fn encrypt<'a>(
self,
plaintext: &'a mut [u8],
aad: Option<&'a [u8]>,
buffer: &'a mut [u8],
) -> Result<&'a [u8], ChaCha20Poly1305EncryptionError> {
if plaintext.len() + 16 != buffer.len() {
return Err(ChaCha20Poly1305EncryptionError::IncorrectBuffer("The buffer provided was incorrect. Ensure the buffer is 16 bytes longer than the message.".to_string()));
}
let mut chacha = ChaCha20::new_from_block(self.key, self.nonce, 1);
chacha.apply_keystream(plaintext);
let keystream = chacha.get_keystream(0);
let mut poly = Poly1305::new(keystream[..32].try_into().expect("32 is a valid subset of 64."));
let mut poly = Poly1305::new(
keystream[..32]
.try_into()
.expect("32 is a valid subset of 64."),
);
let aad = aad.unwrap_or(&[]);
poly.add(aad);
poly.add(plaintext);
Expand All @@ -49,13 +58,21 @@ impl ChaCha20Poly1305 {
Ok(&buffer[..plaintext.len() + tag.len()])
}

pub fn decrypt<'a>(self, ciphertext: &'a mut [u8], aad: Option<&'a [u8]>) -> Result<&'a [u8], ChaCha20Poly1305DecryptionError> {
pub fn decrypt<'a>(
self,
ciphertext: &'a mut [u8],
aad: Option<&'a [u8]>,
) -> Result<&'a [u8], ChaCha20Poly1305DecryptionError> {
let mut chacha = ChaCha20::new_from_block(self.key, self.nonce, 0);
let keystream = chacha.get_keystream(0);
let mut poly = Poly1305::new(keystream[..32].try_into().expect("32 is a valid subset of 64."));
let mut poly = Poly1305::new(
keystream[..32]
.try_into()
.expect("32 is a valid subset of 64."),
);
let aad = aad.unwrap_or(&[]);
if ciphertext.len() >= 16 {
let (received_msg, received_tag) = ciphertext.split_at_mut(ciphertext.len()- 16);
let (received_msg, received_tag) = ciphertext.split_at_mut(ciphertext.len() - 16);
poly.add(aad);
poly.add(received_msg);
let aad_len = aad.len().to_le_bytes();
Expand All @@ -72,10 +89,16 @@ impl ChaCha20Poly1305 {
chacha.apply_keystream(received_msg);
Ok(received_msg)
} else {
Err(ChaCha20Poly1305DecryptionError::UnauthenticatedAdditionalData("Computed tag did not match.".to_string()))
Err(
ChaCha20Poly1305DecryptionError::UnauthenticatedAdditionalData(
"Computed tag did not match.".to_string(),
),
)
}
} else {
Err(ChaCha20Poly1305DecryptionError::CiphertextTooShort("Ciphertext must be at least 16 bytes.".to_string()))
Err(ChaCha20Poly1305DecryptionError::CiphertextTooShort(
"Ciphertext must be at least 16 bytes.".to_string(),
))
}
}
}
Expand All @@ -87,67 +110,91 @@ mod tests {

#[test]
fn test_encrypt_other_with_aad() {
let key = hex::decode("85d6be7857556d337f4452fe42d506a80103808afb0db2fd4abff6af4149f51b").unwrap();
let key = hex::decode("85d6be7857556d337f4452fe42d506a80103808afb0db2fd4abff6af4149f51b")
.unwrap();
let key: [u8; 32] = key.as_slice().try_into().unwrap();
let nonce = [0u8; 12];
let mut message = b"Cryptographic Forum Research Group".to_vec();
let aad = b"Some 17 bytes!!!!".to_vec();
let conformed_nonce = Nonce::from_slice(&nonce);
let other = chacha20poly1305::ChaCha20Poly1305::new_from_slice(&key).expect("Key is valid.");
other.encrypt_in_place(conformed_nonce, &aad, &mut message).unwrap();
let other =
chacha20poly1305::ChaCha20Poly1305::new_from_slice(&key).expect("Key is valid.");
other
.encrypt_in_place(conformed_nonce, &aad, &mut message)
.unwrap();
let mut message2 = *b"Cryptographic Forum Research Group";
let mut aad = *b"Some 17 bytes!!!!";
let us = ChaCha20Poly1305::new(key.try_into().unwrap(), nonce);
let mut buffer = [0u8; 50];
us.encrypt(message2.as_mut_slice(), Some(aad.as_mut_slice()), buffer.as_mut_slice()).unwrap();
us.encrypt(
message2.as_mut_slice(),
Some(aad.as_mut_slice()),
buffer.as_mut_slice(),
)
.unwrap();
assert_eq!(hex::encode(message), hex::encode(buffer));
}

#[test]
fn test_encrypt_other_no_aad() {
let key = hex::decode("85d6be7857556d337f4452fe42d506a80103808afb0db2fd4abff6af4149f51b").unwrap();
let key = hex::decode("85d6be7857556d337f4452fe42d506a80103808afb0db2fd4abff6af4149f51b")
.unwrap();
let key = key.as_slice().try_into().unwrap();
let nonce = [0u8; 12];
let mut message = b"Cryptographic Forum Research Group".to_vec();
let aad = b"".to_vec();
let conformed_nonce = Nonce::from_slice(&nonce);
let other = chacha20poly1305::ChaCha20Poly1305::new_from_slice(key).expect("Key is valid.");
other.encrypt_in_place(conformed_nonce, &aad, &mut message).unwrap();
other
.encrypt_in_place(conformed_nonce, &aad, &mut message)
.unwrap();
let mut message2 = *b"Cryptographic Forum Research Group";
let us = ChaCha20Poly1305::new(key.try_into().unwrap(), nonce);
let mut buffer = [0u8; 50];
us.encrypt(message2.as_mut_slice(), None, buffer.as_mut_slice()).unwrap();
us.encrypt(message2.as_mut_slice(), None, buffer.as_mut_slice())
.unwrap();
assert_eq!(hex::encode(message), hex::encode(buffer));
}

#[test]
fn test_encrypt_other_no_content() {
let key = hex::decode("85d6be7857556d337f4452fe42d506a80103808afb0db2fd4abff6af4149f51b").unwrap();
let key = hex::decode("85d6be7857556d337f4452fe42d506a80103808afb0db2fd4abff6af4149f51b")
.unwrap();
let key = key.as_slice().try_into().unwrap();
let nonce = [0u8; 12];
let mut message = b"".to_vec();
let aad = b"Some secret".to_vec();
let conformed_nonce = Nonce::from_slice(&nonce);
let other = chacha20poly1305::ChaCha20Poly1305::new_from_slice(key).expect("Key is valid.");
other.encrypt_in_place(conformed_nonce, &aad, &mut message).unwrap();
other
.encrypt_in_place(conformed_nonce, &aad, &mut message)
.unwrap();
let mut message2 = *b"";
let mut aad = *b"Some secret";
let us = ChaCha20Poly1305::new(key.try_into().unwrap(), nonce);
let mut buffer = [0u8; 16];
us.encrypt(message2.as_mut_slice(), Some(aad.as_mut_slice()), buffer.as_mut_slice()).unwrap();
us.encrypt(
message2.as_mut_slice(),
Some(aad.as_mut_slice()),
buffer.as_mut_slice(),
)
.unwrap();
assert_eq!(hex::encode(message), hex::encode(buffer));
}

#[test]
fn test_decrypt_other_no_aad() {
let key = hex::decode("85d6be7857556d337f4452fe42d506a80103808afb0db2fd4abff6af4149f51b").unwrap();
let key = hex::decode("85d6be7857556d337f4452fe42d506a80103808afb0db2fd4abff6af4149f51b")
.unwrap();
let key = key.as_slice().try_into().unwrap();
let nonce = [0u8; 12];
let mut message = b"Cryptographic Forum Research Group".to_vec();
let aad = b"".to_vec();
let conformed_nonce = Nonce::from_slice(&nonce);
let other = chacha20poly1305::ChaCha20Poly1305::new_from_slice(key).expect("Key is valid.");
other.encrypt_in_place(conformed_nonce, &aad, &mut message).unwrap();
other
.encrypt_in_place(conformed_nonce, &aad, &mut message)
.unwrap();
let us = ChaCha20Poly1305::new(key.try_into().unwrap(), nonce);
let plaintext = us.decrypt(message.as_mut_slice(), None).unwrap();
let message = b"Cryptographic Forum Research Group".to_vec();
Expand All @@ -156,17 +203,20 @@ mod tests {

#[test]
fn test_decrypt_other_no_content() {
let key = hex::decode("85d6be7857556d337f4452fe42d506a80103808afb0db2fd4abff6af4149f51b").unwrap();
let key = hex::decode("85d6be7857556d337f4452fe42d506a80103808afb0db2fd4abff6af4149f51b")
.unwrap();
let key = key.as_slice().try_into().unwrap();
let nonce = [0u8; 12];
let mut message = b"".to_vec();
let aad = b"Cryptographic Forum Research Group".to_vec();
let conformed_nonce = Nonce::from_slice(&nonce);
let other = chacha20poly1305::ChaCha20Poly1305::new_from_slice(key).expect("Key is valid.");
other.encrypt_in_place(conformed_nonce, &aad, &mut message).unwrap();
other
.encrypt_in_place(conformed_nonce, &aad, &mut message)
.unwrap();
let us = ChaCha20Poly1305::new(key.try_into().unwrap(), nonce);
let aad = *b"Cryptographic Forum Research Group";
let plaintext = us.decrypt(message.as_mut_slice(), Some(&aad)).unwrap();
assert!(plaintext.len() == 0);
}
}
}
10 changes: 7 additions & 3 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,15 +102,19 @@ pub enum ChaCha20Poly1305DecryptionError {
impl fmt::Display for ChaCha20Poly1305DecryptionError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
ChaCha20Poly1305DecryptionError::UnauthenticatedAdditionalData(s) => write!(f, "Cipher error: {}", s),
ChaCha20Poly1305DecryptionError::CiphertextTooShort(s) => write!(f, "Cipher error: {}", s),
ChaCha20Poly1305DecryptionError::UnauthenticatedAdditionalData(s) => {
write!(f, "Cipher error: {}", s)
}
ChaCha20Poly1305DecryptionError::CiphertextTooShort(s) => {
write!(f, "Cipher error: {}", s)
}
}
}
}

#[derive(Debug)]
pub enum ChaCha20Poly1305EncryptionError {
IncorrectBuffer(String)
IncorrectBuffer(String),
}

impl fmt::Display for ChaCha20Poly1305EncryptionError {
Expand Down
12 changes: 7 additions & 5 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@ mod chacha;
mod chachapoly;
mod error;
mod hkdf;
mod types;
mod poly1305;
mod types;

use chacha::ChaCha20;
use chachapoly::ChaCha20Poly1305;
Expand Down Expand Up @@ -267,8 +267,9 @@ impl FSChaCha20Poly1305 {
CryptType::Encrypt => {
let mut buffer = contents.clone();
buffer.extend([0u8; 16]);
cipher.encrypt(&mut contents, Some(&aad), &mut buffer)
.map_err(|e| FSChaChaError::Poly1305Encryption(e.to_string()))?;
cipher
.encrypt(&mut contents, Some(&aad), &mut buffer)
.map_err(|e| FSChaChaError::Poly1305Encryption(e.to_string()))?;
buffer.to_vec()
}
CryptType::Decrypt => {
Expand All @@ -295,8 +296,9 @@ impl FSChaCha20Poly1305 {
self.key,
rekey_nonce.try_into().expect("Nonce is malformed."),
);
cipher.encrypt(&mut plaintext, Some(&aad), &mut buffer)
.map_err(|e| FSChaChaError::Poly1305Encryption(e.to_string()))?;
cipher
.encrypt(&mut plaintext, Some(&aad), &mut buffer)
.map_err(|e| FSChaChaError::Poly1305Encryption(e.to_string()))?;
self.key = buffer[0..32]
.try_into()
.expect("Cipher should be at least 32 bytes.");
Expand Down
53 changes: 26 additions & 27 deletions src/poly1305.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,14 @@ impl Poly1305 {
pub(crate) fn new(key: [u8; 32]) -> Self {
// taken from donna. assigns R to a 26-bit 5-limb number while simultaneously 'clamping' R
let r0 = u32::from_le_bytes(key[0..4].try_into().expect("Valid subset of 32.")) & 0x3ffffff;
let r1 = u32::from_le_bytes(key[3..7].try_into().expect("Valid subset of 32.")) >> 2 & 0x03ffff03;
let r2 = u32::from_le_bytes(key[6..10].try_into().expect("Valid subset of 32.")) >> 4 & 0x03ffc0ff;
let r3 = u32::from_le_bytes(key[9..13].try_into().expect("Valid subset of 32.")) >> 6 & 0x03f03fff;
let r4 = u32::from_le_bytes(key[12..16].try_into().expect("Valid subset of 32.")) >> 8 & 0x000fffff;
let r1 = u32::from_le_bytes(key[3..7].try_into().expect("Valid subset of 32.")) >> 2
& 0x03ffff03;
let r2 = u32::from_le_bytes(key[6..10].try_into().expect("Valid subset of 32.")) >> 4
& 0x03ffc0ff;
let r3 = u32::from_le_bytes(key[9..13].try_into().expect("Valid subset of 32.")) >> 6
& 0x03f03fff;
let r4 = u32::from_le_bytes(key[12..16].try_into().expect("Valid subset of 32.")) >> 8
& 0x000fffff;
let r = [r0, r1, r2, r3, r4];
let s0 = u32::from_le_bytes(key[16..20].try_into().expect("Valid subset of 32."));
let s1 = u32::from_le_bytes(key[20..24].try_into().expect("Valid subset of 32."));
Expand All @@ -32,7 +36,7 @@ impl Poly1305 {
pub(crate) fn add(&mut self, message: &[u8]) {
let mut i = 0;
while i < message.len() / 16 {
let msg_slice = prepare_padded_message_slice(&message[i * 16..(i+1) * 16], false);
let msg_slice = prepare_padded_message_slice(&message[i * 16..(i + 1) * 16], false);
for (i, b) in msg_slice.iter().enumerate() {
self.acc[i] += *b;
}
Expand All @@ -51,7 +55,7 @@ impl Poly1305 {
pub(crate) fn tag(&mut self) -> [u8; 16] {
// carry and mask
for i in 1..4 {
self.acc[i+1] += self.acc[i] >> CARRY;
self.acc[i + 1] += self.acc[i] >> CARRY;
}
self.acc[0] += (self.acc[4] >> CARRY) * 5;
self.acc[1] += self.acc[0] >> CARRY;
Expand All @@ -61,11 +65,11 @@ impl Poly1305 {
// reduce
let mut t = self.acc;
t[0] += 5;
t[4] = t[4].wrapping_sub(1 << CARRY);
t[4] = t[4].wrapping_sub(1 << CARRY);
for i in 0..3 {
t[i+1] += t[i] >> CARRY;
t[i + 1] += t[i] >> CARRY;
}
t[4] = t[4].wrapping_add(t[3] >> CARRY);
t[4] = t[4].wrapping_add(t[3] >> CARRY);
for t in t.iter_mut().take(4) {
*t &= BITMASK;
}
Expand All @@ -81,7 +85,7 @@ impl Poly1305 {
let a3 = self.acc[3] >> 18 | self.acc[4] << 8;
let a = [a0, a1, a2, a3];
// a + s
let mut tag : [u64; 4] = [0; 4];
let mut tag: [u64; 4] = [0; 4];
for i in 0..4 {
tag[i] = a[i] as u64 + self.s[i] as u64;
}
Expand All @@ -93,23 +97,19 @@ impl Poly1305 {
let mut ret: [u8; 16] = [0; 16];
for i in 0..tag.len() {
let bytes = (tag[i] as u32).to_le_bytes();
ret[i * 4..(i+1) * 4].copy_from_slice(&bytes);
ret[i * 4..(i + 1) * 4].copy_from_slice(&bytes);
}
ret
}

fn r_times_a(&mut self) {
// multiply and reduce
// while this looks complicated, it is a variation of schoolbook multiplication,
// while this looks complicated, it is a variation of schoolbook multiplication,
// described well in an article here: https://loup-vaillant.fr/tutorials/poly1305-design
let mut t = [0; 5];
for i in 0..5 {
for (j, t) in t.iter_mut().enumerate() {
let modulus: u64 = if i > j {
5
} else {
1
};
for (j, t) in t.iter_mut().enumerate() {
let modulus: u64 = if i > j { 5 } else { 1 };
let start = (5 - i) % 5;
*t += modulus * self.r[i] as u64 * self.acc[(start + j) % 5] as u64;
}
Expand All @@ -130,18 +130,17 @@ impl Poly1305 {
}

fn prepare_padded_message_slice(msg: &[u8], is_last: bool) -> [u32; 5] {
let hi_bit: u32 = if is_last {
0
} else {
1 << 24
};
let hi_bit: u32 = if is_last { 0 } else { 1 << 24 };
let mut fmt_msg = [0u8; 17];
fmt_msg[..msg.len()].clone_from_slice(msg);
fmt_msg[16] = 0x01;
let m0 = u32::from_le_bytes(fmt_msg[0..4].try_into().expect("Valid subset of 32.")) & BITMASK;
let m1 = u32::from_le_bytes(fmt_msg[3..7].try_into().expect("Valid subset of 32.")) >> 2 & BITMASK;
let m2 = u32::from_le_bytes(fmt_msg[6..10].try_into().expect("Valid subset of 32.")) >> 4 & BITMASK;
let m3 = u32::from_le_bytes(fmt_msg[9..13].try_into().expect("Valid subset of 32.")) >> 6 & BITMASK;
let m1 =
u32::from_le_bytes(fmt_msg[3..7].try_into().expect("Valid subset of 32.")) >> 2 & BITMASK;
let m2 =
u32::from_le_bytes(fmt_msg[6..10].try_into().expect("Valid subset of 32.")) >> 4 & BITMASK;
let m3 =
u32::from_le_bytes(fmt_msg[9..13].try_into().expect("Valid subset of 32.")) >> 6 & BITMASK;
let m4: u32 = if is_last {
u32::from_le_bytes(fmt_msg[13..17].try_into().expect("Valid subset of 32.")) | hi_bit
} else {
Expand Down Expand Up @@ -179,4 +178,4 @@ fn _print_acc(num: &[u32; 5]) {
// let tag = poly.tag();
// assert_eq!("a8061dc1305136c6c22b8baf0c0127a9",hex::encode(tag));
// }
// }
// }

0 comments on commit 00af8e8

Please sign in to comment.