use std::fmt;
use std::str::FromStr;
use uuid::Uuid;
use base64::prelude::*;
use super::error::{Error, Result};
pub enum Algorithm {
RsaOaepMgf1p,
RsaOaepCouple(String, String),
}
impl Algorithm {
pub const RSA_OAEP_MGF1P: &str = "http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p";
pub const RSA_OAEP: &str = "http://www.w3.org/2001/04/xmlenc#rsa-oaep";
pub const MGF1_SHA1: &str = "http://www.w3.org/2009/xmlenc11#mgf1sha1";
pub const MGF1_SHA224: &str = "http://www.w3.org/2009/xmlenc11#mgf1sha224";
pub const MGF1_SHA256: &str = "http://www.w3.org/2009/xmlenc11#mgf1sha256";
pub const MGF1_SHA384: &str = "http://www.w3.org/2009/xmlenc11#mgf1sha384";
pub const MGF1_SHA512: &str = "http://www.w3.org/2009/xmlenc11#mgf1sha512";
pub const SHA1: &str = "http://www.w3.org/2000/09/xmldsig#sha1";
pub const SHA256: &str = "http://www.w3.org/2001/04/xmlenc#sha256";
pub const SHA384: &str = "http://www.w3.org/2001/04/xmlenc#sha384";
pub const SHA512: &str = "http://www.w3.org/2001/04/xmlenc#sha512";
pub const AES_GCM: &str = "http://www.w3.org/2009/xmlenc11#aes256-gcm";
}
#[derive(Debug, Clone, Default)]
pub struct KeyStore {
pub uuid: Uuid,
pub consumers: Vec<Consumer>,
pub resource_data_groups: Vec<ResourceDataGroup>,
}
impl KeyStore {
pub fn new(uuid: &str) -> Result<Self> {
Ok(Self {
uuid: Uuid::parse_str(uuid)?,
consumers: Vec::new(),
resource_data_groups: Vec::new(),
})
}
}
#[derive(Debug, Clone, Default)]
pub struct Consumer {
pub consumer_id: String,
pub key_id: Option<String>,
pub key_value: Option<KeyValue>,
}
impl Consumer {
pub fn new(consumer_id: impl Into<String>) -> Self {
Self {
consumer_id: consumer_id.into(),
key_id: None,
key_value: None,
}
}
}
#[derive(Debug, Clone, Default)]
pub struct KeyValue(pub String);
#[derive(Debug, Clone, Default)]
pub struct ResourceDataGroup {
pub key_uuid: Uuid,
pub access_rights: Vec<AccessRight>,
pub resource_datas: Vec<ResourceData>,
}
impl ResourceDataGroup {
pub fn new(uuid: &str) -> Result<Self> {
Ok(Self {
key_uuid: Uuid::parse_str(uuid)?,
access_rights: Vec::new(),
resource_datas: Vec::new(),
})
}
}
#[derive(Debug, Clone, Default)]
pub struct AccessRight {
pub consumer_index: u32,
pub kek_params: KEKParams,
pub cipher_data: CipherData,
}
impl AccessRight {
pub fn new(consumer_index: u32, kek_params: KEKParams, cipher_data: CipherData) -> Self {
Self {
consumer_index,
kek_params,
cipher_data,
}
}
}
#[derive(Debug, Clone)]
pub struct KEKParams {
pub wrapping_algorithm: String,
pub mgf_algorithm: Option<String>,
pub digest_method: Option<String>,
}
impl Default for KEKParams {
fn default() -> Self {
Self {
wrapping_algorithm: Algorithm::RSA_OAEP_MGF1P.to_string(),
mgf_algorithm: None,
digest_method: None,
}
}
}
#[derive(Debug, Clone, Default)]
pub struct Base64Value(pub Vec<u8>);
impl FromStr for Base64Value {
type Err = Error;
fn from_str(s: &str) -> Result<Self> {
Ok(Self(BASE64_STANDARD.decode(s)?))
}
}
impl fmt::Display for Base64Value {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", BASE64_STANDARD.encode(&self.0))
}
}
#[derive(Debug, Clone, Default)]
pub struct CipherData {
pub cipher_value: CipherValue,
}
impl CipherData {
pub fn new() -> Self {
Self { cipher_value: CipherValue::default() }
}
pub fn set_value(&mut self, value: &str) -> Result<&mut Self> {
self.cipher_value.0 = value.parse()?;
Ok(self)
}
pub fn get_value(&self) -> String {
self.cipher_value.0.to_string()
}
}
#[derive(Debug, Clone, Default)]
pub struct CipherValue(pub Base64Value);
#[derive(Debug, Clone, Default)]
pub struct ResourceData {
pub path: String,
pub cek_params: CEKParams,
}
impl ResourceData {
pub fn new(path: impl Into<String>, cek_params: CEKParams) -> Self {
Self {
path: path.into(),
cek_params,
}
}
}
#[derive(Debug, Clone)]
pub struct CEKParams {
pub encryption_algorithm: String,
pub compression: Compression,
pub iv: Option<Base64Value>,
pub tag: Option<Base64Value>,
pub aad: Option<Base64Value>,
}
impl Default for CEKParams {
fn default() -> Self {
Self {
encryption_algorithm: Algorithm::AES_GCM.to_string(),
compression: Compression::None,
iv: None,
tag: None,
aad: None,
}
}
}
impl CEKParams {
pub fn set_iv(&mut self, iv: &str) -> Result<&mut Self> {
self.iv = Some(iv.parse()?);
Ok(self)
}
pub fn set_tag(&mut self, tag: &str) -> Result<&mut Self> {
self.tag = Some(tag.parse()?);
Ok(self)
}
pub fn set_aad(&mut self, aad: &str) -> Result<&mut Self> {
self.aad = Some(aad.parse()?);
Ok(self)
}
pub fn get_iv(&self) -> Option<String> {
self.iv.as_ref().map(|iv| iv.to_string())
}
pub fn get_tag(&self) -> Option<String> {
self.tag.as_ref().map(|tag| tag.to_string())
}
pub fn get_aad(&self) -> Option<String> {
self.aad.as_ref().map(|aad| aad.to_string())
}
}
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
pub enum Compression {
#[default]
None,
Deflate,
}
impl fmt::Display for Compression {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Compression::None => write!(f, "none"),
Compression::Deflate => write!(f, "deflate"),
}
}
}
impl FromStr for Compression {
type Err = Error;
fn from_str(s: &str) -> Result<Self> {
match s.to_lowercase().as_str() {
"none" => Ok(Compression::None),
"deflate" => Ok(Compression::Deflate),
_ => Err(Error::InvalidAttribute {
name: "compression".to_string(),
message: format!("unknown compression: {}", s),
}),
}
}
}