1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
extern crate saltbabe;
#[macro_use]
extern crate arrayref;
extern crate hex;
use std::str;
pub use saltbabe::{KeyPair,Public, Secret, Error};
pub use saltbabe::traits::FromUnsafeSlice;

const VERSION: &str =  "x25519-xsalsa20-poly1305";

#[derive(Debug, Clone)]
pub struct EncryptedData {
    version: String,    
    nonce: String,
    ephem_public: String,
    ciphertext: String
}

pub fn get_encryption_keypair(sk: [u8; 32]) -> KeyPair<Secret, Public> {
    let keypair = saltbabe::crypto_box::gen_keypair_from_secret(&sk);
    return keypair;
}

pub fn to_byte32(bytes: &[u8]) -> [u8; 32] {
    array_ref!(bytes, 0, 32).clone()
}


pub fn encrypt(data: &[u8], version: Option<String>, send_pk: [u8; 32], ephermal_sk: [u8; 32]) -> Result<EncryptedData, Error> {
    let version = match version {
        Some(s) => s,
        None => VERSION.to_string()
    };
    let nonce = saltbabe::gen_nonce();
    let send_public = Public::from_unsafe_slice(&send_pk).unwrap();
    // Generate another ephemeral keypair from the key input
    let ephemeral_keypair = saltbabe::crypto_box::gen_keypair_from_secret(&ephermal_sk);
    let result = saltbabe::crypto_box::seal(&data, &nonce, &send_public, ephemeral_keypair.clone().secret()).unwrap();
    let result_hex = hex::encode(&result);
    let blob = EncryptedData {
        version: version,
        nonce: hex::encode(nonce),
        ephem_public: hex::encode(**ephemeral_keypair.public()),
        ciphertext: result_hex
    };
    return Ok(blob);
}


pub fn decrypt(encrypted_data: EncryptedData, recv_sk: [u8; 32]) -> Result<String, Error> {
    
    let recv_sk = KeyPair::<Secret, Public>::from_secret_slice(&recv_sk).unwrap();
    let pk_byte32 = to_byte32(&hex::decode(&encrypted_data.ephem_public).unwrap()); 
    let send_pk = Public::from_unsafe_slice(&pk_byte32).unwrap();
    let cipher_bytes = hex::decode(encrypted_data.ciphertext).unwrap();
    let nonce_bytes = hex::decode(encrypted_data.nonce).unwrap();
    let nonce = array_ref!(nonce_bytes, 0, 24).clone();
    println!("cipher_bytes: {:?}\n nonce: {:?}\n send_pk: {:?}\n recv_sk: {:?}\n", cipher_bytes, nonce, hex::encode(*send_pk), hex::encode(recv_sk.secret()) );
    let result = saltbabe::crypto_box::open(&cipher_bytes, &nonce, &send_pk, &recv_sk.secret()).unwrap();
    return Ok(str::from_utf8(&result.clone()).unwrap().to_string());
}

pub fn gen_keypair() -> KeyPair<Secret, Public> {
    
    KeyPair::<Secret, Public>::generate_keypair().unwrap()
    
}



#[cfg(test)]
mod tests {
    extern crate saltbabe;
    extern crate hex;
 

    #[test]
    fn get_encryption_publickey_works() {
        let recv_sk = "mJxmrVq8pfeR80HMZBTkjV+RiND1lqPqLuCdDUiduis=";
        let recv_sk_slice: [u8; 32] = crate::to_byte32(recv_sk.as_bytes());
        let public = **crate::get_encryption_keypair(recv_sk_slice).public();
        let pk_hex = hex::encode(public.clone());
        println!("Generated public: {}", pk_hex.clone());
        assert_eq!("262c59a6bb83b58a8120911bf6ed4863157089fc4bf0b294a95206d93146ad14", pk_hex);
    }
    #[test]
    fn to_encrypt() {
        let bob_sk = "mJxmrVq8pfeR80HMZBTkjV+RiND1lqPqLuCdDUiduis=";
        let bob_sk_slice: [u8; 32] = crate::to_byte32(bob_sk.as_bytes());
        let alice_sk = "Rz2i6pXUKcpWt6/b+mYtPPH+PiwhyLswOjcP8ZM0dyI=";
        let alice_sk_slice: [u8; 32] = crate::to_byte32(alice_sk.as_bytes());
        let alice = saltbabe::crypto_box::gen_keypair_from_secret(&bob_sk_slice);
        let bob = saltbabe::crypto_box::gen_keypair_from_secret(&alice_sk_slice);
        
        // Alice requests Bob's public encryption key so bob sends his encryption public key
        let bob_encrypt_pubkey = **crate::get_encryption_keypair(*bob.secret()).public();

        // Alice generates a random ephemeralKeyPair 
        let alice_ephemeral_keypair = saltbabe::crypto_box::gen_keypair_from_secret(alice.secret());

        // Alice uses her ephemeralKeypair.secretKey and Bob's encryptionPublicKey to encrypt the data using nacl.box.
        let encrypted = crate::encrypt(b"Hello world", None, bob_encrypt_pubkey, *alice_ephemeral_keypair.secret());

        // Alice sends encrypted blob to Bob
        println!("{:?}", encrypted);
    }

    #[test]
    fn to_decrypt() {
        let bob_sk = "mJxmrVq8pfeR80HMZBTkjV+RiND1lqPqLuCdDUiduis=";
        let bob_sk_slice: [u8; 32] = crate::to_byte32(bob_sk.as_bytes());
        let alice_sk = "Rz2i6pXUKcpWt6/b+mYtPPH+PiwhyLswOjcP8ZM0dyI=";
        let alice_sk_slice: [u8; 32] = crate::to_byte32(alice_sk.as_bytes());
        let alice = saltbabe::crypto_box::gen_keypair_from_secret(&bob_sk_slice);
        let bob = saltbabe::crypto_box::gen_keypair_from_secret(&alice_sk_slice);
        // Alice requests Bob's public encryption key so bob sends his encryption public key
        let bob_encrypt_keypair = crate::get_encryption_keypair(*bob.secret());

        // Alice generates a random ephemeralKeyPair 
        let alice_ephemeral_keypair = saltbabe::crypto_box::gen_keypair_from_secret(alice.secret());

        
        // Encrypt data first
        let encrypted_data = crate::encrypt(b"Hello world", None, **bob_encrypt_keypair.public(), *alice_ephemeral_keypair.secret()).unwrap();
        

        // Bob generates his encryptionPrivateKey
        let bob_encrypt_secret = bob_encrypt_keypair.secret(); 


        // Bob passes his encryptionPrivateKey
        // along with the encrypted blob 
        // to nacl.box.open(ciphertext, nonce, ephemPublicKey, myEncryptionPrivatekey)
        let decrypted = crate::decrypt(encrypted_data, *bob_encrypt_secret).unwrap();
        
        // Decrypted message
        println!("{:?}", decrypted);
    }
}