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);
}
}