-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Adam Khayam
authored and
Adam Khayam
committed
May 6, 2024
1 parent
7eb2639
commit 9b783c7
Showing
2 changed files
with
160 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
use cosmian_crypto_core::{ | ||
reexport::rand_core::CryptoRngCore, Aes256Gcm, Dem, FixedSizeCBytes, Instantiable, Nonce, | ||
RandomFixedSizeCBytes, SymmetricKey, | ||
}; | ||
|
||
use crate::Error; | ||
|
||
/// Authenticated Encryption trait | ||
pub trait AE<const KEY_LENGTH: usize> { | ||
/// Encrypts the given plaintext `ptx` using the given `key`. | ||
fn encrypt( | ||
key: &SymmetricKey<KEY_LENGTH>, | ||
ptx: &[u8], | ||
rng: &mut impl CryptoRngCore, | ||
) -> Result<Vec<u8>, Error>; | ||
|
||
/// Decrypts the given ciphertext `ctx` using the given `key`. | ||
/// | ||
/// # Error | ||
/// | ||
/// Returns an error if the integrity of the ciphertext could not be verified. | ||
fn decrypt(key: &SymmetricKey<KEY_LENGTH>, ctx: &[u8]) -> Result<Vec<u8>, Error>; | ||
} | ||
|
||
impl AE<{ Self::KEY_LENGTH }> for Aes256Gcm { | ||
fn encrypt( | ||
key: &SymmetricKey<{ Self::KEY_LENGTH }>, | ||
ptx: &[u8], | ||
rng: &mut impl CryptoRngCore, | ||
) -> Result<Vec<u8>, Error> { | ||
let nonce = Nonce::<{ Self::NONCE_LENGTH }>::new(&mut *rng); | ||
let ciphertext = Self::new(key).encrypt(&nonce, ptx, None)?; | ||
Ok([nonce.as_bytes(), &ciphertext].concat()) | ||
} | ||
|
||
fn decrypt(key: &SymmetricKey<{ Self::KEY_LENGTH }>, ctx: &[u8]) -> Result<Vec<u8>, Error> { | ||
if ctx.len() < Self::NONCE_LENGTH { | ||
return Err(Error::CryptoCoreError( | ||
cosmian_crypto_core::CryptoCoreError::DecryptionError, | ||
)); | ||
} | ||
let nonce = Nonce::try_from_slice(&ctx[..Self::NONCE_LENGTH])?; | ||
Self::new(key) | ||
.decrypt(&nonce, &ctx[Self::NONCE_LENGTH..], None) | ||
.map_err(Error::CryptoCoreError) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
use cosmian_crypto_core::{ | ||
kdf256, Aes256Gcm, Dem, Instantiable, Nonce, RandomFixedSizeCBytes, Secret, SymmetricKey, | ||
}; | ||
|
||
use crate::{ | ||
abe_policy::{AccessPolicy, Policy}, | ||
api::{Covercrypt, CovercryptKEM}, | ||
core::SEED_LENGTH, | ||
Encapsulation, Error, MasterPublicKey, UserSecretKey, | ||
}; | ||
|
||
/// Encrypted header holding a `Covercrypt` encapsulation of a 256-byte seed, and metadata | ||
/// encrypted under the scheme AES256Gcm using a key derived from the encapsulated seed. | ||
#[derive(Debug, PartialEq, Eq)] | ||
pub struct EncryptedHeader { | ||
pub encapsulation: Encapsulation, | ||
pub encrypted_metadata: Option<Vec<u8>>, | ||
} | ||
|
||
impl EncryptedHeader { | ||
/// Generates an encrypted header for a random seed and the given metadata. | ||
/// Returns the encrypted header along with the encapsulated seed. | ||
/// | ||
/// - `cover_crypt` : `Covercrypt` object | ||
/// - `policy` : global policy | ||
/// - `public_key` : `Covercrypt` public key | ||
/// - `encryption_policy` : access policy used for the encapsulation | ||
/// - `header_metadata` : additional data symmetrically encrypted in the | ||
/// header | ||
/// - `authentication_data` : authentication data used in the DEM encryption | ||
pub fn generate( | ||
cover_crypt: &Covercrypt, | ||
policy: &Policy, | ||
public_key: &MasterPublicKey, | ||
encryption_policy: &AccessPolicy, | ||
metadata: Option<&[u8]>, | ||
authentication_data: Option<&[u8]>, | ||
) -> Result<(Secret<SEED_LENGTH>, Self), Error> { | ||
let (seed, encapsulation) = cover_crypt.encaps(public_key, policy, encryption_policy)?; | ||
|
||
let encrypted_metadata = metadata | ||
.map(|bytes| { | ||
let mut key = SymmetricKey::<{ Aes256Gcm::KEY_LENGTH }>::default(); | ||
kdf256!(&mut key, &seed, &[0u8]); | ||
let mut rng = cover_crypt.rng(); | ||
let nonce = Nonce::<{ Aes256Gcm::NONCE_LENGTH }>::new(&mut *rng); | ||
let aes = Aes256Gcm::new(&key); | ||
aes.encrypt(&nonce, bytes, authentication_data) | ||
}) | ||
.transpose()?; | ||
|
||
// Generating a new seed adding a variant component 1, to prevent reusing | ||
// seed used for the metadata encryption. | ||
let mut new_seed = Secret::<SEED_LENGTH>::default(); | ||
kdf256!(&mut new_seed, &seed, &[1u8]); | ||
|
||
Ok(( | ||
new_seed, | ||
Self { | ||
encapsulation, | ||
encrypted_metadata, | ||
}, | ||
)) | ||
} | ||
|
||
/// Decrypts the header with the given user secret key. | ||
/// | ||
/// - `cover_crypt` : `Covercrypt` object | ||
/// - `usk` : `Covercrypt` user secret key | ||
/// - `authentication_data` : authentication data used in the DEM encryption | ||
pub fn decrypt( | ||
&self, | ||
cover_crypt: &Covercrypt, | ||
usk: &UserSecretKey, | ||
authentication_data: Option<&[u8]>, | ||
) -> Result<Option<CleartextHeader>, Error> { | ||
cover_crypt | ||
.decaps(usk, &self.encapsulation)? | ||
.map(|seed| { | ||
let metadata = self | ||
.encrypted_metadata | ||
.as_ref() | ||
.map(|ctx| { | ||
let mut key = SymmetricKey::<{ Aes256Gcm::KEY_LENGTH }>::default(); | ||
kdf256!(&mut key, &seed, &[0u8]); | ||
let mut rng = cover_crypt.rng(); | ||
let nonce = Nonce::<{ Aes256Gcm::NONCE_LENGTH }>::new(&mut *rng); | ||
let aes = Aes256Gcm::new(&key); | ||
aes.decrypt(&nonce, ctx, authentication_data) | ||
}) | ||
.transpose()?; | ||
|
||
let mut new_seed = Secret::<SEED_LENGTH>::default(); | ||
kdf256!(&mut new_seed, &seed, &[1u8]); | ||
|
||
Ok(CleartextHeader { | ||
seed: new_seed, | ||
metadata, | ||
}) | ||
}) | ||
.transpose() | ||
} | ||
} | ||
|
||
/// Structure containing all data encrypted in an `EncryptedHeader`. | ||
/// | ||
/// - `symmetric_key` : DEM key | ||
/// - `metadata` : additional data symmetrically encrypted in a header | ||
#[derive(Debug, PartialEq, Eq)] | ||
pub struct CleartextHeader { | ||
pub seed: Secret<SEED_LENGTH>, | ||
pub metadata: Option<Vec<u8>>, | ||
} |