use crate::{ContentFormat, CryptoError, EncString, KeySlotId, KeySlotIds, store::KeyStoreContext};
pub trait CompositeEncryptable<Ids: KeySlotIds, Key: KeySlotId, Output> {
fn encrypt_composite(
&self,
ctx: &mut KeyStoreContext<Ids>,
key: Key,
) -> Result<Output, CryptoError>;
}
impl<Ids: KeySlotIds, Key: KeySlotId, T: CompositeEncryptable<Ids, Key, Output>, Output>
CompositeEncryptable<Ids, Key, Option<Output>> for Option<T>
{
fn encrypt_composite(
&self,
ctx: &mut KeyStoreContext<Ids>,
key: Key,
) -> Result<Option<Output>, CryptoError> {
self.as_ref()
.map(|value| value.encrypt_composite(ctx, key))
.transpose()
}
}
impl<Ids: KeySlotIds, Key: KeySlotId, T: CompositeEncryptable<Ids, Key, Output>, Output>
CompositeEncryptable<Ids, Key, Vec<Output>> for Vec<T>
{
fn encrypt_composite(
&self,
ctx: &mut KeyStoreContext<Ids>,
key: Key,
) -> Result<Vec<Output>, CryptoError> {
self.iter()
.map(|value| value.encrypt_composite(ctx, key))
.collect()
}
}
pub trait PrimitiveEncryptable<Ids: KeySlotIds, Key: KeySlotId, Output> {
fn encrypt(&self, ctx: &mut KeyStoreContext<Ids>, key: Key) -> Result<Output, CryptoError>;
}
impl<Ids: KeySlotIds, Key: KeySlotId, T: PrimitiveEncryptable<Ids, Key, Output>, Output>
PrimitiveEncryptable<Ids, Key, Option<Output>> for Option<T>
{
fn encrypt(
&self,
ctx: &mut KeyStoreContext<Ids>,
key: Key,
) -> Result<Option<Output>, CryptoError> {
self.as_ref()
.map(|value| value.encrypt(ctx, key))
.transpose()
}
}
impl<Ids: KeySlotIds> PrimitiveEncryptable<Ids, Ids::Symmetric, EncString> for &str {
fn encrypt(
&self,
ctx: &mut KeyStoreContext<Ids>,
key: Ids::Symmetric,
) -> Result<EncString, CryptoError> {
self.as_bytes().encrypt(ctx, key, ContentFormat::Utf8)
}
}
impl<Ids: KeySlotIds> PrimitiveEncryptable<Ids, Ids::Symmetric, EncString> for String {
fn encrypt(
&self,
ctx: &mut KeyStoreContext<Ids>,
key: Ids::Symmetric,
) -> Result<EncString, CryptoError> {
self.as_bytes().encrypt(ctx, key, ContentFormat::Utf8)
}
}
pub(crate) trait PrimitiveEncryptableWithContentType<Ids: KeySlotIds, Key: KeySlotId, Output> {
fn encrypt(
&self,
ctx: &mut KeyStoreContext<Ids>,
key: Key,
content_format: ContentFormat,
) -> Result<Output, CryptoError>;
}
impl<Ids: KeySlotIds> PrimitiveEncryptableWithContentType<Ids, Ids::Symmetric, EncString>
for &[u8]
{
fn encrypt(
&self,
ctx: &mut KeyStoreContext<Ids>,
key: Ids::Symmetric,
content_format: ContentFormat,
) -> Result<EncString, CryptoError> {
ctx.encrypt_data_with_symmetric_key(key, self, content_format)
}
}
impl<Ids: KeySlotIds> PrimitiveEncryptableWithContentType<Ids, Ids::Symmetric, EncString>
for Vec<u8>
{
fn encrypt(
&self,
ctx: &mut KeyStoreContext<Ids>,
key: Ids::Symmetric,
content_format: ContentFormat,
) -> Result<EncString, CryptoError> {
ctx.encrypt_data_with_symmetric_key(key, self, content_format)
}
}
impl<
Ids: KeySlotIds,
Key: KeySlotId,
T: PrimitiveEncryptableWithContentType<Ids, Key, Output>,
Output,
> PrimitiveEncryptableWithContentType<Ids, Key, Option<Output>> for Option<T>
{
fn encrypt(
&self,
ctx: &mut KeyStoreContext<Ids>,
key: Key,
content_format: crate::ContentFormat,
) -> Result<Option<Output>, CryptoError> {
self.as_ref()
.map(|value| value.encrypt(ctx, key, content_format))
.transpose()
}
}
impl<
Ids: KeySlotIds,
Key: KeySlotId,
T: PrimitiveEncryptableWithContentType<Ids, Key, Output>,
Output,
> PrimitiveEncryptableWithContentType<Ids, Key, Vec<Output>> for Vec<T>
{
fn encrypt(
&self,
ctx: &mut KeyStoreContext<Ids>,
key: Key,
content_format: ContentFormat,
) -> Result<Vec<Output>, CryptoError> {
self.iter()
.map(|value| value.encrypt(ctx, key, content_format))
.collect()
}
}
#[cfg(test)]
mod tests {
use crate::{
ContentFormat, Decryptable, KeyStore, PrimitiveEncryptable, PrivateKey,
PublicKeyEncryptionAlgorithm, SymmetricKeyAlgorithm,
traits::{encryptable::PrimitiveEncryptableWithContentType, tests::*},
};
fn test_store() -> KeyStore<TestIds> {
let store = KeyStore::<TestIds>::default();
let private_key = PrivateKey::make(PublicKeyEncryptionAlgorithm::RsaOaepSha1);
let mut ctx = store.context_mut();
let local_key_id = ctx.make_symmetric_key(SymmetricKeyAlgorithm::Aes256CbcHmac);
ctx.persist_symmetric_key(local_key_id, TestSymmKey::A(0))
.unwrap();
#[allow(deprecated)]
ctx.set_private_key(TestPrivateKey::A(0), private_key.clone())
.unwrap();
drop(ctx);
store
}
#[test]
fn test_encryptable_bytes() {
let store = test_store();
let mut ctx = store.context();
let key = TestSymmKey::A(0);
let vec_data = vec![1, 2, 3, 4, 5];
let slice_data: &[u8] = &vec_data;
let vec_encrypted = vec_data
.encrypt(&mut ctx, key, ContentFormat::OctetStream)
.unwrap();
let slice_encrypted = slice_data
.encrypt(&mut ctx, key, ContentFormat::OctetStream)
.unwrap();
let vec_decrypted: Vec<u8> = vec_encrypted.decrypt(&mut ctx, key).unwrap();
let slice_decrypted: Vec<u8> = slice_encrypted.decrypt(&mut ctx, key).unwrap();
assert_eq!(vec_data, vec_decrypted);
assert_eq!(slice_data, slice_decrypted);
}
#[test]
fn test_encryptable_string() {
let store = test_store();
let mut ctx = store.context();
let key = TestSymmKey::A(0);
let string_data = "Hello, World!".to_string();
let str_data: &str = string_data.as_str();
let string_encrypted = string_data.encrypt(&mut ctx, key).unwrap();
let str_encrypted = str_data.encrypt(&mut ctx, key).unwrap();
let string_decrypted: String = string_encrypted.decrypt(&mut ctx, key).unwrap();
let str_decrypted: String = str_encrypted.decrypt(&mut ctx, key).unwrap();
assert_eq!(string_data, string_decrypted);
assert_eq!(str_data, str_decrypted);
}
#[test]
fn test_encryptable_option_some() {
let store = test_store();
let mut ctx = store.context();
let key = TestSymmKey::A(0);
let string_data = Some("Hello, World!".to_string());
let string_encrypted = string_data.encrypt(&mut ctx, key).unwrap();
let string_decrypted: Option<String> = string_encrypted.decrypt(&mut ctx, key).unwrap();
assert_eq!(string_data, string_decrypted);
}
#[test]
fn test_encryptable_option_none() {
let store = test_store();
let mut ctx = store.context();
let key = TestSymmKey::A(0);
let none_data: Option<String> = None;
let string_encrypted = none_data.encrypt(&mut ctx, key).unwrap();
assert_eq!(string_encrypted, None);
let bad_key = TestSymmKey::B((0, 1));
let string_encrypted_bad = none_data.encrypt(&mut ctx, bad_key).unwrap();
assert_eq!(string_encrypted_bad, None);
}
}