ecdh and chachapoly tests

This commit is contained in:
Evan Feenstra
2022-07-01 09:36:20 -07:00
parent c70f265ced
commit cb95ab609a
4 changed files with 146 additions and 31 deletions

56
crypter/src/chacha.rs Normal file
View File

@@ -0,0 +1,56 @@
use lightning::util::chacha20poly1305rfc::ChaCha20Poly1305RFC;
use anyhow::anyhow;
pub const MSG_LEN: usize = 32;
pub const KEY_LEN: usize = 32;
pub const NONCE_END_LEN: usize = 8;
const TAG_LEN: usize = 16;
const CIPHER_LEN: usize = MSG_LEN + NONCE_END_LEN + TAG_LEN;
pub fn encrypt(plaintext: [u8; MSG_LEN], key: [u8; KEY_LEN], nonce_end: [u8; NONCE_END_LEN]) -> anyhow::Result<[u8; CIPHER_LEN]> {
let mut nonce = [0; 4 + NONCE_END_LEN];
nonce[4..].copy_from_slice(&nonce_end);
let mut chacha = ChaCha20Poly1305RFC::new(&key, &nonce, &[0; 0]);
let mut res = [0; MSG_LEN];
let mut tag = [0; TAG_LEN];
chacha.encrypt(&plaintext[..], &mut res[0..plaintext.len()], &mut tag);
let mut ret = [0; CIPHER_LEN];
ret[..MSG_LEN].copy_from_slice(&res);
ret[MSG_LEN..MSG_LEN + NONCE_END_LEN].copy_from_slice(&nonce_end);
ret[MSG_LEN + NONCE_END_LEN..].copy_from_slice(&tag);
Ok(ret)
}
pub fn decrypt(ciphertext: [u8; CIPHER_LEN], key: [u8; KEY_LEN]) -> anyhow::Result<[u8; MSG_LEN]> {
let mut nonce = [0; 4 + NONCE_END_LEN];
nonce[4..].copy_from_slice(&ciphertext[MSG_LEN..MSG_LEN + NONCE_END_LEN]);
let mut tag = [0; TAG_LEN];
tag.copy_from_slice(&ciphertext[MSG_LEN + NONCE_END_LEN..]);
let mut chacha2 = ChaCha20Poly1305RFC::new(&key, &nonce, &[0; 0]);
let mut dec = [0; MSG_LEN];
let ok = chacha2.decrypt(&ciphertext[..MSG_LEN], &mut dec, &tag);
if ok {
Ok(dec)
} else {
Err(anyhow!("failed chacha authentication"))
}
}
#[cfg(test)]
mod tests {
use crate::chacha::{decrypt, encrypt, MSG_LEN, KEY_LEN, NONCE_END_LEN};
use rand::{rngs::OsRng, RngCore};
#[test]
fn test_chacha() -> anyhow::Result<()> {
let key = [9; KEY_LEN];
let plaintext = [1; MSG_LEN];
let mut nonce_end = [0; NONCE_END_LEN];
OsRng.fill_bytes(&mut nonce_end);
let cipher = encrypt(plaintext, key, nonce_end)?;
let plain = decrypt(cipher, key)?;
assert_eq!(plaintext, plain);
Ok(())
}
}

47
crypter/src/ecdh.rs Normal file
View File

@@ -0,0 +1,47 @@
use secp256k1::ecdh::SharedSecret;
use secp256k1::{SecretKey, PublicKey};
use anyhow::Result;
const PUBLIC_KEY_LEN: usize = 33;
const PRIVATE_KEY_LEN: usize = 32;
const SECRET_LEN: usize = 32;
pub fn derive_shared_secret_from_slice(their_public_key: [u8; PUBLIC_KEY_LEN], my_private_key: [u8; PRIVATE_KEY_LEN]) -> Result<[u8; SECRET_LEN]> {
let public_key = PublicKey::from_slice(&their_public_key[..])?;
let private_key = SecretKey::from_slice(&my_private_key[..])?;
Ok(derive_shared_secret(&public_key, &private_key).secret_bytes())
}
pub fn derive_shared_secret(their_public_key: &PublicKey, my_private_key: &SecretKey) -> SharedSecret {
SharedSecret::new(their_public_key, my_private_key)
}
#[cfg(test)]
mod tests {
use crate::ecdh::{derive_shared_secret, derive_shared_secret_from_slice};
use rand::thread_rng;
use secp256k1::Secp256k1;
#[test]
fn test_ecdh() -> anyhow::Result<()> {
let s = Secp256k1::new();
let (sk1, pk1) = s.generate_keypair(&mut thread_rng());
let (sk2, pk2) = s.generate_keypair(&mut thread_rng());
let sec1 = derive_shared_secret(&pk2, &sk1);
let sec2 = derive_shared_secret(&pk1, &sk2);
assert_eq!(sec1, sec2);
Ok(())
}
#[test]
fn test_ecdh_from_slice() -> anyhow::Result<()> {
let s = Secp256k1::new();
let (sk1, pk1) = s.generate_keypair(&mut thread_rng());
let (sk2, pk2) = s.generate_keypair(&mut thread_rng());
let sec1 = derive_shared_secret_from_slice(pk2.serialize(), sk1.secret_bytes())?;
let sec2 = derive_shared_secret_from_slice(pk1.serialize(), sk2.secret_bytes())?;
assert_eq!(sec1, sec2);
Ok(())
}
}

View File

@@ -1,39 +1,42 @@
use lightning::util::chacha20poly1305rfc::ChaCha20Poly1305RFC;
pub mod chacha;
pub mod ecdh;
pub fn test_chacha20poly1305() {
let key = [0; 32];
// 32 bytes key
// 12 byte nonce
let n: u64 = 123456;
let mut nonce = [0; 12];
println!("chacha1");
nonce[4..].copy_from_slice(&n.to_le_bytes()[..]);
println!("chacha2");
let mut chacha = ChaCha20Poly1305RFC::new(&key, &nonce, &[0; 0]);
println!("chacha3");
let mut tag = [0; 16];
let plaintext = b"plaintext";
let mut res = [0; 50];
chacha.encrypt(plaintext, &mut res[0..plaintext.len()], &mut tag);
println!("chacha4 {:?}", res);
println!("tag {:?}", tag);
let mut chacha2 = ChaCha20Poly1305RFC::new(&key, &nonce, &[0; 0]);
let mut dec = [0; 9];
let ok = chacha2.decrypt(&res[0..9], &mut dec, &tag);
println!("ok {}", ok);
println!("dec {:?}", dec);
println!("decrypted: {}", String::from_utf8_lossy(&dec[..]));
}
#[cfg(test)]
mod tests {
use crate::test_chacha20poly1305;
use crate::chacha::{decrypt, encrypt, MSG_LEN, NONCE_END_LEN};
use crate::ecdh::derive_shared_secret_from_slice;
use rand::{rngs::OsRng, RngCore, thread_rng};
use secp256k1::Secp256k1;
#[test]
fn find_solution_1_btc() {
test_chacha20poly1305();
fn test_crypter() -> anyhow::Result<()> {
// two keypairs
let s = Secp256k1::new();
let (sk1, pk1) = s.generate_keypair(&mut thread_rng());
let (sk2, pk2) = s.generate_keypair(&mut thread_rng());
// derive shared secrets
let sec1 = derive_shared_secret_from_slice(
pk2.serialize(), sk1.secret_bytes()
)?;
let sec2 = derive_shared_secret_from_slice(
pk1.serialize(), sk2.secret_bytes()
)?;
assert_eq!(sec1, sec2);
// encrypt plaintext with sec1
let plaintext = [1; MSG_LEN];
let mut nonce_end = [0; NONCE_END_LEN];
OsRng.fill_bytes(&mut nonce_end);
let cipher = encrypt(plaintext, sec1, nonce_end)?;
// decrypt with sec2
let plain = decrypt(cipher, sec2)?;
assert_eq!(plaintext, plain);
println!("PLAINTEXT MATCHES!");
Ok(())
}
}