use bitwarden_encoding::B64;
use serde::{Deserialize, Serialize};
use crate::{
CryptoError, EncString, KeyEncryptable, KeyEncryptableWithContentType, KeySlotIds,
KeyStoreContext, PrimitiveEncryptable, SymmetricCryptoKey,
traits::PrimitiveEncryptableWithContentType,
};
#[derive(Clone, Copy, Debug, PartialEq)]
pub(crate) enum ContentFormat {
Utf8,
Pkcs8PrivateKey,
SPKIPublicKeyDer,
CoseKey,
CoseSign1,
CoseEncrypt0,
BitwardenLegacyKey,
OctetStream,
Cbor,
}
mod private {
pub trait Sealed {}
}
pub trait ConstContentFormat: private::Sealed {
#[allow(private_interfaces)]
fn content_format() -> ContentFormat;
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct Bytes<C: ConstContentFormat> {
inner: Vec<u8>,
_marker: std::marker::PhantomData<C>,
}
impl<C: ConstContentFormat> From<Vec<u8>> for Bytes<C> {
fn from(inner: Vec<u8>) -> Self {
Self {
inner,
_marker: std::marker::PhantomData,
}
}
}
impl<C: ConstContentFormat> From<&[u8]> for Bytes<C> {
fn from(inner: &[u8]) -> Self {
Self::from(inner.to_vec())
}
}
impl<C: ConstContentFormat + FromB64ContentFormat> From<&B64> for Bytes<C> {
fn from(val: &B64) -> Self {
Self::from(val.as_bytes())
}
}
impl<C: ConstContentFormat + FromB64ContentFormat> From<Bytes<C>> for B64 {
fn from(val: Bytes<C>) -> Self {
B64::from(val.as_ref())
}
}
impl<C: ConstContentFormat> AsRef<[u8]> for Bytes<C> {
fn as_ref(&self) -> &[u8] {
&self.inner
}
}
impl<C: ConstContentFormat> Bytes<C> {
pub fn to_vec(&self) -> Vec<u8> {
self.inner.clone()
}
}
#[derive(PartialEq, Eq, Clone, Debug)]
pub(crate) struct Utf8ContentFormat;
impl private::Sealed for Utf8ContentFormat {}
impl ConstContentFormat for Utf8ContentFormat {
fn content_format() -> ContentFormat {
ContentFormat::Utf8
}
}
pub(crate) type Utf8Bytes = Bytes<Utf8ContentFormat>;
#[derive(PartialEq, Eq, Clone, Debug)]
pub struct OctetStreamContentFormat;
impl private::Sealed for OctetStreamContentFormat {}
impl ConstContentFormat for OctetStreamContentFormat {
#[allow(private_interfaces)]
fn content_format() -> ContentFormat {
ContentFormat::OctetStream
}
}
pub type OctetStreamBytes = Bytes<OctetStreamContentFormat>;
#[derive(PartialEq, Eq, Clone, Debug)]
pub struct Pkcs8PrivateKeyDerContentFormat;
impl private::Sealed for Pkcs8PrivateKeyDerContentFormat {}
impl ConstContentFormat for Pkcs8PrivateKeyDerContentFormat {
#[allow(private_interfaces)]
fn content_format() -> ContentFormat {
ContentFormat::Pkcs8PrivateKey
}
}
pub type Pkcs8PrivateKeyBytes = Bytes<Pkcs8PrivateKeyDerContentFormat>;
#[derive(PartialEq, Eq, Clone, Debug)]
pub struct SpkiPublicKeyDerContentFormat;
impl private::Sealed for SpkiPublicKeyDerContentFormat {}
impl ConstContentFormat for SpkiPublicKeyDerContentFormat {
#[allow(private_interfaces)]
fn content_format() -> ContentFormat {
ContentFormat::SPKIPublicKeyDer
}
}
impl FromB64ContentFormat for SpkiPublicKeyDerContentFormat {}
pub type SpkiPublicKeyBytes = Bytes<SpkiPublicKeyDerContentFormat>;
pub trait CoseContentFormat {}
pub trait FromB64ContentFormat {}
#[derive(PartialEq, Eq, Clone, Debug)]
pub struct CoseKeyContentFormat;
impl private::Sealed for CoseKeyContentFormat {}
impl ConstContentFormat for CoseKeyContentFormat {
#[allow(private_interfaces)]
fn content_format() -> ContentFormat {
ContentFormat::CoseKey
}
}
impl CoseContentFormat for CoseKeyContentFormat {}
impl FromB64ContentFormat for CoseKeyContentFormat {}
pub type CoseKeyBytes = Bytes<CoseKeyContentFormat>;
#[derive(PartialEq, Eq, Clone, Debug)]
pub struct BitwardenLegacyKeyContentFormat;
impl private::Sealed for BitwardenLegacyKeyContentFormat {}
impl ConstContentFormat for BitwardenLegacyKeyContentFormat {
#[allow(private_interfaces)]
fn content_format() -> ContentFormat {
ContentFormat::BitwardenLegacyKey
}
}
impl FromB64ContentFormat for BitwardenLegacyKeyContentFormat {}
pub type BitwardenLegacyKeyBytes = Bytes<BitwardenLegacyKeyContentFormat>;
#[derive(PartialEq, Eq, Clone, Debug)]
pub struct CoseSign1ContentFormat;
impl private::Sealed for CoseSign1ContentFormat {}
impl ConstContentFormat for CoseSign1ContentFormat {
#[allow(private_interfaces)]
fn content_format() -> ContentFormat {
ContentFormat::CoseSign1
}
}
impl CoseContentFormat for CoseSign1ContentFormat {}
impl FromB64ContentFormat for CoseSign1ContentFormat {}
pub type CoseSign1Bytes = Bytes<CoseSign1ContentFormat>;
#[derive(PartialEq, Eq, Clone, Debug)]
pub struct CborContentFormat;
impl private::Sealed for CborContentFormat {}
impl ConstContentFormat for CborContentFormat {
#[allow(private_interfaces)]
fn content_format() -> ContentFormat {
ContentFormat::Cbor
}
}
pub type CborBytes = Bytes<CborContentFormat>;
#[derive(PartialEq, Eq, Clone, Debug)]
pub struct CoseEncrypt0ContentFormat;
impl private::Sealed for CoseEncrypt0ContentFormat {}
impl ConstContentFormat for CoseEncrypt0ContentFormat {
#[allow(private_interfaces)]
fn content_format() -> ContentFormat {
ContentFormat::CoseEncrypt0
}
}
pub type CoseEncrypt0Bytes = Bytes<CoseEncrypt0ContentFormat>;
impl<Ids: KeySlotIds, T: ConstContentFormat> PrimitiveEncryptable<Ids, Ids::Symmetric, EncString>
for Bytes<T>
{
fn encrypt(
&self,
ctx: &mut KeyStoreContext<Ids>,
key: Ids::Symmetric,
) -> Result<EncString, CryptoError> {
self.inner.encrypt(ctx, key, T::content_format())
}
}
impl<T: ConstContentFormat> KeyEncryptable<SymmetricCryptoKey, EncString> for &Bytes<T> {
fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result<EncString, CryptoError> {
self.as_ref().encrypt_with_key(key, T::content_format())
}
}
impl From<String> for Bytes<Utf8ContentFormat> {
fn from(val: String) -> Self {
Bytes::from(val.into_bytes())
}
}
impl From<&str> for Bytes<Utf8ContentFormat> {
fn from(val: &str) -> Self {
Bytes::from(val.as_bytes().to_vec())
}
}