use aes::cipher::{BlockDecryptMut, KeyIvInit};
use uuid::Uuid;
use crate::error::{Error, Result};
use crate::license_protocol::license::key_container::KeyType;
use crate::license_protocol::license::KeyContainer;
type Aes128CbcDec = cbc::Decryptor<aes::Aes128>;
#[derive(Debug, Clone)]
pub struct Key {
pub key_type: String,
pub kid: Uuid,
pub key: Vec<u8>,
pub permissions: Vec<String>,
}
impl Key {
#[must_use]
pub fn new(key_type: String, kid: Uuid, key: Vec<u8>, permissions: Vec<String>) -> Self {
Self {
key_type,
kid,
key,
permissions,
}
}
pub fn from_key_container(container: &KeyContainer, enc_key: &[u8]) -> Result<Self> {
let mut permissions = Vec::new();
if container.r#type() == KeyType::OperatorSession {
if let Some(ref perms) = container.operator_session_key_permissions {
if perms.allow_encrypt.unwrap_or(false) {
permissions.push("allow_encrypt".to_string());
}
if perms.allow_decrypt.unwrap_or(false) {
permissions.push("allow_decrypt".to_string());
}
if perms.allow_sign.unwrap_or(false) {
permissions.push("allow_sign".to_string());
}
if perms.allow_signature_verify.unwrap_or(false) {
permissions.push("allow_signature_verify".to_string());
}
}
}
let key_type = container
.r#type
.and_then(|v| KeyType::try_from(v).ok())
.map(|t| t.as_str_name().to_string())
.ok_or_else(|| Error::InvalidLicenseMessage("Missing key type".to_string()))?;
let kid_bytes = container
.id
.as_ref()
.ok_or_else(|| Error::InvalidLicenseMessage("Missing key ID".to_string()))?;
let kid = Self::kid_to_uuid(kid_bytes)?;
let key_bytes = container
.key
.as_ref()
.ok_or_else(|| Error::InvalidLicenseMessage("Missing key bytes".to_string()))?;
let iv_bytes = container
.iv
.as_ref()
.ok_or_else(|| Error::InvalidLicenseMessage("Missing IV bytes".to_string()))?;
let decrypted_key = Self::decrypt_key(key_bytes, iv_bytes, enc_key)?;
Ok(Self::new(key_type, kid, decrypted_key, permissions))
}
fn decrypt_key(encrypted_key: &[u8], iv: &[u8], enc_key: &[u8]) -> Result<Vec<u8>> {
if enc_key.len() != 16 {
return Err(Error::Other(format!(
"Invalid encryption key length: expected 16, got {}",
enc_key.len()
)));
}
if iv.len() != 16 {
return Err(Error::Other(format!(
"Invalid IV length: expected 16, got {}",
iv.len()
)));
}
let enc_key_arr: [u8; 16] = enc_key.try_into().unwrap();
let iv_arr: [u8; 16] = iv.try_into().unwrap();
let mut buffer = encrypted_key.to_vec();
let decryptor = Aes128CbcDec::new(&enc_key_arr.into(), &iv_arr.into());
let decrypted = decryptor
.decrypt_padded_mut::<aes::cipher::block_padding::Pkcs7>(&mut buffer)
.map_err(|e| Error::Other(format!("Failed to decrypt key: {}", e)))?;
Ok(decrypted.to_vec())
}
pub fn kid_to_uuid(kid: &[u8]) -> Result<Uuid> {
if kid.is_empty() {
return Ok(Uuid::nil());
}
if let Ok(s) = std::str::from_utf8(kid) {
if s.chars().all(|c| c.is_ascii_digit()) {
if let Ok(n) = s.parse::<u128>() {
return Ok(Uuid::from_u128(n));
}
}
}
if kid.len() == 16 {
return Ok(Uuid::from_slice(kid).unwrap_or_else(|_| Uuid::nil()));
}
if kid.len() == 32 {
if let Ok(s) = std::str::from_utf8(kid) {
if let Ok(uuid) = Uuid::parse_str(s) {
return Ok(uuid);
}
}
}
if kid.len() < 16 {
let mut padded = vec![0u8; 16];
padded[..kid.len()].copy_from_slice(kid);
return Ok(Uuid::from_slice(&padded).unwrap_or_else(|_| Uuid::nil()));
}
Ok(Uuid::from_slice(&kid[..16]).unwrap_or_else(|_| Uuid::nil()))
}
}