Add support for AES128-GCM using HKDF-SHA256 to derive keys
This commit is contained in:
parent
56db45cbad
commit
ca86747862
7 changed files with 202 additions and 10 deletions
66
src/scheme/aes.rs
Normal file
66
src/scheme/aes.rs
Normal file
|
@ -0,0 +1,66 @@
|
|||
use crate::encrypted_data::EncryptedData;
|
||||
use crate::error::{Error, Result};
|
||||
use aes_gcm::aead::{Aead, KeyInit, Payload};
|
||||
use aes_gcm::{Aes128Gcm, Key, Nonce};
|
||||
|
||||
// 96 bits (12 bytes)
|
||||
const NONCE_SIZE: usize = 12;
|
||||
|
||||
pub(crate) fn aes128gcm_gen_nonce() -> Result<Vec<u8>> {
|
||||
let mut nonce: [u8; NONCE_SIZE] = [0; NONCE_SIZE];
|
||||
getrandom::getrandom(&mut nonce)?;
|
||||
Ok(nonce.to_vec())
|
||||
}
|
||||
|
||||
pub(crate) fn aes128gcm_encrypt(
|
||||
key: &[u8],
|
||||
nonce: &[u8],
|
||||
data: &[u8],
|
||||
aad: &str,
|
||||
) -> Result<EncryptedData> {
|
||||
// Adapt the key and nonce
|
||||
let key = Key::<Aes128Gcm>::from_slice(key);
|
||||
let nonce = Nonce::from_slice(&nonce[0..NONCE_SIZE]);
|
||||
|
||||
// Prepare the payload
|
||||
let payload = Payload {
|
||||
msg: data,
|
||||
aad: aad.as_bytes(),
|
||||
};
|
||||
|
||||
// Encrypt the payload
|
||||
let cipher = Aes128Gcm::new(key);
|
||||
let ciphertext = cipher.encrypt(nonce, payload)?;
|
||||
|
||||
// Return the result
|
||||
Ok(EncryptedData {
|
||||
nonce: nonce.to_vec(),
|
||||
ciphertext,
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn aes128gcm_decrypt(
|
||||
key: &[u8],
|
||||
encrypted_data: &EncryptedData,
|
||||
aad: &str,
|
||||
) -> Result<Vec<u8>> {
|
||||
// Adapt the key and nonce
|
||||
let key = Key::<Aes128Gcm>::from_slice(key);
|
||||
if encrypted_data.nonce.len() != NONCE_SIZE {
|
||||
return Err(Error::InvalidNonceSize(
|
||||
NONCE_SIZE,
|
||||
encrypted_data.nonce.len(),
|
||||
));
|
||||
}
|
||||
let nonce = Nonce::from_slice(&encrypted_data.nonce[0..NONCE_SIZE]);
|
||||
|
||||
// Prepare the payload
|
||||
let payload = Payload {
|
||||
msg: &encrypted_data.ciphertext,
|
||||
aad: aad.as_bytes(),
|
||||
};
|
||||
|
||||
// Decrypt the payload and return
|
||||
let cipher = Aes128Gcm::new(key);
|
||||
Ok(cipher.decrypt(nonce, payload)?)
|
||||
}
|
23
src/scheme/sha2.rs
Normal file
23
src/scheme/sha2.rs
Normal file
|
@ -0,0 +1,23 @@
|
|||
use hkdf::Hkdf;
|
||||
use sha2::Sha256;
|
||||
|
||||
pub(crate) fn sha256_derive(context: &str, ikm: &[u8]) -> Vec<u8> {
|
||||
let mut buff = [0u8; 16];
|
||||
let hkdf = Hkdf::<Sha256>::new(None, ikm);
|
||||
hkdf.expand(context.as_bytes(), &mut buff).unwrap();
|
||||
buff.to_vec()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
#[test]
|
||||
fn sha256_derive() {
|
||||
assert_eq!(
|
||||
super::sha256_derive("this is a context", b"7b47db8f365e5b602fd956d35985e9e1"),
|
||||
vec![
|
||||
0xad, 0xf2, 0xcd, 0x3a, 0x52, 0xfd, 0xf6, 0xad, 0x12, 0xce, 0xdd, 0x9a, 0x4d, 0x9e,
|
||||
0xcd, 0x4b,
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue