diff --git a/Cargo.toml b/Cargo.toml index 388aca29..ccc99812 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,7 +19,7 @@ travis-ci = { repository = "warner/magic-wormhole.rs" } serde = "1.0" serde_json = "1.0" serde_derive = "1.0" -sodiumoxide = "0.2" +xsalsa20poly1305 = "0.1" spake2 = "0.2.0" sha2 = "0.8" hkdf = "0.8.0" diff --git a/src/core/key.rs b/src/core/key.rs index ce62b349..f4b40a64 100644 --- a/src/core/key.rs +++ b/src/core/key.rs @@ -4,9 +4,14 @@ use serde_derive::{Deserialize, Serialize}; use serde_json::json; use serde_json::{self, Value}; use sha2::{Digest, Sha256}; -use sodiumoxide; -use sodiumoxide::crypto::secretbox; use spake2::{Ed25519Group, Identity, Password, SPAKE2}; +use xsalsa20poly1305::{ + aead::{ + generic_array::{typenum::Unsigned, GenericArray}, + Aead, NewAead, + }, + XSalsa20Poly1305, +}; use super::events::{AppID, Code, Events, Key, MySide, Phase}; use super::util; @@ -154,34 +159,35 @@ fn encrypt_data_with_nonce( plaintext: &[u8], noncebuf: &[u8], ) -> Vec { - let nonce = secretbox::Nonce::from_slice(&noncebuf).unwrap(); - let sodium_key = secretbox::Key::from_slice(&key).unwrap(); - let ciphertext = secretbox::seal(&plaintext, &nonce, &sodium_key); - let mut nonce_and_ciphertext = Vec::new(); - nonce_and_ciphertext.extend(nonce.as_ref().to_vec()); - nonce_and_ciphertext.extend(ciphertext); + let cipher = XSalsa20Poly1305::new(*GenericArray::from_slice(&key)); + let mut ciphertext = cipher + .encrypt(GenericArray::from_slice(&noncebuf), plaintext) + .unwrap(); + let mut nonce_and_ciphertext = vec![]; + nonce_and_ciphertext.append(&mut Vec::from(noncebuf)); + nonce_and_ciphertext.append(&mut ciphertext); nonce_and_ciphertext } pub fn encrypt_data(key: &[u8], plaintext: &[u8]) -> (Vec, Vec) { - let noncebuf = secretbox::gen_nonce().as_ref().to_vec(); + let mut noncebuf: GenericArray::NonceSize> = + GenericArray::default(); + util::random_bytes(&mut noncebuf); let nonce_and_ciphertext = encrypt_data_with_nonce(key, plaintext, &noncebuf); - (noncebuf, nonce_and_ciphertext) + (noncebuf.to_vec(), nonce_and_ciphertext) } // TODO: return an Result with a proper error type // secretbox::open() returns Result, ()> which is not helpful. pub fn decrypt_data(key: &[u8], encrypted: &[u8]) -> Option> { - let (nonce, ciphertext) = - encrypted.split_at(sodiumoxide::crypto::secretbox::NONCEBYTES); - assert_eq!(nonce.len(), sodiumoxide::crypto::secretbox::NONCEBYTES); - secretbox::open( - &ciphertext, - &secretbox::Nonce::from_slice(nonce).unwrap(), - &secretbox::Key::from_slice(&key).unwrap(), - ) - .ok() + let nonce_size = ::NonceSize::to_usize(); + let (nonce, ciphertext) = encrypted.split_at(nonce_size); + assert_eq!(nonce.len(), nonce_size); + let cipher = XSalsa20Poly1305::new(*GenericArray::from_slice(key)); + cipher + .decrypt(GenericArray::from_slice(nonce), ciphertext) + .ok() } fn sha256_digest(input: &[u8]) -> Vec { @@ -206,7 +212,7 @@ pub fn derive_phase_key(side: &str, key: &Key, phase: &Phase) -> Vec { purpose_vec.extend(side_digest); purpose_vec.extend(phase_digest); - let length = sodiumoxide::crypto::secretbox::KEYBYTES; + let length = ::KeySize::to_usize(); derive_key(&key.to_vec(), &purpose_vec, length) }