#![doc(
html_logo_url = "https://raw.githubusercontent.com/maidsafe/QA/master/Images/maidsafe_logo.png",
html_favicon_url = "https://maidsafe.net/img/favicon.ico",
test(attr(forbid(warnings)))
)]
#![forbid(
exceeding_bitshifts,
mutable_transmutes,
no_mangle_const_items,
unknown_crate_types,
warnings
)]
#![deny(
bad_style,
deprecated,
improper_ctypes,
missing_docs,
non_shorthand_field_patterns,
overflowing_literals,
plugin_as_library,
stable_features,
unconditional_recursion,
unknown_lints,
unsafe_code,
unused,
unused_allocation,
unused_attributes,
unused_comparisons,
unused_features,
unused_parens,
while_true
)]
#![warn(
trivial_casts,
trivial_numeric_casts,
unused_extern_crates,
unused_import_braces,
unused_qualifications,
unused_results
)]
#![allow(
box_pointers,
missing_copy_implementations,
missing_debug_implementations,
variant_size_differences
)]
#[cfg(feature = "mock")]
#[macro_use]
extern crate lazy_static;
#[cfg(not(feature = "mock"))]
extern crate rust_sodium as crypto_impl;
#[cfg(not(feature = "mock"))]
extern crate scrypt as derive_impl;
#[macro_use]
extern crate serde_derive;
#[cfg(not(feature = "mock"))]
extern crate tiny_keccak as hashing_impl;
#[macro_use]
extern crate quick_error;
#[macro_use]
extern crate unwrap;
use rand;
#[cfg(feature = "mock")]
mod mock_crypto;
#[cfg(feature = "mock")]
mod seeded_rng;
#[cfg(feature = "mock")]
use crate::mock_crypto::crypto_impl;
#[cfg(feature = "mock")]
use crate::mock_crypto::derive_impl;
#[cfg(feature = "mock")]
use crate::mock_crypto::hashing_impl;
#[cfg(feature = "mock")]
pub use crate::seeded_rng::SeededRng;
use crate::crypto_impl::crypto::{box_, sealedbox, secretbox, sign};
use crate::derive_impl::ScryptParams;
use maidsafe_utilities::serialisation::{deserialise, serialise, SerialisationError};
use rand::{OsRng, Rng};
use serde::{de::DeserializeOwned, Serialize};
use std::fmt;
use std::sync::Arc;
pub const PUBLIC_ENCRYPT_KEY_BYTES: usize = box_::PUBLICKEYBYTES;
pub const SECRET_ENCRYPT_KEY_BYTES: usize = box_::SECRETKEYBYTES;
pub const PUBLIC_SIGN_KEY_BYTES: usize = sign::PUBLICKEYBYTES;
pub const SECRET_SIGN_KEY_BYTES: usize = sign::SECRETKEYBYTES;
pub const SHARED_SECRET_KEY_BYTES: usize = box_::PRECOMPUTEDKEYBYTES;
pub const SIGNATURE_BYTES: usize = sign::SIGNATUREBYTES;
pub const SYMMETRIC_KEY_BYTES: usize = secretbox::KEYBYTES;
pub const NONCE_BYTES: usize = secretbox::NONCEBYTES;
pub const HASH_BYTES: usize = 32;
pub const SEED_BYTES: usize = sign::SEEDBYTES;
quick_error! {
#[derive(Debug)]
pub enum Error {
Serialisation(e: SerialisationError) {
display("error serialising or deserialising message: {}", e)
cause(e)
from()
}
DecryptVerify(_e: ()) {
display("error decrypting/verifying message")
from()
}
InitError(e: i32) {
display("error while initialising safe_crypto")
from()
}
DeriveKey {
display("error deriving encryption key from password")
}
}
}
pub fn init() -> Result<(), Error> {
crypto_impl::init().map_err(|_| Error::InitError(-1))
}
#[cfg(feature = "mock")]
pub fn init_with_rng<T: Rng>(rng: &mut T) -> Result<(), Error> {
crypto_impl::init_with_rng(rng).map_err(Error::InitError)
}
pub fn hash(data: &[u8]) -> [u8; HASH_BYTES] {
hashing_impl::sha3_256(data)
}
pub fn derive_key_from_pw(
password: &[u8],
salt: &[u8],
work_factor: Option<u8>,
output: &mut [u8],
) -> Result<(), Error> {
let params =
ScryptParams::new(work_factor.unwrap_or(19), 8, 1).map_err(|_| Error::DeriveKey)?;
derive_impl::scrypt(password, salt, ¶ms, output).map_err(|_| Error::DeriveKey)
}
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, Clone)]
pub struct Seed {
seed: sign::Seed,
}
impl Seed {
pub fn new() -> Self {
let mut seed_bytes = [0; SEED_BYTES];
seed_bytes.copy_from_slice(&generate_random_bytes(SEED_BYTES));
Self {
seed: sign::Seed(seed_bytes),
}
}
pub fn from_bytes(seed: [u8; SEED_BYTES]) -> Self {
Self {
seed: sign::Seed(seed),
}
}
pub fn into_bytes(self) -> [u8; SEED_BYTES] {
self.seed.0
}
}
impl Default for Seed {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Hash, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize, Clone, Copy)]
pub struct PublicEncryptKey {
encrypt: box_::PublicKey,
}
impl PublicEncryptKey {
pub fn from_bytes(public_key: [u8; PUBLIC_ENCRYPT_KEY_BYTES]) -> Self {
Self {
encrypt: box_::PublicKey(public_key),
}
}
pub fn into_bytes(self) -> [u8; PUBLIC_ENCRYPT_KEY_BYTES] {
self.encrypt.0
}
pub fn anonymously_encrypt<T>(&self, plaintext: &T) -> Result<Vec<u8>, Error>
where
T: Serialize,
{
Ok(self.anonymously_encrypt_bytes(&serialise(plaintext)?))
}
pub fn anonymously_encrypt_bytes(&self, plaintext: &[u8]) -> Vec<u8> {
sealedbox::seal(plaintext, &self.encrypt)
}
}
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, Clone)]
pub struct SecretEncryptKey {
inner: Arc<SecretEncryptKeyInner>,
}
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
struct SecretEncryptKeyInner {
encrypt: box_::SecretKey,
}
impl SecretEncryptKey {
pub fn from_bytes(secret_key: [u8; SECRET_ENCRYPT_KEY_BYTES]) -> Self {
Self {
inner: Arc::new(SecretEncryptKeyInner {
encrypt: box_::SecretKey(secret_key),
}),
}
}
pub fn shared_secret(&self, their_pk: &PublicEncryptKey) -> SharedSecretKey {
let precomputed = Arc::new(box_::precompute(&their_pk.encrypt, &self.inner.encrypt));
SharedSecretKey { precomputed }
}
pub fn into_bytes(self) -> [u8; SECRET_ENCRYPT_KEY_BYTES] {
self.inner.encrypt.0
}
pub fn anonymously_decrypt<T>(
&self,
ciphertext: &[u8],
my_pk: &PublicEncryptKey,
) -> Result<T, Error>
where
T: Serialize + DeserializeOwned,
{
Ok(deserialise(
&self.anonymously_decrypt_bytes(ciphertext, my_pk)?,
)?)
}
pub fn anonymously_decrypt_bytes(
&self,
ciphertext: &[u8],
my_pk: &PublicEncryptKey,
) -> Result<Vec<u8>, Error> {
Ok(sealedbox::open(
ciphertext,
&my_pk.encrypt,
&self.inner.encrypt,
)?)
}
}
pub fn gen_encrypt_keypair() -> (PublicEncryptKey, SecretEncryptKey) {
let (encrypt_pk, encrypt_sk) = box_::gen_keypair();
let pub_enc_key = PublicEncryptKey {
encrypt: encrypt_pk,
};
let sec_enc_key = SecretEncryptKey {
inner: Arc::new(SecretEncryptKeyInner {
encrypt: encrypt_sk,
}),
};
(pub_enc_key, sec_enc_key)
}
#[derive(Debug, Hash, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize, Clone, Copy)]
pub struct PublicSignKey {
sign: sign::PublicKey,
}
impl PublicSignKey {
pub fn verify_detached(&self, signature: &Signature, data: &[u8]) -> bool {
sign::verify_detached(&signature.signature, data, &self.sign)
}
pub fn from_bytes(public_key: [u8; PUBLIC_SIGN_KEY_BYTES]) -> Self {
Self {
sign: sign::PublicKey(public_key),
}
}
pub fn into_bytes(self) -> [u8; PUBLIC_SIGN_KEY_BYTES] {
self.sign.0
}
}
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, Clone)]
pub struct SecretSignKey {
inner: Arc<SecretSignKeyInner>,
}
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
struct SecretSignKeyInner {
sign: sign::SecretKey,
}
impl SecretSignKey {
pub fn from_bytes(secret_key: [u8; SECRET_SIGN_KEY_BYTES]) -> Self {
Self {
inner: Arc::new(SecretSignKeyInner {
sign: sign::SecretKey(secret_key),
}),
}
}
pub fn into_bytes(self) -> [u8; SECRET_SIGN_KEY_BYTES] {
self.inner.sign.0
}
pub fn sign_detached(&self, data: &[u8]) -> Signature {
Signature {
signature: sign::sign_detached(data, &self.inner.sign),
}
}
}
pub fn gen_sign_keypair() -> (PublicSignKey, SecretSignKey) {
let (sign_pk, sign_sk) = sign::gen_keypair();
let pub_sign_key = PublicSignKey { sign: sign_pk };
let sec_sign_key = SecretSignKey {
inner: Arc::new(SecretSignKeyInner { sign: sign_sk }),
};
(pub_sign_key, sec_sign_key)
}
pub fn gen_sign_keypair_from_seed(seed: &Seed) -> (PublicSignKey, SecretSignKey) {
let (sign_pk, sign_sk) = sign::keypair_from_seed(&seed.seed);
let pub_sign_key = PublicSignKey { sign: sign_pk };
let sec_sign_key = SecretSignKey {
inner: Arc::new(SecretSignKeyInner { sign: sign_sk }),
};
(pub_sign_key, sec_sign_key)
}
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, Clone)]
pub struct SharedSecretKey {
precomputed: Arc<box_::PrecomputedKey>,
}
impl SharedSecretKey {
pub fn from_bytes(key: [u8; SHARED_SECRET_KEY_BYTES]) -> Self {
Self {
precomputed: Arc::new(box_::PrecomputedKey(key)),
}
}
pub fn into_bytes(self) -> [u8; SHARED_SECRET_KEY_BYTES] {
self.precomputed.0
}
pub fn encrypt_bytes(&self, plaintext: &[u8]) -> Result<Vec<u8>, Error> {
let nonce = box_::gen_nonce();
let ciphertext = box_::seal_precomputed(plaintext, &nonce, &self.precomputed);
Ok(serialise(&CipherText {
nonce: nonce.0,
ciphertext,
})?)
}
pub fn encrypt<T>(&self, plaintext: &T) -> Result<Vec<u8>, Error>
where
T: Serialize,
{
self.encrypt_bytes(&serialise(plaintext)?)
}
pub fn decrypt_bytes(&self, encoded: &[u8]) -> Result<Vec<u8>, Error> {
let CipherText { nonce, ciphertext } = deserialise(encoded)?;
Ok(box_::open_precomputed(
&ciphertext,
&box_::Nonce(nonce),
&self.precomputed,
)?)
}
pub fn decrypt<T>(&self, ciphertext: &[u8]) -> Result<T, Error>
where
T: Serialize + DeserializeOwned,
{
Ok(deserialise(&self.decrypt_bytes(ciphertext)?)?)
}
}
#[derive(Debug, Hash, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize, Clone, Copy)]
pub struct Signature {
signature: sign::Signature,
}
impl Signature {
pub fn from_bytes(key: [u8; SIGNATURE_BYTES]) -> Self {
Self {
signature: sign::Signature(key),
}
}
pub fn into_bytes(self) -> [u8; SIGNATURE_BYTES] {
self.signature.0
}
}
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, Clone)]
pub struct SymmetricKey {
encrypt: Arc<secretbox::Key>,
}
impl SymmetricKey {
pub fn new() -> Self {
let sk = secretbox::gen_key();
Self {
encrypt: Arc::new(sk),
}
}
pub fn from_bytes(key: [u8; SYMMETRIC_KEY_BYTES]) -> Self {
Self {
encrypt: Arc::new(secretbox::Key(key)),
}
}
pub fn into_bytes(self) -> [u8; SYMMETRIC_KEY_BYTES] {
self.encrypt.0
}
pub fn encrypt<T: Serialize>(&self, plaintext: &T) -> Result<Vec<u8>, Error> {
self.encrypt_bytes(&serialise(plaintext)?)
}
pub fn encrypt_with_nonce<T: Serialize>(
&self,
plaintext: &T,
nonce: &Nonce,
) -> Result<Vec<u8>, Error> {
self.encrypt_bytes_with_nonce(&serialise(plaintext)?, nonce)
}
pub fn encrypt_bytes_with_nonce(
&self,
plaintext: &[u8],
nonce: &Nonce,
) -> Result<Vec<u8>, Error> {
let nonce = &nonce.nonce;
let ciphertext = secretbox::seal(plaintext, &nonce, &self.encrypt);
Ok(serialise(&CipherText {
nonce: nonce.0,
ciphertext,
})?)
}
pub fn encrypt_bytes(&self, plaintext: &[u8]) -> Result<Vec<u8>, Error> {
let nonce = secretbox::gen_nonce();
self.encrypt_bytes_with_nonce(plaintext, &Nonce { nonce })
}
pub fn decrypt<T>(&self, ciphertext: &[u8]) -> Result<T, Error>
where
T: DeserializeOwned + Serialize,
{
Ok(deserialise(&self.decrypt_bytes(ciphertext)?)?)
}
pub fn decrypt_bytes(&self, ciphertext: &[u8]) -> Result<Vec<u8>, Error> {
let CipherText { nonce, ciphertext } = deserialise(ciphertext)?;
Ok(secretbox::open(
&ciphertext,
&secretbox::Nonce(nonce),
&self.encrypt,
)?)
}
}
impl Default for SymmetricKey {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, Clone)]
pub struct Nonce {
nonce: secretbox::Nonce,
}
impl Nonce {
pub fn new() -> Self {
Self {
nonce: secretbox::gen_nonce(),
}
}
pub fn from_bytes(nonce: [u8; NONCE_BYTES]) -> Self {
Self {
nonce: secretbox::Nonce(nonce),
}
}
pub fn into_bytes(self) -> [u8; NONCE_BYTES] {
self.nonce.0
}
}
impl Default for Nonce {
fn default() -> Self {
Self::new()
}
}
#[derive(Serialize, Deserialize)]
struct CipherText {
nonce: [u8; NONCE_BYTES],
ciphertext: Vec<u8>,
}
impl fmt::Display for PublicEncryptKey {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(
f,
"{:02x}{:02x}{:02x}..",
&self.encrypt.0[0], &self.encrypt.0[1], &self.encrypt.0[2]
)
}
}
impl fmt::Display for PublicSignKey {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(
f,
"{:02x}{:02x}{:02x}..",
&self.sign.0[0], &self.sign.0[1], &self.sign.0[2]
)
}
}
impl fmt::Display for Signature {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(
f,
"{:02x}{:02x}{:02x}..",
&self.signature.0[0], &self.signature.0[1], &self.signature.0[2]
)
}
}
pub(crate) fn generate_random_bytes(length: usize) -> Vec<u8> {
let mut os_rng = unwrap!(OsRng::new());
os_rng
.gen_iter::<u8>()
.filter(|b| *b != 0)
.take(length)
.collect()
}
#[cfg(test)]
mod tests {
use self::rand::{OsRng, Rng};
use super::*;
#[test]
fn anonymous_bytes_cipher() {
let data = generate_random_bytes(50);
let (pk, sk) = gen_encrypt_keypair();
let (pk2, sk2) = gen_encrypt_keypair();
let ciphertext = pk.anonymously_encrypt_bytes(&data);
assert_ne!(&ciphertext, &data);
let error_res = sk.anonymously_decrypt_bytes(&data, &pk);
match error_res {
Err(_e) => (),
Ok(_) => {
panic!("Unexpected result: we're using wrong data, it should have returned error")
}
}
let error_res: Result<_, _> = sk2.anonymously_decrypt_bytes(&ciphertext, &pk2);
match error_res {
Err(_e) => (),
Ok(_) => {
panic!("Unexpected result: we're using a wrong key, it should have returned error")
}
}
let plaintext: Vec<u8> = unwrap!(
sk.anonymously_decrypt_bytes(&ciphertext, &pk),
"couldn't decrypt ciphertext"
);
assert_eq!(&plaintext, &data);
}
#[test]
fn anonymous_cipher() {
let mut os_rng = unwrap!(OsRng::new());
let data: Vec<u64> = os_rng.gen_iter().take(32).collect();
let (pk, sk) = gen_encrypt_keypair();
let ciphertext = unwrap!(pk.anonymously_encrypt(&data), "couldn't encrypt base data");
assert!(!ciphertext.is_empty());
let plaintext: Vec<u64> = unwrap!(
sk.anonymously_decrypt(&ciphertext, &pk),
"couldn't decrypt ciphertext"
);
assert_eq!(plaintext, data);
}
#[test]
fn authenticated_cipher() {
let data = generate_random_bytes(50);
let (pk1, sk1) = gen_encrypt_keypair();
let (pk2, sk2) = gen_encrypt_keypair();
let shared_sk1 = sk1.shared_secret(&pk2);
let shared_sk2 = sk2.shared_secret(&pk1);
let ciphertext = unwrap!(shared_sk1.encrypt_bytes(&data), "couldn't encrypt data");
assert_ne!(&ciphertext, &data);
let plaintext = unwrap!(
shared_sk2.decrypt_bytes(&ciphertext),
"couldn't decrypt data"
);
assert_eq!(&plaintext, &data);
let error_res: Result<_, _> = shared_sk2.decrypt_bytes(&plaintext);
match error_res {
Err(_e) => (),
Ok(_) => panic!(
"Unexpected result: we're using wrong data, it should have returned an error"
),
}
let (_, sk3) = gen_encrypt_keypair();
let shared_sk3 = sk3.shared_secret(&pk2);
let error_res = shared_sk3.decrypt_bytes(&ciphertext);
match error_res {
Err(_e) => (),
Ok(_) => panic!(
"Unexpected result: we're using a wrong key, it should have returned an error"
),
}
}
#[test]
fn signing() {
let data1 = generate_random_bytes(50);
let data2 = generate_random_bytes(50);
let (pk1, sk1) = gen_sign_keypair();
let (pk2, sk2) = gen_sign_keypair();
let sig1 = sk1.sign_detached(&data1);
let sig2 = sk2.sign_detached(&data2);
assert!(pk1.verify_detached(&sig1, &data1));
assert!(!pk1.verify_detached(&sig1, &data2));
assert!(!pk1.verify_detached(&sig2, &data1));
assert!(!pk1.verify_detached(&sig2, &data2));
assert!(!pk2.verify_detached(&sig1, &data1));
assert!(!pk2.verify_detached(&sig1, &data2));
assert!(!pk2.verify_detached(&sig2, &data1));
assert!(pk2.verify_detached(&sig2, &data2));
}
#[test]
fn signing_seed() {
let data1 = generate_random_bytes(50);
let data2 = generate_random_bytes(50);
let seed = Seed::new();
let (pk1, sk1) = gen_sign_keypair_from_seed(&seed);
let (pk2, sk2) = gen_sign_keypair_from_seed(&seed);
assert_eq!(pk1, pk2);
assert_eq!(sk1, sk2);
let sig1 = sk1.sign_detached(&data1);
let sig2 = sk2.sign_detached(&data2);
assert!(pk1.verify_detached(&sig1, &data1));
assert!(pk2.verify_detached(&sig2, &data2));
let seed2 = Seed::new();
assert_ne!(seed, seed2);
let (pk3, sk3) = gen_sign_keypair_from_seed(&seed2);
let sig3 = sk3.sign_detached(&data2);
assert!(pk1.verify_detached(&sig1, &data1));
assert!(!pk1.verify_detached(&sig1, &data2));
assert!(!pk1.verify_detached(&sig3, &data1));
assert!(!pk1.verify_detached(&sig3, &data2));
assert!(!pk3.verify_detached(&sig1, &data1));
assert!(!pk3.verify_detached(&sig1, &data2));
assert!(!pk3.verify_detached(&sig3, &data1));
assert!(pk3.verify_detached(&sig3, &data2));
}
#[test]
fn symmetric() {
let data = generate_random_bytes(50);
let nonce = Nonce::new();
let (sk1, sk2) = (SymmetricKey::new(), SymmetricKey::new());
let ciphertexts = vec![
unwrap!(sk1.encrypt_bytes(&data), "could not encrypt data"),
unwrap!(
sk1.encrypt_bytes_with_nonce(&data, &nonce),
"could not encrypt data using a nonce"
),
];
for ciphertext in ciphertexts {
let plaintext = unwrap!(sk1.decrypt_bytes(&ciphertext), "could not decrypt data");
assert_eq!(plaintext, data);
match sk2.decrypt_bytes(&ciphertext) {
Err(_) => (),
Ok(_) => panic!(
"Unexpected result: we're using a wrong key, it should have returned an error"
),
}
let mut os_rng = unwrap!(OsRng::new());
let data: Vec<u64> = os_rng.gen_iter().take(32).collect();
let ciphertext = unwrap!(sk2.encrypt(&data), "could not encrypt data");
let plaintext: Vec<u64> = unwrap!(sk2.decrypt(&ciphertext), "could not decrypt data");
assert_eq!(plaintext, data);
}
}
#[test]
fn hashes() {
let mut data = generate_random_bytes(10);
let data2 = generate_random_bytes(10);
let h1 = hash(&data);
assert_eq!(h1, hash(&data));
assert_ne!(h1, hash(&data2));
data.push(1);
assert_ne!(h1, hash(&data));
}
}