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
//! The only goal of this library is to provide the easiest way to encrypt and decrypt a message to
//! a computer, its a very very minimal and provides no choices for the user to increase
//! performance or security.
//!
//! It is a minimal wrapper for the crate aes_siv and anyone wanting anything more advanced than
//! what this library provides should look in that crate where ALL the heavy lifting is performed.
//!
//! Encryption and decryption example:
//!
//! ``` rust
//! use std::str;
//! fn main() {
//!     let payload = "Hello world!".as_bytes();
//!     let password = b"hello wooooooooo";
//!
//!     let encrypted = simplestcrypt::encrypt_and_serialize(&password[..], &payload).unwrap();
//!     let plain = simplestcrypt::deserialize_and_decrypt(&password[..], &encrypted).unwrap();
//!
//!     println!("{:?}", str::from_utf8(&plain));
//! }
//! ```

use aes_siv::aead::{generic_array::GenericArray, Aead, NewAead};
use aes_siv::Aes128SivAead;

use rand::RngCore;
use serde::{Deserialize, Serialize};

/// Contains the Nonce used in the encryption process. This type is inflated when serialized using bincode
/// (16 bytes for the nonce + 8 bytes with size of the Vec + (rest of bytes for Vec ciphertext).
#[derive(Deserialize, Serialize)]
pub struct Encrypted {
    nonce: [u8; 16],
    ciphertext: Vec<u8>,
}

#[derive(Deserialize, Serialize, Debug)]
pub enum EncryptError {
    PasswordSize,
    EncryptionFail,
    SerializeFail,
}

#[derive(Deserialize, Serialize, Debug)]
pub enum DecryptError {
    PasswordSize,
    DecryptFail,
    DeserializeFail,
}

/// Encrypts the given bytes using a random nonce using Aes128SivAed
/// Password cannot be longer than 32 bytes
pub fn encrypt(password: &[u8], bytes: &[u8]) -> Result<Encrypted, EncryptError> {
    let mut key: [u8; 32] = [0; 32];

    if password.len() > key.len() {
        return Err(EncryptError::PasswordSize);
    };

    for (i, k) in password.iter().enumerate() {
        if i >= key.len() {
            break;
        } else {
            key[i] = *k;
        }
    }
    let key = GenericArray::from_slice(&key);

    let mut rng = rand::thread_rng();
    let mut nonce: [u8; 16] = [0; 16];
    rng.fill_bytes(&mut nonce);
    let noncearray = GenericArray::from_slice(&nonce);

    let cipher = Aes128SivAead::new(key);

    let ciphertext = cipher
        .encrypt(noncearray, bytes)
        .map_err(|_e| EncryptError::EncryptionFail)?;

    Ok(Encrypted { nonce, ciphertext })
}

/// Encrypts the given bytes using a random nonce using Aes128SivAed, and then serializes the
/// encryption along with the nonce using bincode. The resulting vector is then bincode serialized
/// Encrypted structure
///
/// Password cannot be longer than 32 bytes
pub fn encrypt_and_serialize(password: &[u8], bytes: &[u8]) -> Result<Vec<u8>, EncryptError> {
    let encrypted = encrypt(password, bytes)?;

    bincode::serialize(&encrypted).map_err(|_e| EncryptError::SerializeFail)
}

/// Decrypts an Encrypted structure using Aes128SivAead and returns a decrypted vector using the
/// given password
///
/// Password cannot be longer than 32 bytes
pub fn decrypt(password: &[u8], encrypted: &Encrypted) -> Result<Vec<u8>, DecryptError> {
    let mut key: [u8; 32] = [0; 32];

    if password.len() > key.len() {
        return Err(DecryptError::PasswordSize);
    };

    for (i, k) in password.iter().enumerate() {
        if i >= key.len() {
            break;
        } else {
            key[i] = *k;
        }
    }
    let key = GenericArray::from_slice(&key);
    let cipher = Aes128SivAead::new(key);
    let noncearray = GenericArray::from_slice(&encrypted.nonce);

    let bytes = cipher
        .decrypt(noncearray, encrypted.ciphertext.as_ref())
        .map_err(|_e| DecryptError::DecryptFail)?;

    Ok(bytes)
}

/// Assumes that the given bytes is a Bincode serialized Encrypted structure, and first
/// deserializes it and then tries to decrypt it using the given password bytes
///
/// Password cannot be longer than 32 bytes
pub fn deserialize_and_decrypt(
    password: &[u8],
    serialized: &[u8],
) -> Result<Vec<u8>, DecryptError> {
    let deser: Encrypted =
        bincode::deserialize(&serialized).map_err(|_e| DecryptError::DeserializeFail)?;

    let plain = decrypt(&password[..], &deser).map_err(|_e| DecryptError::DecryptFail)?;

    Ok(plain)
}