#![doc(html_logo_url =
"https://raw.githubusercontent.com/maidsafe/QA/master/Images/maidsafe_logo.png",
html_favicon_url = "https://maidsafe.net/img/favicon.ico",
html_root_url = "https://docs.rs/secure_serialisation")]
#![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, private_no_mangle_fns, private_no_mangle_statics,
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)]
extern crate maidsafe_utilities;
#[cfg(test)]
extern crate rand;
extern crate rust_sodium;
extern crate serde;
#[macro_use]
extern crate serde_derive;
#[cfg(test)]
#[macro_use]
extern crate unwrap;
#[macro_use]
extern crate quick_error;
use maidsafe_utilities::serialisation;
use rust_sodium::crypto::box_::{self, Nonce};
pub use rust_sodium::crypto::box_::{PrecomputedKey, PublicKey, SecretKey, gen_keypair, precompute};
use rust_sodium::crypto::sealedbox;
use serde::de::DeserializeOwned;
use serde::ser::Serialize;
quick_error! {
#[derive(Debug)]
pub enum Error {
Serialisation(e: serialisation::SerialisationError) {
description("Error serializing/deserializing data")
display("Error serializing/deserializing data: {}", e)
cause(e)
from()
}
Crypto(_e: ()) {
description("Crypto error")
display("Crypto error")
from()
}
}
}
#[derive(Serialize, Deserialize)]
struct Payload {
ciphertext: Vec<u8>,
nonce: Nonce,
}
pub fn pre_computed_serialise<T: Serialize>(
data: &T,
pre_computed_key: &PrecomputedKey,
) -> Result<Vec<u8>, Error> {
let nonce = box_::gen_nonce();
let serialised_data = serialisation::serialise(data)?;
let full_payload = Payload {
ciphertext: box_::seal_precomputed(&serialised_data, &nonce, pre_computed_key),
nonce: nonce,
};
Ok(serialisation::serialise(&full_payload)?)
}
pub fn serialise<T: Serialize>(
data: &T,
their_public_key: &PublicKey,
our_secret_key: &SecretKey,
) -> Result<Vec<u8>, Error> {
let nonce = box_::gen_nonce();
let serialised_data = serialisation::serialise(data)?;
let full_payload = Payload {
ciphertext: box_::seal(&serialised_data, &nonce, their_public_key, our_secret_key),
nonce: nonce,
};
Ok(serialisation::serialise(&full_payload)?)
}
pub fn pre_computed_deserialise<T: DeserializeOwned + Serialize>(
message: &[u8],
pre_computed_key: &PrecomputedKey,
) -> Result<T, Error> {
let payload = serialisation::deserialise::<Payload>(message)?;
let plain_serialised_data =
box_::open_precomputed(&payload.ciphertext, &payload.nonce, pre_computed_key)?;
Ok(serialisation::deserialise(&plain_serialised_data)?)
}
pub fn deserialise<T: DeserializeOwned + Serialize>(
message: &[u8],
their_public_key: &PublicKey,
our_secret_key: &SecretKey,
) -> Result<T, Error> {
let payload = serialisation::deserialise::<Payload>(message)?;
let plain_serialised_data = box_::open(
&payload.ciphertext,
&payload.nonce,
their_public_key,
our_secret_key,
)?;
Ok(serialisation::deserialise(&plain_serialised_data)?)
}
pub fn anonymous_serialise<T: Serialize>(
data: &T,
their_public_key: &PublicKey,
) -> Result<Vec<u8>, Error> {
let serialised_data = serialisation::serialise(data)?;
let encrypted_data = sealedbox::seal(&serialised_data, their_public_key);
Ok(serialisation::serialise(&encrypted_data)?)
}
pub fn anonymous_deserialise<T: DeserializeOwned + Serialize>(
message: &[u8],
our_pub_key: &PublicKey,
our_secret_key: &SecretKey,
) -> Result<T, Error> {
let encrypted_data = serialisation::deserialise::<Vec<u8>>(message)?;
let plain_serialised_data = sealedbox::open(&encrypted_data[..], our_pub_key, our_secret_key)?;
Ok(serialisation::deserialise(&plain_serialised_data)?)
}
#[cfg(test)]
mod tests {
use super::*;
use rand::{Rand, Rng};
use rand::distributions::{IndependentSample, Range};
fn tamper(bytes: &mut [u8]) {
let range = Range::new(0, bytes.len());
let mut rng = ::rand::thread_rng();
let index = range.ind_sample(&mut rng);
bytes[index] ^= 0x01;
}
fn generate_random_vec<T: Rand>(size: usize) -> Vec<T> {
::rand::thread_rng().gen_iter().take(size).collect()
}
type Msg = (Vec<u8>, Vec<i64>, String);
#[test]
fn authenticated_encryption() {
let bob_message1 = (
generate_random_vec::<u8>(10),
generate_random_vec::<i64>(100),
"Message from Bob for Alice, very secret".to_owned(),
);
let bob_message2 = generate_random_vec::<u8>(1000);
let (alice_public_key, alice_secret_key) = gen_keypair();
let (bob_public_key, bob_secret_key) = gen_keypair();
let bob_precomputed_key = precompute(&alice_public_key, &bob_secret_key);
let alice_precomputed_key = precompute(&bob_public_key, &alice_secret_key);
let bob_encrypted_message1 =
unwrap!(serialise(&bob_message1, &alice_public_key, &bob_secret_key));
let bob_encrypted_message2 =
unwrap!(pre_computed_serialise(&bob_message2, &bob_precomputed_key));
let mut alice_decrypted_message1: Msg = unwrap!(deserialise(
&bob_encrypted_message1,
&bob_public_key,
&alice_secret_key,
));
assert_eq!(alice_decrypted_message1, bob_message1);
alice_decrypted_message1 = unwrap!(pre_computed_deserialise(
&bob_encrypted_message1,
&alice_precomputed_key,
));
assert_eq!(alice_decrypted_message1, bob_message1);
let mut alice_decrypted_message2: Vec<u8> = unwrap!(deserialise(
&bob_encrypted_message2,
&bob_public_key,
&alice_secret_key,
));
assert_eq!(alice_decrypted_message2, bob_message2);
alice_decrypted_message2 = unwrap!(pre_computed_deserialise(
&bob_encrypted_message2,
&alice_precomputed_key,
));
assert_eq!(alice_decrypted_message2, bob_message2);
let mut corrupted_message = bob_encrypted_message1.clone();
tamper(&mut corrupted_message[..]);
assert!(
deserialise::<Msg>(&corrupted_message, &bob_public_key, &alice_secret_key).is_err()
);
assert!(
pre_computed_deserialise::<Msg>(&corrupted_message, &alice_precomputed_key).is_err()
);
let (bad_public_key, bad_secret_key) = gen_keypair();
assert!(
deserialise::<Msg>(&bob_encrypted_message1, &bob_public_key, &bad_secret_key).is_err()
);
assert!(
deserialise::<Msg>(&bob_encrypted_message1, &bad_public_key, &alice_secret_key).is_err()
);
let mut bad_precomputed_key = precompute(&bob_public_key, &bad_secret_key);
assert!(
pre_computed_deserialise::<Msg>(&bob_encrypted_message1, &bad_precomputed_key).is_err()
);
bad_precomputed_key = precompute(&bad_public_key, &alice_secret_key);
assert!(
pre_computed_deserialise::<Msg>(&bob_encrypted_message1, &bad_precomputed_key).is_err()
);
}
#[test]
fn anonymous_encryption() {
let bob_message = (
generate_random_vec::<u8>(10),
generate_random_vec::<i64>(100),
"Message from Bob for Alice, very secret".to_owned(),
);
let (alice_public_key, alice_secret_key) = gen_keypair();
let bob_encrypted_message = unwrap!(anonymous_serialise(&bob_message, &alice_public_key));
let alice_decrypted_message: Msg = unwrap!(anonymous_deserialise(
&bob_encrypted_message,
&alice_public_key,
&alice_secret_key,
));
assert_eq!(alice_decrypted_message, bob_message);
let mut corrupted_message = bob_encrypted_message.clone();
tamper(&mut corrupted_message[..]);
assert!(
anonymous_deserialise::<Msg>(&corrupted_message, &alice_public_key, &alice_secret_key)
.is_err()
);
let (bad_public_key, bad_secret_key) = gen_keypair();
assert!(
anonymous_deserialise::<Msg>(&bob_encrypted_message, &bad_public_key, &bad_secret_key)
.is_err()
);
assert!(
anonymous_deserialise::<Msg>(&bob_encrypted_message, &bad_public_key, &alice_secret_key)
.is_err()
);
assert!(
anonymous_deserialise::<Msg>(&bob_encrypted_message, &alice_public_key, &bad_secret_key)
.is_err()
);
}
}