use crate::{Algorithm, CoseKey, Curve, Error, KeyType, Result};
use alloc::vec::Vec;
use core::fmt;
#[derive(Clone, Eq, PartialEq)]
pub struct SymmetricKey {
material: Vec<u8>,
algorithm: Option<Algorithm>,
kid: Option<Vec<u8>>,
}
impl SymmetricKey {
pub fn new(material: impl AsRef<[u8]>) -> Self {
Self {
material: material.as_ref().to_vec(),
algorithm: None,
kid: None,
}
}
pub fn with_algorithm(mut self, algorithm: Algorithm) -> Self {
self.algorithm = Some(algorithm);
self
}
pub fn with_kid(mut self, kid: impl AsRef<[u8]>) -> Self {
self.kid = Some(kid.as_ref().to_vec());
self
}
pub fn material(&self) -> &[u8] {
&self.material
}
pub fn algorithm(&self) -> Option<Algorithm> {
self.algorithm
}
pub fn kid(&self) -> Option<&[u8]> {
self.kid.as_deref()
}
pub fn into_cose_key(self) -> Result<CoseKey> {
let mut builder = CoseKeyBuilder::symmetric(self.material);
if let Some(algorithm) = self.algorithm {
builder = builder.algorithm(algorithm);
}
if let Some(kid) = self.kid {
builder = builder.kid(kid);
}
builder.build()
}
}
impl fmt::Debug for SymmetricKey {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("SymmetricKey")
.field("material_len", &self.material.len())
.field("algorithm", &self.algorithm)
.field("kid", &self.kid)
.finish_non_exhaustive()
}
}
#[derive(Clone, Default)]
pub struct CoseKeyBuilder {
key_type: Option<KeyType>,
algorithm: Option<Algorithm>,
curve: Option<Curve>,
kid: Option<Vec<u8>>,
symmetric: Option<Vec<u8>>,
has_private: Option<bool>,
}
impl fmt::Debug for CoseKeyBuilder {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("CoseKeyBuilder")
.field("key_type", &self.key_type)
.field("algorithm", &self.algorithm)
.field("curve", &self.curve)
.field("kid", &self.kid)
.field("symmetric_len", &self.symmetric.as_ref().map(Vec::len))
.field("has_private", &self.has_private)
.finish_non_exhaustive()
}
}
impl CoseKeyBuilder {
pub fn new() -> Self {
Self::default()
}
pub fn symmetric(material: impl AsRef<[u8]>) -> Self {
Self::new()
.key_type(KeyType::SYMMETRIC)
.symmetric_material(material)
}
pub fn key_type(mut self, key_type: KeyType) -> Self {
self.key_type = Some(key_type);
self
}
pub fn algorithm(mut self, algorithm: Algorithm) -> Self {
self.algorithm = Some(algorithm);
self
}
pub fn curve(mut self, curve: Curve) -> Self {
self.curve = Some(curve);
self
}
pub fn kid(mut self, kid: impl AsRef<[u8]>) -> Self {
self.kid = Some(kid.as_ref().to_vec());
self
}
pub fn symmetric_material(mut self, material: impl AsRef<[u8]>) -> Self {
self.symmetric = Some(material.as_ref().to_vec());
self
}
pub fn has_private(mut self, has_private: bool) -> Self {
self.has_private = Some(has_private);
self
}
pub fn build(self) -> Result<CoseKey> {
if let (Some(algorithm), Some(material)) = (self.algorithm, self.symmetric.as_deref()) {
validate_symmetric_len(algorithm, material.len())?;
}
let mut key = CoseKey::new()?;
if let Some(material) = self.symmetric {
key.set_symmetric(material)?;
}
if let Some(key_type) = self.key_type {
key.set_key_type(key_type);
}
if let Some(algorithm) = self.algorithm {
key.set_algorithm(algorithm);
}
if let Some(curve) = self.curve {
key.set_curve(curve);
}
if let Some(kid) = self.kid {
key.set_kid(kid);
}
if let Some(has_private) = self.has_private {
key.set_has_private(has_private);
}
Ok(key)
}
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct CoseKeyView {
pub key_type: KeyType,
pub algorithm: Algorithm,
pub curve: Curve,
pub kid: Vec<u8>,
pub symmetric_len: Option<usize>,
pub has_private: bool,
}
impl CoseKeyView {
pub fn from_key(key: &CoseKey) -> Self {
let raw = key.as_raw();
Self {
key_type: KeyType::from_id(raw.kty),
algorithm: Algorithm::from_id(raw.alg),
curve: Curve::from_id(raw.crv),
kid: key.kid().unwrap_or_default().to_vec(),
symmetric_len: key.symmetric_material().map(<[u8]>::len),
has_private: key.has_private(),
}
}
}
fn validate_symmetric_len(algorithm: Algorithm, len: usize) -> Result<()> {
if let Some(bits) = algorithm.key_bits_hint() {
if len * 8 != bits {
return Err(Error::CoseKeyType);
}
}
Ok(())
}