Updating crates & README

This commit is contained in:
Matéo Duparc 2021-05-03 13:23:56 +02:00
parent 01e593bbc5
commit ede47d9574
Signed by: hardcoresushi
GPG Key ID: 007F84120107191E
5 changed files with 28 additions and 29 deletions

View File

@ -14,9 +14,10 @@ rusqlite = {version = "0.25.1", features = ["bundled"]}
ed25519-dalek = "1" #for singing
x25519-dalek = "1.1" #for shared secret
sha2 = "0.9.3"
hkdf = "0.10.0"
aes-gcm = "0.8.0"
hmac = "0.10.1"
hkdf = "0.11.0"
aes-gcm = "0.9.0" #PSEC
aes-gcm-siv = "0.10.0" #Database
hmac = "0.11.0"
hex = "0.4.3"
strum_macros = "0.20.1" #display enums
actix-web = "3"
@ -33,6 +34,5 @@ libmdns = "0.6" #mDNS advertiser
multicast_dns = "0.5" #mDNS browser
base64 = "0.13.0"
time = "0.2.25"
aes-gcm-siv = "0.9.0"
scrypt = "0.6.3"
scrypt = "0.7.0"
zeroize = "1.2.0"

View File

@ -1,7 +1,7 @@
# AIRA
AIRA is peer-to-peer encrypted communication tool for local networks built on the [PSEC protocol](https://forge.chapril.org/hardcoresushi/PSEC). It allows to securely send text messages and files without any server or Internet access.
<img src="https://forge.chapril.org/hardcoresushi/AIRA/raw/branch/master/screenshot.png">
![Screenshot of a conversation between Alice and Bob on AIRA](/screenshot.png)
# Rationale
When people want to send a file from one computer to another located only meters apart, they usually send it via mail. This mail usually goes through many servers around the world before reaching its final destination.
@ -19,7 +19,6 @@ AIRA is still under developement and is not ready for production usage yet. Not
- Automatic peer discovery using mDNS
- Manual peer connection
- File transferts
- Notifications
- Encrypted database
- Contact verification
- IPv4/v6 compatibility

View File

@ -4,8 +4,8 @@ use sha2::Sha384;
use hmac::{Hmac, Mac, NewMac};
use scrypt::{scrypt, Params};
use rand_8::{RngCore, rngs::OsRng};
use aes_gcm::{aead::{Aead, generic_array::GenericArray}, NewAead};
use aes_gcm_siv::{Aes256GcmSiv};
use aes_gcm::{aead::Aead, NewAead, Nonce};
use aes_gcm_siv::Aes256GcmSiv;
use zeroize::Zeroize;
use strum_macros::Display;
use crate::utils::*;
@ -128,7 +128,7 @@ impl ApplicationKeys {
pub fn compute_handshake_finished(local_handshake_traffic_secret: [u8; HASH_OUTPUT_LEN], handshake_hash: [u8; HASH_OUTPUT_LEN]) -> [u8; HASH_OUTPUT_LEN] {
let mut finished_key = [0; HASH_OUTPUT_LEN];
hkdf_expand_label(&local_handshake_traffic_secret, "finished", None, &mut finished_key);
let mut hmac = Hmac::<Sha384>::new_varkey(&finished_key).unwrap();
let mut hmac = Hmac::<Sha384>::new_from_slice(&finished_key).unwrap();
hmac.update(&handshake_hash);
hmac.finalize().into_bytes().as_slice().try_into().unwrap()
}
@ -136,7 +136,7 @@ pub fn compute_handshake_finished(local_handshake_traffic_secret: [u8; HASH_OUTP
pub fn verify_handshake_finished(peer_handshake_finished: [u8; HASH_OUTPUT_LEN], peer_handshake_traffic_secret: [u8; HASH_OUTPUT_LEN], handshake_hash: [u8; HASH_OUTPUT_LEN]) -> bool {
let mut peer_finished_key = [0; HASH_OUTPUT_LEN];
hkdf_expand_label(&peer_handshake_traffic_secret, "finished", None, &mut peer_finished_key);
let mut hmac = Hmac::<Sha384>::new_varkey(&peer_finished_key).unwrap();
let mut hmac = Hmac::<Sha384>::new_from_slice(&peer_finished_key).unwrap();
hmac.update(&handshake_hash);
hmac.verify(&peer_handshake_finished).is_ok()
}
@ -161,11 +161,11 @@ pub fn encrypt_data(data: &[u8], master_key: &[u8]) -> Result<Vec<u8>, CryptoErr
if master_key.len() != MASTER_KEY_LEN {
return Err(CryptoError::InvalidLength);
}
let cipher = Aes256GcmSiv::new(GenericArray::from_slice(master_key));
let cipher = Aes256GcmSiv::new_from_slice(master_key).unwrap();
let mut iv = [0; IV_LEN];
OsRng.fill_bytes(&mut iv); //use it for IV for now
let mut cipher_text = iv.to_vec();
cipher_text.extend(cipher.encrypt(GenericArray::from_slice(&iv), data).unwrap());
cipher_text.extend(cipher.encrypt(Nonce::from_slice(&iv), data).unwrap());
Ok(cipher_text)
}
@ -179,8 +179,8 @@ pub fn decrypt_data(data: &[u8], master_key: &[u8]) -> Result<Vec<u8>, CryptoErr
if data.len() <= IV_LEN || master_key.len() != MASTER_KEY_LEN {
return Err(CryptoError::InvalidLength);
}
let cipher = Aes256GcmSiv::new(GenericArray::from_slice(master_key));
match cipher.decrypt(GenericArray::from_slice(&data[..IV_LEN]), &data[IV_LEN..]) {
let cipher = Aes256GcmSiv::new_from_slice(master_key).unwrap();
match cipher.decrypt(Nonce::from_slice(&data[..IV_LEN]), &data[IV_LEN..]) {
Ok(data) => {
Ok(data)
},
@ -202,8 +202,8 @@ pub fn encrypt_master_key(mut master_key: [u8; MASTER_KEY_LEN], password: &[u8])
scrypt(password, &salt, &scrypt_params(), &mut password_hash).unwrap();
let mut output = [0; IV_LEN+MASTER_KEY_LEN+AES_TAG_LEN];
OsRng.fill_bytes(&mut output); //use it for IV for now
let cipher = Aes256GcmSiv::new(GenericArray::from_slice(&password_hash));
let encrypted_master_key = cipher.encrypt(GenericArray::from_slice(&output[..IV_LEN]), master_key.as_ref()).unwrap();
let cipher = Aes256GcmSiv::new_from_slice(&password_hash).unwrap();
let encrypted_master_key = cipher.encrypt(Nonce::from_slice(&output[..IV_LEN]), master_key.as_ref()).unwrap();
master_key.zeroize();
password_hash.zeroize();
encrypted_master_key.into_iter().enumerate().for_each(|i|{
@ -218,8 +218,8 @@ pub fn decrypt_master_key(encrypted_master_key: &[u8], password: &[u8], salt: &[
}
let mut password_hash = [0; PASSWORD_HASH_LEN];
scrypt(password, salt, &scrypt_params(), &mut password_hash).unwrap();
let cipher = Aes256GcmSiv::new(GenericArray::from_slice(&password_hash));
let result = match cipher.decrypt(GenericArray::from_slice(&encrypted_master_key[..IV_LEN]), &encrypted_master_key[IV_LEN..]) {
let cipher = Aes256GcmSiv::new_from_slice(&password_hash).unwrap();
let result = match cipher.decrypt(Nonce::from_slice(&encrypted_master_key[..IV_LEN]), &encrypted_master_key[IV_LEN..]) {
Ok(master_key) => {
if master_key.len() == MASTER_KEY_LEN {
Ok(master_key.try_into().unwrap())

View File

@ -415,7 +415,7 @@ impl Identity {
Ok(Identity {
name: name.to_owned(),
keypair,
master_key: master_key,
master_key,
})
}

View File

@ -5,7 +5,7 @@ use ed25519_dalek::{ed25519::signature::Signature, Verifier, PUBLIC_KEY_LENGTH,
use x25519_dalek;
use rand_7::{RngCore, rngs::OsRng};
use sha2::{Sha384, Digest};
use aes_gcm::{Aes128Gcm, aead::Aead, NewAead, aead::Payload, aead::generic_array::GenericArray};
use aes_gcm::{Aes128Gcm, aead::Aead, NewAead, aead::Payload, Nonce};
use crate::utils::*;
use crate::crypto::*;
use crate::identity::Identity;
@ -112,9 +112,9 @@ impl Session {
}
fn on_handshake_successful(&mut self, application_keys: ApplicationKeys){
self.local_cipher = Some(Aes128Gcm::new_varkey(&application_keys.local_key).unwrap());
self.local_cipher = Some(Aes128Gcm::new_from_slice(&application_keys.local_key).unwrap());
self.local_iv = Some(application_keys.local_iv);
self.peer_cipher = Some(Aes128Gcm::new_varkey(&application_keys.peer_key).unwrap());
self.peer_cipher = Some(Aes128Gcm::new_from_slice(&application_keys.peer_key).unwrap());
self.peer_iv = Some(application_keys.peer_iv);
self.handshake_sent_buff.clear();
self.handshake_sent_buff.shrink_to_fit();
@ -156,19 +156,19 @@ impl Session {
auth_msg[..PUBLIC_KEY_LENGTH].copy_from_slice(&identity.get_public_key());
auth_msg[PUBLIC_KEY_LENGTH..].copy_from_slice(&identity.sign(ephemeral_public_key.as_bytes()));
//encrypt auth_msg
let local_cipher = Aes128Gcm::new_varkey(&handshake_keys.local_key).unwrap();
let local_cipher = Aes128Gcm::new_from_slice(&handshake_keys.local_key).unwrap();
let mut local_handshake_counter = 0;
let nonce = iv_to_nonce(&handshake_keys.local_iv, &mut local_handshake_counter);
let encrypted_auth_msg = local_cipher.encrypt(GenericArray::from_slice(&nonce), auth_msg.as_ref()).unwrap();
let encrypted_auth_msg = local_cipher.encrypt(Nonce::from_slice(&nonce), auth_msg.as_ref()).unwrap();
self.handshake_write(&encrypted_auth_msg).await?;
let mut encrypted_peer_auth_msg = [0; PUBLIC_KEY_LENGTH+SIGNATURE_LENGTH+AES_TAG_LEN];
self.handshake_read(&mut encrypted_peer_auth_msg).await?;
//decrypt peer_auth_msg
let peer_cipher = Aes128Gcm::new_varkey(&handshake_keys.peer_key).unwrap();
let peer_cipher = Aes128Gcm::new_from_slice(&handshake_keys.peer_key).unwrap();
let mut peer_handshake_counter = 0;
let peer_nonce = iv_to_nonce(&handshake_keys.peer_iv, &mut peer_handshake_counter);
match peer_cipher.decrypt(GenericArray::from_slice(&peer_nonce), encrypted_peer_auth_msg.as_ref()) {
match peer_cipher.decrypt(Nonce::from_slice(&peer_nonce), encrypted_peer_auth_msg.as_ref()) {
Ok(peer_auth_msg) => {
//verify ephemeral public key signature
self.peer_public_key = Some(to_array_32(&peer_auth_msg[..PUBLIC_KEY_LENGTH]));
@ -222,7 +222,7 @@ impl Session {
aad: &cipher_len
};
let nonce = iv_to_nonce(&self.local_iv.unwrap(), &mut self.local_counter);
let cipher_text = self.local_cipher.as_ref().unwrap().encrypt(GenericArray::from_slice(&nonce), payload).unwrap();
let cipher_text = self.local_cipher.as_ref().unwrap().encrypt(Nonce::from_slice(&nonce), payload).unwrap();
[&cipher_len, cipher_text.as_slice()].concat()
}
@ -247,7 +247,7 @@ impl Session {
msg: &cipher_text,
aad: &message_len
};
match peer_cipher.decrypt(GenericArray::from_slice(&peer_nonce), payload) {
match peer_cipher.decrypt(Nonce::from_slice(&peer_nonce), payload) {
Ok(plain_text) => Ok(Session::unpad(plain_text)),
Err(_) => Err(SessionError::TransmissionCorrupted)
}