mirror of
https://github.com/stakwork/sphinx-key.git
synced 2026-01-22 17:05:07 +01:00
ecdh and chachapoly tests
This commit is contained in:
56
crypter/src/chacha.rs
Normal file
56
crypter/src/chacha.rs
Normal 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
47
crypter/src/ecdh.rs
Normal 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(())
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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(())
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user