Skip to content

Commit

Permalink
[refactor] hyperledger#3422: transplant X25519Sha256 and ChaCha20Poly…
Browse files Browse the repository at this point in the history
…1305 code from ursa, migrate iroha_p2p to use it

Signed-off-by: Nikita Strygin <dcnick3@users.noreply.github.com>
  • Loading branch information
DCNick3 committed Nov 22, 2023
1 parent 88009e6 commit a37e566
Show file tree
Hide file tree
Showing 10 changed files with 622 additions and 43 deletions.
3 changes: 3 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

50 changes: 37 additions & 13 deletions crypto/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,24 @@ workspace = true
default = ["std"]
# Enable static linkage of the rust standard library.
# Please refer to https://docs.rust-embedded.org/book/intro/no-std.html
std = ["ursa"]
std = [
"ursa",
"blake2",
"sha2",
"hkdf",
"amcl_wrapper",
"ed25519-dalek",
"curve25519-dalek",
"x25519-dalek",
"rand",
"rand_chacha",
"secp256k1",
"zeroize",
"arrayref",
"aead",
"chacha20poly1305",
"k256",
]
# Force static linking
vendored = ["openssl-sys"]
# Replace structures and methods with FFI equivalents to facilitate dynamic linkage (mainly used in smartcontracts)
Expand All @@ -38,28 +55,35 @@ openssl-sys = { version = "0.9.93", features = ["vendored"], optional = true }
getset = { workspace = true }

ursa = { workspace = true, optional = true }
blake2 = "0.10.6"
sha2 = "0.10.8"
hkdf = "0.12.3"
amcl_wrapper = "0.4.0"
blake2 = { version = "0.10.6", optional = true }
sha2 = { version = "0.10.8", optional = true }
hkdf = { version = "0.12.3", optional = true }
amcl_wrapper = { version = "0.4.0", optional = true }

# TODO: bump these
ed25519-dalek = "1.0.1"
curve25519-dalek = "3.2.1"
x25519-dalek = "1.2.0"
ed25519-dalek = { version = "1.0.1", optional = true }
curve25519-dalek = { version = "3.2.1", optional = true }
x25519-dalek = { version = "1.2.0", optional = true }

# TODO: bump me
rand = "0.7"
rand = { version = "0.7", optional = true }
# TODO: bump me
rand_chacha = "0.2"
rand_chacha = { version = "0.2", optional = true }

# TODO: bump me
secp256k1 = { version = "0.19", features = ["rand", "serde"] }
secp256k1 = { version = "0.19", features = ["rand", "serde"], optional = true }

# TODO: bump me
zeroize = "1.1"
arrayref = "0.3.7"
zeroize = { version = "1.1", optional = true }
arrayref = { version = "0.3.7", optional = true }

# TODO: bump me
aead = { version = "0.3", optional = true }
# TODO: bump me
chacha20poly1305 = { version = "0.7", optional = true }

# TODO: bump me
k256 = { version = "0.9.6", optional = true, features = ["ecdh", "ecdsa", "sha256"]}

[dev-dependencies]
hex-literal = { workspace = true }
Expand Down
150 changes: 150 additions & 0 deletions crypto/src/encryption/chacha20poly1305.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
use aead::{
generic_array::{
typenum::{U0, U12, U16, U32, U36},
GenericArray,
},
Aead, Error, NewAead, Payload,
};
use chacha20poly1305::ChaCha20Poly1305 as SysChaCha20Poly1305;

// use zeroize::Zeroize;
use super::Encryptor;

#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub struct ChaCha20Poly1305 {
key: GenericArray<u8, U32>,
}

impl Encryptor for ChaCha20Poly1305 {
type MinSize = U36;
}

impl NewAead for ChaCha20Poly1305 {
type KeySize = U32;

fn new(key: &GenericArray<u8, Self::KeySize>) -> Self {
Self { key: *key }
}
}

impl Aead for ChaCha20Poly1305 {
type NonceSize = U12;
type TagSize = U16;
type CiphertextOverhead = U0;

fn encrypt<'msg, 'aad>(
&self,
nonce: &GenericArray<u8, Self::NonceSize>,
plaintext: impl Into<Payload<'msg, 'aad>>,
) -> Result<Vec<u8>, Error> {
let aead = SysChaCha20Poly1305::new(&self.key);
let ciphertext = aead.encrypt(nonce, plaintext)?;
Ok(ciphertext)
}

fn decrypt<'msg, 'aad>(
&self,
nonce: &GenericArray<u8, Self::NonceSize>,
ciphertext: impl Into<Payload<'msg, 'aad>>,
) -> Result<Vec<u8>, Error> {
let aead = SysChaCha20Poly1305::new(&self.key);
let plaintext = aead.decrypt(nonce, ciphertext)?;
Ok(plaintext)
}
}

// default_impl!(ChaCha20Poly1305);
// drop_impl!(ChaCha20Poly1305);

#[cfg(test)]
mod tests {
use std::io::Cursor;

use super::*;

#[test]
fn encrypt_easy_works() {
let aes = ChaCha20Poly1305::new(&ChaCha20Poly1305::key_gen().unwrap());
let aad = Vec::new();
let message = b"Hello and Goodbye!".to_vec();
let res = aes.encrypt_easy(&aad, &message);
assert!(res.is_ok());
let ciphertext = res.unwrap();
let res = aes.decrypt_easy(&aad, &ciphertext);
assert!(res.is_ok());
assert_eq!(message, res.unwrap());
}

#[test]
fn encrypt_works() {
let aes = ChaCha20Poly1305::new(&ChaCha20Poly1305::key_gen().unwrap());
let nonce = ChaCha20Poly1305::nonce_gen().unwrap();
let aad = b"encrypt test".to_vec();
let message = b"Hello and Goodbye!".to_vec();
let payload = Payload {
msg: message.as_slice(),
aad: aad.as_slice(),
};
let res = aes.encrypt(&nonce, payload);
assert!(res.is_ok());
let ciphertext = res.unwrap();
let payload = Payload {
msg: ciphertext.as_slice(),
aad: aad.as_slice(),
};
let res = aes.decrypt(&nonce, payload);
assert!(res.is_ok());
assert_eq!(message, res.unwrap());
}

#[test]
fn decrypt_should_fail() {
let aes = ChaCha20Poly1305::new(&ChaCha20Poly1305::key_gen().unwrap());
let aad = b"decrypt should fail".to_vec();
let message = b"Hello and Goodbye!".to_vec();
let res = aes.encrypt_easy(&aad, &message);
assert!(res.is_ok());
let mut ciphertext = res.unwrap();

let aad = b"decrypt should succeed".to_vec();
let res = aes.decrypt_easy(&aad, &ciphertext);
assert!(res.is_err());

let aad = b"decrypt should fail".to_vec();
ciphertext[0] ^= ciphertext[1];
let res = aes.decrypt_easy(&aad, &ciphertext);
assert!(res.is_err());
}

#[test]
fn buffer_works() {
let aes = ChaCha20Poly1305::new(&ChaCha20Poly1305::key_gen().unwrap());
let aad = b"buffer works".to_vec();
let dummytext = b"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.";
let mut ciphertext = Vec::new();
let res = aes.encrypt_buffer(&aad, &mut Cursor::new(dummytext), &mut ciphertext);
assert!(res.is_ok());
let mut plaintext = Vec::new();
let res = aes.decrypt_buffer(
&aad,
&mut Cursor::new(ciphertext.as_slice()),
&mut plaintext,
);
assert!(res.is_ok());
assert_eq!(dummytext.to_vec(), plaintext);
}

// #[test]
// fn zeroed_on_drop() {
// let mut aes = ChaCha20Poly1305::new(&ChaCha20Poly1305::key_gen().unwrap());
// aes.zeroize();
//
// fn as_bytes<T>(x: &T) -> &[u8] {
// use std::{mem, slice};
//
// unsafe { slice::from_raw_parts(x as *const T as *const u8, mem::size_of_val(x)) }
// }
//
// assert!(as_bytes(&aes.key).iter().all(|b| *b == 0u8));
// }
}
Loading

0 comments on commit a37e566

Please sign in to comment.