*most* cryptography functions finished
This commit is contained in:
parent
cd25dd1d0e
commit
611ae05913
12 changed files with 169 additions and 15 deletions
|
@ -1,4 +1,4 @@
|
|||
use std::net::{IpAddr, Ipv4Addr};
|
||||
use std::net::{Ipv4Addr};
|
||||
use quicktap::cidr::{IpInet, Ipv4Inet};
|
||||
use quicktap::drivers::tun::TunDevice;
|
||||
use quicktap::drivers::tungeneric::{GenericDriver, GenericInterface};
|
||||
|
|
|
@ -9,6 +9,15 @@ edition = "2021"
|
|||
cidr = "0.2.1"
|
||||
etherparse = "0.13.0"
|
||||
blake2 = "0.10.5"
|
||||
tai64 = "4.0.0"
|
||||
x25519-dalek = "2.0.0-pre.1"
|
||||
rand = "0.8.5"
|
||||
hmac = "0.12.1"
|
||||
chacha20poly1305 = "0.10.1"
|
||||
|
||||
[target.'cfg(unix)'.dependencies]
|
||||
tun = "0.5.4"
|
||||
tun = "0.5.4"
|
||||
|
||||
[dev-dependencies]
|
||||
hex_lit = "0.1.1"
|
||||
hex = "0.4.3"
|
|
@ -1,10 +0,0 @@
|
|||
use std::error::Error;
|
||||
use blake2::Blake2sVar;
|
||||
|
||||
pub fn crypto_hash(input: &[u8]) -> Result<[u8; 32], Box<dyn Error>> {
|
||||
let mut hasher = Blake2sVar::new(32)?;
|
||||
hasher.update(input);
|
||||
let mut result_buf = [0u8; 32];
|
||||
hasher.finalize_variable(&mut result_buf)?;
|
||||
Ok(result_buf)
|
||||
}
|
|
@ -36,7 +36,7 @@ impl GenericDriver for TunDevice {
|
|||
/// Upon finding a successful packet inside the internal buffer, or the .clear() method being called, the internal buffer will be cleared.
|
||||
fn read(&mut self) -> Result<TunPacket, Box<dyn Error>> {
|
||||
self.packet_buf = [0u8; 4096];
|
||||
let read_amt = self.device.read(&mut self.packet_buf)?;
|
||||
let _ = self.device.read(&mut self.packet_buf)?;
|
||||
let ip_header = IpHeader::from_slice(&self.packet_buf);
|
||||
if let Ok((packet_header, _, _)) = ip_header {
|
||||
// Found a packet. Clear read buffers
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use std::error::Error;
|
||||
use cidr::IpInet;
|
||||
use etherparse::{IpHeader, SlicedPacket};
|
||||
use etherparse::{IpHeader};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct TunPacket {
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
pub mod drivers; // Baremetal network drivers for various platforms
|
||||
pub use cidr;
|
||||
pub mod crypto;
|
||||
pub mod qcrypto;
|
||||
|
|
38
quicktap/src/qcrypto/aead.rs
Normal file
38
quicktap/src/qcrypto/aead.rs
Normal file
|
@ -0,0 +1,38 @@
|
|||
use chacha20poly1305::{ChaCha20Poly1305, Error, Key, KeyInit, XChaCha20Poly1305};
|
||||
use chacha20poly1305::aead::{Aead, Payload, Nonce};
|
||||
|
||||
pub fn qcrypto_aead(key: &[u8; 32], counter: u64, plaintext: &[u8], authtext: &[u8]) -> Result<Vec<u8>, Error> {
|
||||
let cipher = ChaCha20Poly1305::new_from_slice(key).unwrap();
|
||||
let mut nonce_bytes = [0u8; 12];
|
||||
nonce_bytes[4..].copy_from_slice(&counter.to_le_bytes());
|
||||
let mut payload = Payload::from(plaintext);
|
||||
payload.aad = authtext;
|
||||
|
||||
cipher.encrypt(&Nonce::<ChaCha20Poly1305>::from(nonce_bytes), payload)
|
||||
}
|
||||
|
||||
pub fn qcrypto_aead_decrypt(key: &[u8; 32], counter: u64, ciphertext: &[u8], authtext: &[u8]) -> Result<Vec<u8>, Error> {
|
||||
let cipher = ChaCha20Poly1305::new_from_slice(key).unwrap();
|
||||
let mut nonce_bytes = [0u8; 12];
|
||||
nonce_bytes[4..].copy_from_slice(&counter.to_le_bytes());
|
||||
let mut payload = Payload::from(ciphertext);
|
||||
payload.aad = authtext;
|
||||
|
||||
cipher.decrypt(&Nonce::<ChaCha20Poly1305>::from(nonce_bytes), payload)
|
||||
}
|
||||
|
||||
pub fn qcrypto_xaead(key: &[u8; 32], nonce: &[u8; 24], plaintext: &[u8], authtext: &[u8]) -> Result<Vec<u8>, Error> {
|
||||
let cipher = XChaCha20Poly1305::new_from_slice(key).unwrap();
|
||||
let mut payload = Payload::from(plaintext);
|
||||
payload.aad = authtext;
|
||||
|
||||
cipher.encrypt(Nonce::<XChaCha20Poly1305>::from_slice(nonce), payload)
|
||||
}
|
||||
|
||||
pub fn qcrypto_xaead_decrypt(key: &[u8; 32], nonce: &[u8; 24], ciphertext: &[u8], authtext: &[u8]) -> Result<Vec<u8>, Error> {
|
||||
let cipher = XChaCha20Poly1305::new_from_slice(key).unwrap();
|
||||
let mut payload = Payload::from(ciphertext);
|
||||
payload.aad = authtext;
|
||||
|
||||
cipher.decrypt(Nonce::<XChaCha20Poly1305>::from_slice(nonce), payload)
|
||||
}
|
30
quicktap/src/qcrypto/hashes.rs
Normal file
30
quicktap/src/qcrypto/hashes.rs
Normal file
|
@ -0,0 +1,30 @@
|
|||
use blake2::{Blake2s256, Blake2sMac, Digest};
|
||||
use blake2::digest::{KeyInit, FixedOutput, Update};
|
||||
use hmac::SimpleHmac;
|
||||
|
||||
type HmacBlake2s = SimpleHmac<Blake2s256>;
|
||||
|
||||
pub fn qcrypto_hash(input: &[u8]) -> [u8; 32] {
|
||||
let mut hasher = Blake2s256::new();
|
||||
Update::update(&mut hasher, input);
|
||||
hasher.finalize().into()
|
||||
}
|
||||
|
||||
pub fn qcrypto_mac(key: &[u8], input: &[u8]) -> [u8; 16] {
|
||||
let mut hasher = Blake2sMac::new_from_slice(key).unwrap();
|
||||
hasher.update(input);
|
||||
hasher.finalize_fixed().into()
|
||||
}
|
||||
|
||||
pub fn qcrypto_hmac(key: &[u8], input: &[u8]) -> [u8; 32] {
|
||||
let mut hasher = HmacBlake2s::new_from_slice(key).unwrap();
|
||||
Update::update(&mut hasher, input);
|
||||
hasher.finalize_fixed().into()
|
||||
}
|
||||
|
||||
pub fn qcrypto_hmac_twice(key: &[u8], input: &[u8], input2: &[u8]) -> [u8; 32] {
|
||||
let mut hasher = HmacBlake2s::new_from_slice(key).unwrap();
|
||||
Update::update(&mut hasher, input);
|
||||
Update::update(&mut hasher, input2);
|
||||
hasher.finalize_fixed().into()
|
||||
}
|
17
quicktap/src/qcrypto/hkdf.rs
Normal file
17
quicktap/src/qcrypto/hkdf.rs
Normal file
|
@ -0,0 +1,17 @@
|
|||
use std::error::Error;
|
||||
use crate::qcrypto::hashes::{qcrypto_hmac, qcrypto_hmac_twice};
|
||||
|
||||
pub fn qcrypto_hkdf<const N: usize>(key: &[u8], input: &[u8]) -> Result<[[u8; 32]; N], Box<dyn Error>> {
|
||||
let mut result_array = [[0u8; 32]; N];
|
||||
|
||||
let t0 = qcrypto_hmac(key, input);
|
||||
let t1 = qcrypto_hmac(&t0, &[1u8]);
|
||||
|
||||
result_array[0] = t1;
|
||||
|
||||
for n in 0..N {
|
||||
result_array[n-1] = qcrypto_hmac_twice(&t0, &result_array[n-2], &[n as u8]);
|
||||
}
|
||||
|
||||
Ok(result_array)
|
||||
}
|
|
@ -1,4 +1,16 @@
|
|||
use tai64::Tai64N;
|
||||
|
||||
pub mod hashes;
|
||||
pub mod pki;
|
||||
pub mod aead;
|
||||
|
||||
#[cfg(test)]
|
||||
pub mod tests;
|
||||
pub mod hkdf;
|
||||
|
||||
pub fn timestamp() -> Tai64N {
|
||||
Tai64N::now()
|
||||
}
|
||||
|
||||
pub const CONSTURCTION: &str = "Noise_IKpsk2_25519_ChaChaPoly_BLAKE2s";
|
||||
pub const IDENTIFIER: &str = "WireGuard v1 zx2c4 Jason@zx2c4.com";
|
14
quicktap/src/qcrypto/pki.rs
Normal file
14
quicktap/src/qcrypto/pki.rs
Normal file
|
@ -0,0 +1,14 @@
|
|||
use rand::rngs::OsRng;
|
||||
use x25519_dalek::{PublicKey, SharedSecret, StaticSecret};
|
||||
|
||||
type Keypair = (StaticSecret, PublicKey);
|
||||
|
||||
pub fn qcrypto_dh_generate() -> Keypair {
|
||||
let secret = StaticSecret::new(OsRng);
|
||||
let public = PublicKey::from(&secret);
|
||||
(secret, public)
|
||||
}
|
||||
|
||||
pub fn qcrypto_dh(secret: &StaticSecret, public: &PublicKey) -> SharedSecret {
|
||||
secret.diffie_hellman(public)
|
||||
}
|
44
quicktap/src/qcrypto/tests.rs
Normal file
44
quicktap/src/qcrypto/tests.rs
Normal file
|
@ -0,0 +1,44 @@
|
|||
use hex_lit::hex;
|
||||
use x25519_dalek::PublicKey;
|
||||
use crate::qcrypto::aead::{qcrypto_aead, qcrypto_aead_decrypt, qcrypto_xaead, qcrypto_xaead_decrypt};
|
||||
use crate::qcrypto::hashes::{qcrypto_hash, qcrypto_hmac, qcrypto_mac};
|
||||
use crate::qcrypto::pki::{qcrypto_dh, qcrypto_dh_generate};
|
||||
|
||||
#[test]
|
||||
fn qcrypto_hash_test() {
|
||||
assert_eq!(qcrypto_hash(&[0u8; 32]), hex!("320b5ea99e653bc2b593db4130d10a4efd3a0b4cc2e1a6672b678d71dfbd33ad"))
|
||||
}
|
||||
#[test]
|
||||
fn qcrypto_mac_test() {
|
||||
assert_eq!(qcrypto_mac(&[0u8; 32], &[0u8; 32]), hex!("086de86cfb256a2bc40740062bcf4dcc"))
|
||||
}
|
||||
#[test]
|
||||
fn qcrypto_hmac_test() {
|
||||
assert_eq!(qcrypto_hmac(&[0u8; 32], &[0u8; 32]), hex!("025108dc4694cac66d549e152b967e41e516cc7568111822bf1ca44cb89bcbca"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn qcrypto_pki_generate_test() {
|
||||
let keypair = qcrypto_dh_generate();
|
||||
assert_eq!(keypair.1, PublicKey::from(&keypair.0))
|
||||
}
|
||||
#[test]
|
||||
fn qcrypto_dh_test() {
|
||||
let alice = qcrypto_dh_generate();
|
||||
let bob = qcrypto_dh_generate();
|
||||
|
||||
let secret = qcrypto_dh(&alice.0, &bob.1);
|
||||
let secret2 = qcrypto_dh(&bob.0, &alice.1);
|
||||
|
||||
assert_eq!(secret.as_bytes(), secret2.as_bytes())
|
||||
}
|
||||
#[test]
|
||||
fn qcrypto_aead_test() {
|
||||
let ciphertext = qcrypto_aead(&[0u8; 32], 0, &[0u8; 32], &[0u8; 32]).unwrap();
|
||||
assert_eq!(qcrypto_aead_decrypt(&[0u8; 32], 0, &ciphertext, &[0u8; 32]).unwrap(), [0u8; 32].to_vec())
|
||||
}
|
||||
#[test]
|
||||
fn qcrypto_xaead_test() {
|
||||
let ciphertext = qcrypto_xaead(&[0u8; 32], &[0u8; 24], &[0u8; 32], &[0u8; 32]).unwrap();
|
||||
assert_eq!(qcrypto_xaead_decrypt(&[0u8; 32], &[0u8; 24], &ciphertext, &[0u8; 32]).unwrap(), [0u8; 32].to_vec())
|
||||
}
|
Loading…
Reference in a new issue