pub use sodiumoxide::randombytes::randombytes_into;
pub use sodiumoxide::crypto::box_::*;
pub use sodiumoxide::crypto::hash::{sha256, sha512};
pub use sodiumoxide::crypto::secretbox;
pub use sodiumoxide::crypto::pwhash;
pub fn crypto_init() -> Result<(), ()> {
::sodiumoxide::init()
}
pub fn random_u32() -> u32 {
let mut array = [0; 4];
randombytes_into(&mut array);
u32::from_be_bytes(array)
}
pub fn random_u64() -> u64 {
let mut array = [0; 8];
randombytes_into(&mut array);
u64::from_be_bytes(array)
}
#[cfg(target_pointer_width = "32")]
pub fn random_usize() -> usize {
random_u32() as usize
}
#[cfg(target_pointer_width = "64")]
pub fn random_usize() -> usize {
random_u64() as usize
}
pub fn random_limit_usize(limit: usize) -> usize {
let cap = usize::max_value() - usize::max_value() % limit;
loop {
let n = random_usize();
if n < cap {
return n % limit;
}
}
}
pub fn public_key_valid(&PublicKey(ref pk): &PublicKey) -> bool {
pk[PUBLICKEYBYTES - 1] <= 127
}
#[inline]
pub fn encrypt_precompute(their_public_key: &PublicKey,
our_secret_key: &SecretKey) -> PrecomputedKey {
precompute(their_public_key, our_secret_key)
}
#[inline]
pub fn encrypt_data_symmetric(precomputed_key: &PrecomputedKey,
nonce: &Nonce,
plain: &[u8]) -> Vec<u8> {
seal_precomputed(plain, nonce, precomputed_key)
}
#[inline]
pub fn decrypt_data_symmetric(precomputed_key: &PrecomputedKey,
nonce: &Nonce,
encrypted: &[u8]) -> Result<Vec<u8>, ()> {
open_precomputed(encrypted, nonce, precomputed_key)
}
#[inline]
pub fn increment_nonce(nonce: &mut Nonce) {
let Nonce(ref mut bytes) = *nonce;
bytes.reverse();
::sodiumoxide::utils::increment_le(bytes);
bytes.reverse();
}
pub fn increment_nonce_number(nonce: &mut Nonce, num: u64) {
let Nonce(ref mut bytes) = *nonce;
bytes.reverse();
let mut num_bytes = [0; NONCEBYTES];
num_bytes[..8].copy_from_slice(&u64::to_le_bytes(num));
::sodiumoxide::utils::add_le(bytes, &num_bytes).unwrap();
bytes.reverse();
}
pub fn pk_as_digest(pk: PublicKey) -> sha256::Digest {
sha256::Digest::from_slice(pk.as_ref()).unwrap()
}
pub fn digest_as_pk(d: sha256::Digest) -> PublicKey {
PublicKey::from_slice(d.as_ref()).unwrap()
}
#[cfg(test)]
pub mod tests {
use super::*;
#[test]
fn public_key_cmp_test_empty() {
let alice_publickey = PublicKey([0; PUBLICKEYBYTES]);
let bob_publickey = PublicKey([0; PUBLICKEYBYTES]);
assert_eq!(alice_publickey.eq(&bob_publickey), true);
assert_eq!(bob_publickey.eq(&alice_publickey), true);
}
#[test]
fn public_key_cmp_test_random() {
crypto_init().unwrap();
let (alice_publickey, _alice_secretkey) = gen_keypair();
let (bob_publickey, _bob_secretkey) = gen_keypair();
assert_eq!(alice_publickey.eq(&bob_publickey), false);
assert_eq!(bob_publickey.eq(&alice_publickey), false);
assert_eq!(alice_publickey.eq(&alice_publickey), true);
assert_eq!(bob_publickey.eq(&bob_publickey), true);
}
#[test]
fn random_u32_test() {
crypto_init().unwrap();
let a = random_u32();
let b = random_u32();
assert_ne!(a, 0);
assert_ne!(b, 0);
assert_ne!(a, b);
}
#[test]
fn random_u64_test() {
crypto_init().unwrap();
let a = random_u64();
let b = random_u64();
assert_ne!(a, 0);
assert_ne!(b, 0);
assert_ne!(a, b);
}
#[test]
fn random_usize_test() {
crypto_init().unwrap();
let a = random_usize();
let b = random_usize();
assert_ne!(a, 0);
assert_ne!(b, 0);
assert_ne!(a, b);
}
#[test]
fn random_limit_usize_test() {
crypto_init().unwrap();
let n = random_limit_usize(7);
assert!(n < 7);
}
#[test]
fn public_key_valid_test() {
crypto_init().unwrap();
let (pk, _) = gen_keypair();
assert!(public_key_valid(&pk));
assert!(public_key_valid(&PublicKey([0; PUBLICKEYBYTES])));
assert!(public_key_valid(&PublicKey([0b01_11_11_11; PUBLICKEYBYTES])));
assert!(!public_key_valid(&PublicKey([0b10_00_00_00; PUBLICKEYBYTES])));
assert!(!public_key_valid(&PublicKey([0b11_11_11_11; PUBLICKEYBYTES])));
}
#[test]
fn encrypt_precompute_test() {
crypto_init().unwrap();
let (alice_pk, alice_sk) = gen_keypair();
let (bob_pk, bob_sk) = gen_keypair();
let alice_plaintext = b"Hi, Bob.";
let alice_precomputed_key = encrypt_precompute(&bob_pk, &alice_sk);
let nonce = gen_nonce();
let ciphertext = seal_precomputed(alice_plaintext, &nonce, &alice_precomputed_key);
let bob_precomputed_key = encrypt_precompute(&alice_pk, &bob_sk);
let bob_plaintext = open_precomputed(&ciphertext, &nonce, &bob_precomputed_key).unwrap();
assert_eq!(alice_plaintext, &bob_plaintext[..]);
}
#[test]
fn encrypt_data_symmetric_test() {
crypto_init().unwrap();
let (alice_pk, alice_sk) = gen_keypair();
let (bob_pk, bob_sk) = gen_keypair();
let alice_plain = b"Hi, Bob.";
let precomputed_key = precompute(&bob_pk, &alice_sk);
let nonce = gen_nonce();
let ciphertext = encrypt_data_symmetric(&precomputed_key, &nonce, alice_plain);
let bob_plain = open(&ciphertext, &nonce, &alice_pk, &bob_sk).unwrap();
assert_eq!(alice_plain, &bob_plain[..]);
}
#[test]
fn decrypt_data_symmetric_test() {
crypto_init().unwrap();
let (alice_pk, alice_sk) = gen_keypair();
let (bob_pk, bob_sk) = gen_keypair();
let alice_plain = b"Hi, Bob.";
let precomputed_key = precompute(&alice_pk, &bob_sk);
let nonce = gen_nonce();
let ciphertext = seal(alice_plain, &nonce, &bob_pk, &alice_sk);
let bob_plain = decrypt_data_symmetric(&precomputed_key, &nonce, &ciphertext).unwrap();
assert_eq!(alice_plain, &bob_plain[..]);
}
#[test]
fn increment_nonce_test_zero_plus_one() {
crypto_init().unwrap();
let cmp_nonce = Nonce([0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 1]);
let mut nonce = Nonce([0; NONCEBYTES]);
increment_nonce(&mut nonce);
assert_eq!(nonce, cmp_nonce);
}
#[test]
fn increment_nonce_test_0xf_plus_one() {
crypto_init().unwrap();
let cmp_nonce = Nonce([0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0x10]);
let mut nonce = Nonce([0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0xf]);
increment_nonce(&mut nonce);
assert_eq!(nonce, cmp_nonce);
}
#[test]
fn increment_nonce_test_0xff_plus_one() {
crypto_init().unwrap();
let cmp_nonce = Nonce([0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 1, 0]);
let mut nonce = Nonce([0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0xff]);
increment_nonce(&mut nonce);
assert_eq!(nonce, cmp_nonce);
}
#[test]
fn increment_nonce_test_0xff_max() {
crypto_init().unwrap();
let cmp_nonce = Nonce([0; NONCEBYTES]);
let mut nonce = Nonce([0xff; NONCEBYTES]);
increment_nonce(&mut nonce);
assert_eq!(cmp_nonce, nonce);
}
#[test]
fn increment_nonce_test_random() {
crypto_init().unwrap();
let mut nonce = gen_nonce();
let cmp_nonce = nonce;
increment_nonce(&mut nonce);
assert_ne!(nonce, cmp_nonce);
}
#[test]
fn increment_nonce_number_test_zero_plus_0xff00() {
crypto_init().unwrap();
let cmp_nonce = Nonce([0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0xff, 0]);
let mut nonce = Nonce([0; NONCEBYTES]);
increment_nonce_number(&mut nonce, 0xff00);
assert_eq!(nonce, cmp_nonce);
}
#[test]
fn increment_nonce_number_test_0xff0000_plus_0x011000() {
crypto_init().unwrap();
let cmp_nonce = Nonce([0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 1, 0, 0x10, 0]);
let mut nonce = Nonce([0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0xff, 0, 0]);
increment_nonce_number(&mut nonce, 0x01_10_00);
assert_eq!(nonce, cmp_nonce);
}
}