diff --git a/.gitignore b/.gitignore index 03314f7..6ca7e5c 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,5 @@ -Cargo.lock +# Cargo lock in subs +**/Cargo.lock + +# Generated by Cargo +**/target/ \ No newline at end of file diff --git a/Cargo.toml b/Cargo.toml index 82b3d21..f3ed47a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,6 +9,8 @@ ring = "0.14.6" quick-error = "1.2" rust-crypto = "0.2.36" primitives = { git = "https://github.com/CodeChain-io/rust-codechain-primitives.git", version = "0.4" } +aes-gcm-siv = "0.3.0" +aead = "0.2.0" [dev-dependencies] rand = "0.6.1" diff --git a/src/aes.rs b/src/aes.rs index be2d6a9..10bff57 100644 --- a/src/aes.rs +++ b/src/aes.rs @@ -14,6 +14,8 @@ // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . +use aead::{generic_array::GenericArray, Aead, Error, NewAead}; +use aes_gcm_siv::Aes256GcmSiv; use primitives::H256; use rcrypto::aes::KeySize::KeySize256; use rcrypto::aes::{cbc_decryptor, cbc_encryptor}; @@ -69,6 +71,32 @@ pub fn decrypt(encrypted_data: &[u8], key: &H256, iv: &u128) -> Result, Ok(final_result) } +// AES-256/GCM/Pkcs encryption. +pub fn encrypt_gcm_siv(data: &[u8], key: &H256, nonce: &u128) -> Result, Error> { + let generic_key = GenericArray::clone_from_slice(key); + let aead = Aes256GcmSiv::new(generic_key); + + let temp_nonce = &nonce.to_be_bytes(); + let nonce = GenericArray::from_slice(&temp_nonce[0..12]); + + let ciphertext = aead.encrypt(nonce, data).expect("encryption failure!"); + + Ok(ciphertext) +} + +// AES-256/GCM/Pkcs decryption. +pub fn decrypt_gcm_siv(encrypted_data: &[u8], key: &H256, input_nonce: &u128) -> Result, Error> { + let generic_key = GenericArray::clone_from_slice(key); + let aead = Aes256GcmSiv::new(generic_key); + + let bytes_nonce = &input_nonce.to_be_bytes(); + let nonce = GenericArray::from_slice(&bytes_nonce[0..12]); + + let plaintext = aead.decrypt(nonce, encrypted_data.as_ref()).expect("decryption failure!"); + + Ok(plaintext) +} + /// Encrypt a message (CTR mode). /// /// Key (`k`) length and initialisation vector (`iv`) length have to be 16 bytes each. @@ -128,8 +156,10 @@ mod tests { let encrypted_data = encrypt(message.as_bytes(), &key, &iv).ok().unwrap(); let decrypted_data = decrypt(&encrypted_data[..], &key, &iv).ok().unwrap(); - + let encrypted_data_with_gcm = encrypt_gcm_siv(message.as_bytes(), &key, &iv).ok().unwrap(); + let decrypted_data_with_gcm = decrypt_gcm_siv(&encrypted_data_with_gcm[..], &key, &iv).ok().unwrap(); assert_eq!(message.as_bytes(), &decrypted_data[..]); + assert_eq!(message.as_bytes(), &decrypted_data_with_gcm[..]); } #[test] @@ -144,6 +174,9 @@ mod tests { let encrypted = encrypt(&input, &key, &iv).unwrap(); let decrypted = decrypt(&encrypted, &key, &iv).unwrap(); + let encrypted_with_gcm = encrypt_gcm_siv(&input, &key, &iv).unwrap(); + let decrypted_with_gcm = decrypt_gcm_siv(&encrypted_with_gcm, &key, &iv).unwrap(); assert_eq!(input, decrypted); + assert_eq!(input, decrypted_with_gcm); } }