use std::iter::repeat;
use blake2::{Blake2b, digest::{VariableOutput, Input}};
use crypto::mac::Mac;
use crypto::symmetriccipher::SynchronousStreamCipher;
use crypto::curve25519::{curve25519, curve25519_base, Fe};
use crypto::poly1305::Poly1305;
use crypto::salsa20::{Salsa20, hsalsa20};
use crypto::util::fixed_time_eq;
use rand::{OsRng, RngCore};
use sha2::{self, Digest};
#[allow(non_upper_case_globals)]
pub static crypto_secretbox_KEYBYTES: usize = 32;
#[allow(non_upper_case_globals)]
pub static crypto_secretbox_NONCEBYTES: usize = 24;
#[allow(non_upper_case_globals)]
pub static crypto_secretbox_OVERHEADBYTES: usize = 16;
#[allow(non_upper_case_globals)]
pub static crypto_box_PUBLICKEYBYTES: usize = 32;
#[allow(non_upper_case_globals)]
pub static crypto_box_SECRETKEYBYTES: usize = 32;
#[allow(non_upper_case_globals)]
pub static crypto_box_NONCEBYTES: usize = 24;
#[allow(non_upper_case_globals)]
pub static crypto_box_OVERHEAD: usize = 16;
static ZERO_AUTH_KEY: [u8; 32] = [0u8; 32];
static ZERO_HSALSA_NONCE: [u8; 16] = [0u8; 16];
#[derive(Fail, Debug, PartialEq, Eq)]
#[fail(display="decryption error. This usually means the key is wrong.")]
pub struct DecryptionError;
fn crypto_secretbox_setup(nonce: &[u8], key: &[u8]) -> (Poly1305, Salsa20) {
assert!(nonce.len() == crypto_secretbox_NONCEBYTES);
assert!(key.len() == crypto_secretbox_KEYBYTES);
let mut stream = Salsa20::new_xsalsa20(key, nonce);
let mut auth_key = [0u8; 32];
stream.process(&ZERO_AUTH_KEY, &mut auth_key);
let auth = Poly1305::new(&auth_key);
(auth, stream)
}
pub fn crypto_secretbox(msg: &[u8], nonce: &[u8], key: &[u8]) -> Vec<u8> {
let (mut auth, mut stream) = crypto_secretbox_setup(nonce, key);
let taglen = crypto_secretbox_OVERHEADBYTES;
let outlen = crypto_secretbox_OVERHEADBYTES + msg.len();
let mut out: Vec<u8> = repeat(0).take(outlen).collect();
stream.process(msg, &mut out.as_mut_slice()[taglen..]);
auth.input(&(out[taglen..]));
auth.raw_result(&mut out.as_mut_slice()[..taglen]);
out
}
pub fn crypto_secretbox_open(ciphertext: &[u8], nonce: &[u8], key: &[u8]) -> Result<Vec<u8>, DecryptionError> {
assert!(ciphertext.len() >= crypto_secretbox_OVERHEADBYTES);
let (mut auth, mut stream) = crypto_secretbox_setup(nonce, key);
let taglen = crypto_secretbox_OVERHEADBYTES;
let outlen = ciphertext.len() - taglen;
let mut out: Vec<u8> = repeat(0).take(outlen).collect();
let mut tag = [0u8; 16];
auth.input(&ciphertext[taglen..]);
auth.raw_result(&mut tag);
if fixed_time_eq(&tag, &ciphertext[..taglen]) {
stream.process(&ciphertext[taglen..], out.as_mut_slice());
return Ok(out);
} else {
return Err(DecryptionError);
}
}
fn crypto_box_setup(pk: &[u8], sk: &[u8]) -> [u8; 32] {
assert!(pk.len() == crypto_box_PUBLICKEYBYTES);
assert!(sk.len() == crypto_box_SECRETKEYBYTES);
let curve_key = curve25519(sk, pk);
let mut key = [0u8; 32];
hsalsa20(&curve_key, &ZERO_HSALSA_NONCE, &mut key);
key
}
pub fn crypto_box_seal(msg: &[u8], pk: &[u8]) -> Vec<u8> {
let mut esk = [0u8; 32];
OsRng::new().expect("random works").fill_bytes(&mut esk);
let epk = curve25519_base(&esk);
let nonce = seal_nonce(&epk, pk);
let res = crypto_box(msg, &nonce, pk, &esk);
let mut vec = epk[..].to_owned();
vec.extend(res);
return vec;
}
pub fn crypto_box_edwards_seal(msg: &[u8], pk: &[u8]) -> Vec<u8> {
let pk = convert_public_key(&pk);
return crypto_box_seal(msg, &pk);
}
fn convert_public_key(public_key: &[u8]) -> [u8; 32] {
assert_eq!(public_key.len(), 32);
let ed_y = Fe::from_bytes(&public_key);
let mont_x = edwards_to_montgomery_x(ed_y);
return mont_x.to_bytes();
}
fn convert_private_key(private_key: &[u8]) -> [u8; 32] {
assert_eq!(private_key.len(), 32);
let mut curve_key = [0u8; 32];
let hash = sha2::Sha512::digest(private_key);
curve_key.copy_from_slice(&hash.as_ref()[..32]);
curve_key[0] &= 248;
curve_key[31] &= 63;
curve_key[31] |= 64;
return curve_key;
}
fn edwards_to_montgomery_x(ed_y: Fe) -> Fe {
use std::ops::{Add, Sub, Mul};
let ed_z = Fe([1,0,0,0,0,0,0,0,0,0]);
let temp_x = ed_z.add(ed_y);
let temp_z = ed_z.sub(ed_y);
let temp_z_inv = temp_z.invert();
let mont_x = temp_x.mul(temp_z_inv);
mont_x
}
fn seal_nonce(pk1: &[u8], pk2: &[u8]) -> [u8; 24] {
assert_eq!(pk1.len(), 32);
assert_eq!(pk2.len(), 32);
let mut nonce = [0u8; 24];
let mut b2: Blake2b = VariableOutput::new(nonce.len()).expect("blake2b");
b2.process(&pk1);
b2.process(&pk2);
b2.variable_result(&mut nonce).expect("blake2b");
return nonce;
}
pub fn crypto_box_edwards_seal_open(cipher: &[u8], pk: &[u8], sk: &[u8])
-> Result<Vec<u8>, DecryptionError>
{
assert_eq!(sk.len(), 32);
let montgomery_pk = convert_public_key(pk);
let hashed_sk = convert_private_key(sk);
return crypto_box_seal_open(cipher, &montgomery_pk, &hashed_sk);
}
pub fn crypto_box_seal_open(cipher: &[u8], pk: &[u8], sk: &[u8])
-> Result<Vec<u8>, DecryptionError>
{
assert_eq!(sk.len(), 32);
let (epk, cipher) = cipher.split_at(32);
let nonce = seal_nonce(epk, pk);
return crypto_box_open(cipher, &nonce, epk, sk);
}
pub fn crypto_box(msg: &[u8], nonce: &[u8], pk: &[u8], sk: &[u8]) -> Vec<u8> {
assert!(nonce.len() == crypto_box_NONCEBYTES);
let key = crypto_box_setup(pk, sk);
return crypto_secretbox(msg, nonce, &key);
}
pub fn crypto_box_open(ciphertext: &[u8], nonce: &[u8], pk: &[u8], sk: &[u8]) -> Result<Vec<u8>, DecryptionError> {
assert!(nonce.len() == crypto_box_NONCEBYTES);
let key = crypto_box_setup(pk, sk);
return crypto_secretbox_open(ciphertext, nonce, &key);
}
#[cfg(test)]
mod test {
use sha2::{self, Digest};
use nacl::{crypto_secretbox, crypto_secretbox_open};
use nacl::{crypto_box, crypto_box_open};
use nacl::{crypto_box_seal, crypto_box_seal_open};
use nacl::{crypto_box_edwards_seal, crypto_box_edwards_seal_open};
#[test]
fn test_nacl_secretbox_vectors() {
struct TestVector {
key: Vec<u8>,
nonce: Vec<u8>,
msg: Vec<u8>,
boxed: Vec<u8>,
}
let test_vectors = vec!(
TestVector{
key: vec![
0x1b,0x27,0x55,0x64,0x73,0xe9,0x85,0xd4,
0x62,0xcd,0x51,0x19,0x7a,0x9a,0x46,0xc7,
0x60,0x09,0x54,0x9e,0xac,0x64,0x74,0xf2,
0x06,0xc4,0xee,0x08,0x44,0xf6,0x83,0x89 ],
nonce: vec![
0x69,0x69,0x6e,0xe9,0x55,0xb6,0x2b,0x73,
0xcd,0x62,0xbd,0xa8,0x75,0xfc,0x73,0xd6,
0x82,0x19,0xe0,0x03,0x6b,0x7a,0x0b,0x37 ],
msg: vec![
0xbe,0x07,0x5f,0xc5,0x3c,0x81,0xf2,0xd5,
0xcf,0x14,0x13,0x16,0xeb,0xeb,0x0c,0x7b,
0x52,0x28,0xc5,0x2a,0x4c,0x62,0xcb,0xd4,
0x4b,0x66,0x84,0x9b,0x64,0x24,0x4f,0xfc,
0xe5,0xec,0xba,0xaf,0x33,0xbd,0x75,0x1a,
0x1a,0xc7,0x28,0xd4,0x5e,0x6c,0x61,0x29,
0x6c,0xdc,0x3c,0x01,0x23,0x35,0x61,0xf4,
0x1d,0xb6,0x6c,0xce,0x31,0x4a,0xdb,0x31,
0x0e,0x3b,0xe8,0x25,0x0c,0x46,0xf0,0x6d,
0xce,0xea,0x3a,0x7f,0xa1,0x34,0x80,0x57,
0xe2,0xf6,0x55,0x6a,0xd6,0xb1,0x31,0x8a,
0x02,0x4a,0x83,0x8f,0x21,0xaf,0x1f,0xde,
0x04,0x89,0x77,0xeb,0x48,0xf5,0x9f,0xfd,
0x49,0x24,0xca,0x1c,0x60,0x90,0x2e,0x52,
0xf0,0xa0,0x89,0xbc,0x76,0x89,0x70,0x40,
0xe0,0x82,0xf9,0x37,0x76,0x38,0x48,0x64,
0x5e,0x07,0x05 ],
boxed: vec![
0xf3,0xff,0xc7,0x70,0x3f,0x94,0x00,0xe5,
0x2a,0x7d,0xfb,0x4b,0x3d,0x33,0x05,0xd9,
0x8e,0x99,0x3b,0x9f,0x48,0x68,0x12,0x73,
0xc2,0x96,0x50,0xba,0x32,0xfc,0x76,0xce,
0x48,0x33,0x2e,0xa7,0x16,0x4d,0x96,0xa4,
0x47,0x6f,0xb8,0xc5,0x31,0xa1,0x18,0x6a,
0xc0,0xdf,0xc1,0x7c,0x98,0xdc,0xe8,0x7b,
0x4d,0xa7,0xf0,0x11,0xec,0x48,0xc9,0x72,
0x71,0xd2,0xc2,0x0f,0x9b,0x92,0x8f,0xe2,
0x27,0x0d,0x6f,0xb8,0x63,0xd5,0x17,0x38,
0xb4,0x8e,0xee,0xe3,0x14,0xa7,0xcc,0x8a,
0xb9,0x32,0x16,0x45,0x48,0xe5,0x26,0xae,
0x90,0x22,0x43,0x68,0x51,0x7a,0xcf,0xea,
0xbd,0x6b,0xb3,0x73,0x2b,0xc0,0xe9,0xda,
0x99,0x83,0x2b,0x61,0xca,0x01,0xb6,0xde,
0x56,0x24,0x4a,0x9e,0x88,0xd5,0xf9,0xb3,
0x79,0x73,0xf6,0x22,0xa4,0x3d,0x14,0xa6,
0x59,0x9b,0x1f,0x65,0x4c,0xb4,0x5a,0x74,
0xe3,0x55,0xa5 ]
},
TestVector{
key: vec![
0x1b,0x27,0x55,0x64,0x73,0xe9,0x85,0xd4,
0x62,0xcd,0x51,0x19,0x7a,0x9a,0x46,0xc7,
0x60,0x09,0x54,0x9e,0xac,0x64,0x74,0xf2,
0x06,0xc4,0xee,0x08,0x44,0xf6,0x83,0x89 ],
nonce: vec![
0x69,0x69,0x6e,0xe9,0x55,0xb6,0x2b,0x73,
0xcd,0x62,0xbd,0xa8,0x75,0xfc,0x73,0xd6,
0x82,0x19,0xe0,0x03,0x6b,0x7a,0x0b,0x37 ],
msg: vec![
0xbe,0x07,0x5f,0xc5,0x3c,0x81,0xf2,0xd5,
0xcf,0x14,0x13,0x16,0xeb,0xeb,0x0c,0x7b,
0x52,0x28,0xc5,0x2a,0x4c,0x62,0xcb,0xd4,
0x4b,0x66,0x84,0x9b,0x64,0x24,0x4f,0xfc,
0xe5,0xec,0xba,0xaf,0x33,0xbd,0x75,0x1a,
0x1a,0xc7,0x28,0xd4,0x5e,0x6c,0x61,0x29,
0x6c,0xdc,0x3c,0x01,0x23,0x35,0x61,0xf4,
0x1d,0xb6,0x6c,0xce,0x31,0x4a,0xdb,0x31,
0x0e,0x3b,0xe8,0x25,0x0c,0x46,0xf0,0x6d,
0xce,0xea,0x3a,0x7f,0xa1,0x34,0x80,0x57,
0xe2,0xf6,0x55,0x6a,0xd6,0xb1,0x31,0x8a,
0x02,0x4a,0x83,0x8f,0x21,0xaf,0x1f,0xde,
0x04,0x89,0x77,0xeb,0x48,0xf5,0x9f,0xfd,
0x49,0x24,0xca,0x1c,0x60,0x90,0x2e,0x52,
0xf0,0xa0,0x89,0xbc,0x76,0x89,0x70,0x40,
0xe0,0x82,0xf9,0x37,0x76,0x38,0x48,0x64,
0x5e,0x07,0x05 ],
boxed: vec![
0xf3,0xff,0xc7,0x70,0x3f,0x94,0x00,0xe5,
0x2a,0x7d,0xfb,0x4b,0x3d,0x33,0x05,0xd9,
0x8e,0x99,0x3b,0x9f,0x48,0x68,0x12,0x73,
0xc2,0x96,0x50,0xba,0x32,0xfc,0x76,0xce,
0x48,0x33,0x2e,0xa7,0x16,0x4d,0x96,0xa4,
0x47,0x6f,0xb8,0xc5,0x31,0xa1,0x18,0x6a,
0xc0,0xdf,0xc1,0x7c,0x98,0xdc,0xe8,0x7b,
0x4d,0xa7,0xf0,0x11,0xec,0x48,0xc9,0x72,
0x71,0xd2,0xc2,0x0f,0x9b,0x92,0x8f,0xe2,
0x27,0x0d,0x6f,0xb8,0x63,0xd5,0x17,0x38,
0xb4,0x8e,0xee,0xe3,0x14,0xa7,0xcc,0x8a,
0xb9,0x32,0x16,0x45,0x48,0xe5,0x26,0xae,
0x90,0x22,0x43,0x68,0x51,0x7a,0xcf,0xea,
0xbd,0x6b,0xb3,0x73,0x2b,0xc0,0xe9,0xda,
0x99,0x83,0x2b,0x61,0xca,0x01,0xb6,0xde,
0x56,0x24,0x4a,0x9e,0x88,0xd5,0xf9,0xb3,
0x79,0x73,0xf6,0x22,0xa4,0x3d,0x14,0xa6,
0x59,0x9b,0x1f,0x65,0x4c,0xb4,0x5a,0x74,
0xe3,0x55,0xa5 ]
},
);
for t in test_vectors.iter() {
let boxed = crypto_secretbox(&t.msg, &t.nonce, &t.key);
assert!(boxed == t.boxed);
match crypto_secretbox_open(&t.boxed, &t.nonce, &t.key) {
Ok(unboxed) => assert!(unboxed == t.msg),
Err(_) => panic!()
}
}
}
#[test]
fn test_nacl_box_vectors() {
let alicesk = vec![
0x77,0x07,0x6d,0x0a,0x73,0x18,0xa5,0x7d,
0x3c,0x16,0xc1,0x72,0x51,0xb2,0x66,0x45,
0xdf,0x4c,0x2f,0x87,0xeb,0xc0,0x99,0x2a,
0xb1,0x77,0xfb,0xa5,0x1d,0xb9,0x2c,0x2a ];
let alicepk = vec![
0x85,0x20,0xf0,0x09,0x89,0x30,0xa7,0x54,
0x74,0x8b,0x7d,0xdc,0xb4,0x3e,0xf7,0x5a,
0x0d,0xbf,0x3a,0x0d,0x26,0x38,0x1a,0xf4,
0xeb,0xa4,0xa9,0x8e,0xaa,0x9b,0x4e,0x6a ];
let bobsk = vec![
0x5d,0xab,0x08,0x7e,0x62,0x4a,0x8a,0x4b,
0x79,0xe1,0x7f,0x8b,0x83,0x80,0x0e,0xe6,
0x6f,0x3b,0xb1,0x29,0x26,0x18,0xb6,0xfd,
0x1c,0x2f,0x8b,0x27,0xff,0x88,0xe0,0xeb ];
let bobpk = vec![
0xde,0x9e,0xdb,0x7d,0x7b,0x7d,0xc1,0xb4,
0xd3,0x5b,0x61,0xc2,0xec,0xe4,0x35,0x37,
0x3f,0x83,0x43,0xc8,0x5b,0x78,0x67,0x4d,
0xad,0xfc,0x7e,0x14,0x6f,0x88,0x2b,0x4f];
let nonce = vec![
0x69,0x69,0x6e,0xe9,0x55,0xb6,0x2b,0x73,
0xcd,0x62,0xbd,0xa8,0x75,0xfc,0x73,0xd6,
0x82,0x19,0xe0,0x03,0x6b,0x7a,0x0b,0x37 ];
let msg = vec! [
0xbe,0x07,0x5f,0xc5,0x3c,0x81,0xf2,0xd5,
0xcf,0x14,0x13,0x16,0xeb,0xeb,0x0c,0x7b,
0x52,0x28,0xc5,0x2a,0x4c,0x62,0xcb,0xd4,
0x4b,0x66,0x84,0x9b,0x64,0x24,0x4f,0xfc,
0xe5,0xec,0xba,0xaf,0x33,0xbd,0x75,0x1a,
0x1a,0xc7,0x28,0xd4,0x5e,0x6c,0x61,0x29,
0x6c,0xdc,0x3c,0x01,0x23,0x35,0x61,0xf4,
0x1d,0xb6,0x6c,0xce,0x31,0x4a,0xdb,0x31,
0x0e,0x3b,0xe8,0x25,0x0c,0x46,0xf0,0x6d,
0xce,0xea,0x3a,0x7f,0xa1,0x34,0x80,0x57,
0xe2,0xf6,0x55,0x6a,0xd6,0xb1,0x31,0x8a,
0x02,0x4a,0x83,0x8f,0x21,0xaf,0x1f,0xde,
0x04,0x89,0x77,0xeb,0x48,0xf5,0x9f,0xfd,
0x49,0x24,0xca,0x1c,0x60,0x90,0x2e,0x52,
0xf0,0xa0,0x89,0xbc,0x76,0x89,0x70,0x40,
0xe0,0x82,0xf9,0x37,0x76,0x38,0x48,0x64,
0x5e,0x07,0x05 ];
let box_expected = vec![
0xf3,0xff,0xc7,0x70,0x3f,0x94,0x00,0xe5,
0x2a,0x7d,0xfb,0x4b,0x3d,0x33,0x05,0xd9,
0x8e,0x99,0x3b,0x9f,0x48,0x68,0x12,0x73,
0xc2,0x96,0x50,0xba,0x32,0xfc,0x76,0xce,
0x48,0x33,0x2e,0xa7,0x16,0x4d,0x96,0xa4,
0x47,0x6f,0xb8,0xc5,0x31,0xa1,0x18,0x6a,
0xc0,0xdf,0xc1,0x7c,0x98,0xdc,0xe8,0x7b,
0x4d,0xa7,0xf0,0x11,0xec,0x48,0xc9,0x72,
0x71,0xd2,0xc2,0x0f,0x9b,0x92,0x8f,0xe2,
0x27,0x0d,0x6f,0xb8,0x63,0xd5,0x17,0x38,
0xb4,0x8e,0xee,0xe3,0x14,0xa7,0xcc,0x8a,
0xb9,0x32,0x16,0x45,0x48,0xe5,0x26,0xae,
0x90,0x22,0x43,0x68,0x51,0x7a,0xcf,0xea,
0xbd,0x6b,0xb3,0x73,0x2b,0xc0,0xe9,0xda,
0x99,0x83,0x2b,0x61,0xca,0x01,0xb6,0xde,
0x56,0x24,0x4a,0x9e,0x88,0xd5,0xf9,0xb3,
0x79,0x73,0xf6,0x22,0xa4,0x3d,0x14,0xa6,
0x59,0x9b,0x1f,0x65,0x4c,0xb4,0x5a,0x74,
0xe3,0x55,0xa5 ];
let boxed = crypto_box(&msg, &nonce, &bobpk, &alicesk);
assert_eq!(boxed, box_expected);
match crypto_box_open(&box_expected, &nonce, &alicepk, &bobsk) {
Ok(unboxed) => assert!(unboxed == msg),
Err(_) => panic!()
}
}
#[test]
fn test_box_seal() {
let alicesk = vec![
0x77,0x07,0x6d,0x0a,0x73,0x18,0xa5,0x7d,
0x3c,0x16,0xc1,0x72,0x51,0xb2,0x66,0x45,
0xdf,0x4c,0x2f,0x87,0xeb,0xc0,0x99,0x2a,
0xb1,0x77,0xfb,0xa5,0x1d,0xb9,0x2c,0x2a ];
let alicepk = vec![
0x85,0x20,0xf0,0x09,0x89,0x30,0xa7,0x54,
0x74,0x8b,0x7d,0xdc,0xb4,0x3e,0xf7,0x5a,
0x0d,0xbf,0x3a,0x0d,0x26,0x38,0x1a,0xf4,
0xeb,0xa4,0xa9,0x8e,0xaa,0x9b,0x4e,0x6a ];
let msg = vec! [
0xbe,0x07,0x5f,0xc5,0x3c,0x81,0xf2,0xd5,
0xcf,0x14,0x13,0x16,0xeb,0xeb,0x0c,0x7b,
0x52,0x28,0xc5,0x2a,0x4c,0x62,0xcb,0xd4,
0x4b,0x66,0x84,0x9b,0x64,0x24,0x4f,0xfc,
0xe5,0xec,0xba,0xaf,0x33,0xbd,0x75,0x1a,
0x1a,0xc7,0x28,0xd4,0x5e,0x6c,0x61,0x29,
0x6c,0xdc,0x3c,0x01,0x23,0x35,0x61,0xf4,
0x1d,0xb6,0x6c,0xce,0x31,0x4a,0xdb,0x31,
0x0e,0x3b,0xe8,0x25,0x0c,0x46,0xf0,0x6d,
0xce,0xea,0x3a,0x7f,0xa1,0x34,0x80,0x57,
0xe2,0xf6,0x55,0x6a,0xd6,0xb1,0x31,0x8a,
0x02,0x4a,0x83,0x8f,0x21,0xaf,0x1f,0xde,
0x04,0x89,0x77,0xeb,0x48,0xf5,0x9f,0xfd,
0x49,0x24,0xca,0x1c,0x60,0x90,0x2e,0x52,
0xf0,0xa0,0x89,0xbc,0x76,0x89,0x70,0x40,
0xe0,0x82,0xf9,0x37,0x76,0x38,0x48,0x64,
0x5e,0x07,0x05 ];
let boxed = crypto_box_seal(&msg, &alicepk);
match crypto_box_seal_open(&boxed, &alicepk, &alicesk) {
Ok(unboxed) => assert!(unboxed == msg),
Err(_) => panic!()
}
}
#[test]
fn test_box_edwards_seal() {
let alicesk = vec![
0x77,0x07,0x6d,0x0a,0x73,0x18,0xa5,0x7d,
0x3c,0x16,0xc1,0x72,0x51,0xb2,0x66,0x45,
0xdf,0x4c,0x2f,0x87,0xeb,0xc0,0x99,0x2a,
0xb1,0x77,0xfb,0xa5,0x1d,0xb9,0x2c,0x2a ];
let alicepk = vec![
0xd0,0xa4,0xce,0xc0,0xf8,0xb5,0x0b,0xa1,
0xe9,0x36,0xec,0x56,0x15,0x45,0x4a,0xa9,
0x7d,0xfb,0x27,0x86,0x4f,0x5f,0x17,0x60,
0x8a,0xf2,0xcb,0xb1,0x05,0x48,0xf1,0xb3];
let msg = vec! [
0xbe,0x07,0x5f,0xc5,0x3c,0x81,0xf2,0xd5,
0xcf,0x14,0x13,0x16,0xeb,0xeb,0x0c,0x7b,
0x52,0x28,0xc5,0x2a,0x4c,0x62,0xcb,0xd4,
0x4b,0x66,0x84,0x9b,0x64,0x24,0x4f,0xfc,
0xe5,0xec,0xba,0xaf,0x33,0xbd,0x75,0x1a,
0x1a,0xc7,0x28,0xd4,0x5e,0x6c,0x61,0x29,
0x6c,0xdc,0x3c,0x01,0x23,0x35,0x61,0xf4,
0x1d,0xb6,0x6c,0xce,0x31,0x4a,0xdb,0x31,
0x0e,0x3b,0xe8,0x25,0x0c,0x46,0xf0,0x6d,
0xce,0xea,0x3a,0x7f,0xa1,0x34,0x80,0x57,
0xe2,0xf6,0x55,0x6a,0xd6,0xb1,0x31,0x8a,
0x02,0x4a,0x83,0x8f,0x21,0xaf,0x1f,0xde,
0x04,0x89,0x77,0xeb,0x48,0xf5,0x9f,0xfd,
0x49,0x24,0xca,0x1c,0x60,0x90,0x2e,0x52,
0xf0,0xa0,0x89,0xbc,0x76,0x89,0x70,0x40,
0xe0,0x82,0xf9,0x37,0x76,0x38,0x48,0x64,
0x5e,0x07,0x05 ];
let boxed = crypto_box_edwards_seal(&msg, &alicepk);
match crypto_box_edwards_seal_open(&boxed, &alicepk, &alicesk) {
Ok(unboxed) => assert!(unboxed == msg),
Err(_) => panic!()
}
}
#[test]
fn curve_roundtrip() {
use rand::RngCore;
let mut sk1 = [0u8; 32];
let mut sk2 = [0u8; 32];
::rand::OsRng::new().expect("random works").fill_bytes(&mut sk1);
::rand::OsRng::new().expect("random works").fill_bytes(&mut sk2);
let mut mk1 = [0u8; 64];
mk1.copy_from_slice(sha2::Sha512::digest(&sk1[..32]).as_ref());
mk1[0] &= 248;
mk1[31] &= 63;
mk1[31] |= 64;
let mut mk2 = [0u8; 64];
mk2.copy_from_slice(sha2::Sha512::digest(&sk2[..32]).as_ref());
mk2[0] &= 248;
mk2[31] &= 63;
mk2[31] |= 64;
let pk1 = ::crypto::curve25519::ge_scalarmult_base(&mk1).to_bytes();
let pk2 = ::crypto::curve25519::ge_scalarmult_base(&mk2).to_bytes();
assert_eq!(pk1.len(), 32);
assert_eq!(pk2.len(), 32);
assert_eq!(sk1.len(), 32);
assert_eq!(sk2.len(), 32);
let key1 = ::crypto::ed25519::exchange(&pk1, &sk2);
let key2 = ::crypto::ed25519::exchange(&pk2, &sk1);
assert_eq!(key1, key2);
}
#[test]
fn curve_roundtrip2() {
use rand::RngCore;
let mut sk1 = [0u8; 32];
let mut sk2 = [0u8; 32];
::rand::OsRng::new().expect("random works").fill_bytes(&mut sk1);
::rand::OsRng::new().expect("random works").fill_bytes(&mut sk2);
let pk1 = ::crypto::curve25519::curve25519_base(&sk1);
let pk2 = ::crypto::curve25519::curve25519_base(&sk2);
assert_eq!(pk1.len(), 32);
assert_eq!(pk2.len(), 32);
assert_eq!(sk1.len(), 32);
assert_eq!(sk2.len(), 32);
let key1 = ::crypto::curve25519::curve25519(&sk2, &pk1);
let key2 = ::crypto::curve25519::curve25519(&sk1, &pk2);
assert_eq!(key1, key2);
}
}