Add the IKM id and the nonce to the AAD
This commit is contained in:
parent
bf98245b04
commit
bc3cfe71dc
4 changed files with 66 additions and 24 deletions
|
@ -4,8 +4,8 @@ const CANONICALIZATION_BUFFER_SIZE: usize = 1024;
|
|||
const CANONICALIZATION_SEPARATOR: &str = ":";
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn join_canonicalized_str(s1: &str, s2: &str) -> String {
|
||||
format!("{s1}{CANONICALIZATION_SEPARATOR}{s2}")
|
||||
pub(crate) fn join_canonicalized_str(elems: &[String]) -> String {
|
||||
elems.join(CANONICALIZATION_SEPARATOR)
|
||||
}
|
||||
|
||||
pub(crate) fn canonicalize(context: &[impl AsRef<[u8]>]) -> String {
|
||||
|
@ -51,13 +51,31 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn test_join_canonicalized_empty() {
|
||||
assert_eq!(join_canonicalized_str("", ""), ":");
|
||||
assert_eq!(join_canonicalized_str(&[]), "");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_join_canonicalized_one() {
|
||||
assert_eq!(
|
||||
join_canonicalized_str(&["QWO7RGDt".to_string()]),
|
||||
"QWO7RGDt"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_join_canonicalized_one_empty() {
|
||||
assert_eq!(join_canonicalized_str(&[String::new()]), "");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_join_canonicalized_empty_str() {
|
||||
assert_eq!(join_canonicalized_str(&[String::new(), String::new()]), ":");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_join_canonicalized_with_data() {
|
||||
assert_eq!(
|
||||
join_canonicalized_str("QWO7RGDt:f-JmDPvU", "_Sfx61Fp"),
|
||||
join_canonicalized_str(&["QWO7RGDt:f-JmDPvU".into(), "_Sfx61Fp".into()]),
|
||||
"QWO7RGDt:f-JmDPvU:_Sfx61Fp"
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
use crate::canonicalization::{canonicalize, join_canonicalized_str};
|
||||
use crate::error::Result;
|
||||
use crate::kdf::{derive_key, KeyContext};
|
||||
use crate::{storage, InputKeyMaterialList};
|
||||
use crate::{storage, IkmId, InputKeyMaterialList};
|
||||
use std::time::{SystemTime, UNIX_EPOCH};
|
||||
|
||||
pub(crate) type DecryptionFunction = dyn Fn(&[u8], &EncryptedData, &str) -> Result<Vec<u8>>;
|
||||
pub(crate) type EncryptionFunction = dyn Fn(&[u8], &[u8], &str) -> Result<EncryptedData>;
|
||||
pub(crate) type EncryptionFunction = dyn Fn(&[u8], &[u8], &[u8], &str) -> Result<EncryptedData>;
|
||||
pub(crate) type GenNonceFunction = dyn Fn() -> Result<Vec<u8>>;
|
||||
|
||||
pub struct DataContext {
|
||||
ctx: Vec<String>,
|
||||
|
@ -33,14 +34,23 @@ pub(crate) struct EncryptedData {
|
|||
|
||||
#[inline]
|
||||
fn generate_aad(
|
||||
ikm_id: IkmId,
|
||||
nonce: &[u8],
|
||||
key_context: &KeyContext,
|
||||
data_context: &DataContext,
|
||||
time_period: Option<u64>,
|
||||
) -> String {
|
||||
let ikm_id_canon = canonicalize(&[ikm_id.to_le_bytes()]);
|
||||
let nonce_canon = canonicalize(&[nonce]);
|
||||
let elems = key_context.get_ctx_elems(time_period);
|
||||
let key_context_canon = canonicalize(&elems);
|
||||
let data_context_canon = canonicalize(data_context.get_ctx_elems());
|
||||
join_canonicalized_str(&key_context_canon, &data_context_canon)
|
||||
join_canonicalized_str(&[
|
||||
ikm_id_canon,
|
||||
nonce_canon,
|
||||
key_context_canon,
|
||||
data_context_canon,
|
||||
])
|
||||
}
|
||||
|
||||
pub fn encrypt(
|
||||
|
@ -57,9 +67,11 @@ pub fn encrypt(
|
|||
};
|
||||
let ikm = ikml.get_latest_ikm()?;
|
||||
let key = derive_key(ikm, key_context, tp);
|
||||
let aad = generate_aad(key_context, data_context, tp);
|
||||
let gen_nonce_function = ikm.scheme.get_gen_nonce();
|
||||
let nonce = gen_nonce_function()?;
|
||||
let aad = generate_aad(ikm.id, &nonce, key_context, data_context, tp);
|
||||
let encryption_function = ikm.scheme.get_encryption();
|
||||
let encrypted_data = encryption_function(&key, data.as_ref(), &aad)?;
|
||||
let encrypted_data = encryption_function(&key, &nonce, data.as_ref(), &aad)?;
|
||||
Ok(storage::encode_cipher(ikm.id, &encrypted_data, tp))
|
||||
}
|
||||
|
||||
|
@ -72,7 +84,7 @@ pub fn decrypt(
|
|||
let (ikm_id, encrypted_data, tp) = storage::decode_cipher(stored_data)?;
|
||||
let ikm = ikml.get_ikm_by_id(ikm_id)?;
|
||||
let key = derive_key(ikm, key_context, tp);
|
||||
let aad = generate_aad(key_context, data_context, tp);
|
||||
let aad = generate_aad(ikm.id, &encrypted_data.nonce, key_context, data_context, tp);
|
||||
let decryption_function = ikm.scheme.get_decryption();
|
||||
decryption_function(&key, &encrypted_data, &aad)
|
||||
}
|
||||
|
@ -82,7 +94,7 @@ mod tests {
|
|||
use super::*;
|
||||
use crate::{DataContext, KeyContext};
|
||||
|
||||
const TEST_CIPHERTEXT: &str = "AQAAAA:elFanOvp5DNewgq75T5U6wLYNn8zzo1n:9izU-8cw4oSIU4lqcYrfEBzOXluS7lVcUbF_KnEg0HFp2srx6xq3Bir91A:NgAAAAAAAAA";
|
||||
const TEST_CIPHERTEXT: &str = "AQAAAA:W-nzcGkPU6eWj_JjjqLpQk6WSe_CIUPF:we_HR8yD3XnQ9aaJlZFvqPitnDlQHexw4QPaYaOTzpHSWNW86QQrLRRZOg:NgAAAAAAAAA";
|
||||
const TEST_DATA: &[u8] = b"Lorem ipsum dolor sit amet.";
|
||||
const TEST_KEY_CTX: [&str; 3] = ["db_name", "table_name", "column_name"];
|
||||
const TEST_DATA_CTX: [&str; 1] = ["018db876-3d9d-79af-9460-55d17da991d8"];
|
||||
|
@ -170,12 +182,12 @@ mod tests {
|
|||
fn decrypt_invalid_ciphertext() {
|
||||
let tests = &[
|
||||
("", "empty data"),
|
||||
("AQAATA:elFanOvp5DNewgq75T5U6wLYNn8zzo1n:9izU-8cw4oSIU4lqcYrfEBzOXluS7lVcUbF_KnEg0HFp2srx6xq3Bir91A:NgAAAAAAAAA", "unknown ikm id"),
|
||||
("AQAAAA:MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0:9izU-8cw4oSIU4lqcYrfEBzOXluS7lVcUbF_KnEg0HFp2srx6xq3Bir91A:NgAAAAAAAAA", "invalid nonce"),
|
||||
("AQAAAA:elFanOvp5DNewgq75T5U6wLYNn8zzo1n:8izU-8cw4oSIU4lqcYrfEBzOXluS7lVcUbF_KnEg0HFp2srx6xq3Bir91A:NgAAAAAAAAA", "invalid ciphertext"),
|
||||
("AQAAAA:elFanOvp5DNewgq75T5U6wLYNn8zzo1n:9izU-8cw4oSIU4lqcYrfEBzOXluS7lVcUbF_KnEg0HFp2srx6xq3Bir91A:NaAAAAAAAAA", "invalid time period"),
|
||||
("AQAAAA:elFanOvp5DNewgq75T5U6wLYNn8zzo1n:9izU-8cw4oSIU4lqcYrfEBzOXluS7lVcUbF_KnEg0HFp2srx6xq3Bir91A:", "empty time period"),
|
||||
("AQAAAA:elFanOvp5DNewgq75T5U6wLYNn8zzo1n:9izU-8cw4oSIU4lqcYrfEBzOXluS7lVcUbF_KnEg0HFp2srx6xq3Bir91A", "missing time period"),
|
||||
("AQAATA:W-nzcGkPU6eWj_JjjqLpQk6WSe_CIUPF:we_HR8yD3XnQ9aaJlZFvqPitnDlQHexw4QPaYaOTzpHSWNW86QQrLRRZOg:NgAAAAAAAAA", "unknown ikm id"),
|
||||
("AQAAAA:MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0:we_HR8yD3XnQ9aaJlZFvqPitnDlQHexw4QPaYaOTzpHSWNW86QQrLRRZOg:NgAAAAAAAAA", "invalid nonce"),
|
||||
("AQAAAA:W-nzcGkPU6eWj_JjjqLpQk6WSe_CIUPF:8e_HR8yD3XnQ9aaJlZFvqPitnDlQHexw4QPaYaOTzpHSWNW86QQrLRRZOg:NgAAAAAAAAA", "invalid ciphertext"),
|
||||
("AQAAAA:W-nzcGkPU6eWj_JjjqLpQk6WSe_CIUPF:we_HR8yD3XnQ9aaJlZFvqPitnDlQHexw4QPaYaOTzpHSWNW86QQrLRRZOg:NaAAAAAAAAA", "invalid time period"),
|
||||
("AQAAAA:W-nzcGkPU6eWj_JjjqLpQk6WSe_CIUPF:we_HR8yD3XnQ9aaJlZFvqPitnDlQHexw4QPaYaOTzpHSWNW86QQrLRRZOg:", "empty time period"),
|
||||
("AQAAAA:W-nzcGkPU6eWj_JjjqLpQk6WSe_CIUPF:we_HR8yD3XnQ9aaJlZFvqPitnDlQHexw4QPaYaOTzpHSWNW86QQrLRRZOg", "missing time period"),
|
||||
];
|
||||
|
||||
let lst = get_ikm_lst();
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#[cfg(feature = "encryption")]
|
||||
use crate::encryption::{DecryptionFunction, EncryptionFunction};
|
||||
use crate::encryption::{DecryptionFunction, EncryptionFunction, GenNonceFunction};
|
||||
#[cfg(feature = "encryption")]
|
||||
use crate::kdf::KdfFunction;
|
||||
use crate::Error;
|
||||
|
@ -45,6 +45,14 @@ impl Scheme {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn get_gen_nonce(&self) -> Box<GenNonceFunction> {
|
||||
match self {
|
||||
Scheme::XChaCha20Poly1305WithBlake3 => {
|
||||
Box::new(xchacha20poly1305::xchacha20poly1305_gen_nonce)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<SchemeSerializeType> for Scheme {
|
||||
|
|
|
@ -3,18 +3,22 @@ use crate::error::Result;
|
|||
use chacha20poly1305::aead::{Aead, KeyInit, Payload};
|
||||
use chacha20poly1305::{Key, XChaCha20Poly1305, XNonce};
|
||||
|
||||
pub(crate) fn xchacha20poly1305_gen_nonce() -> Result<Vec<u8>> {
|
||||
// X-variant: the nonce's size is 192 bits (24 bytes)
|
||||
let mut nonce: [u8; 24] = [0; 24];
|
||||
getrandom::getrandom(&mut nonce)?;
|
||||
Ok(nonce.to_vec())
|
||||
}
|
||||
|
||||
pub(crate) fn xchacha20poly1305_encrypt(
|
||||
key: &[u8],
|
||||
nonce: &[u8],
|
||||
data: &[u8],
|
||||
aad: &str,
|
||||
) -> Result<EncryptedData> {
|
||||
// Adapt the key
|
||||
// Adapt the key and nonce
|
||||
let key = Key::from_slice(key);
|
||||
|
||||
// Generate a nonce
|
||||
let mut nonce: [u8; 24] = [0; 24];
|
||||
getrandom::getrandom(&mut nonce)?;
|
||||
let nonce = XNonce::from_slice(&nonce);
|
||||
let nonce = XNonce::from_slice(nonce);
|
||||
|
||||
// Prepare the payload
|
||||
let payload = Payload {
|
||||
|
|
Loading…
Reference in a new issue