use crate::constants::cose_algs;
use std::collections::BTreeMap;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Algorithm {
HmacSha256,
}
impl Algorithm {
pub fn identifier(&self) -> i32 {
match self {
Algorithm::HmacSha256 => cose_algs::HMAC_SHA_256,
}
}
pub fn from_identifier(id: i32) -> Option<Self> {
match id {
cose_algs::HMAC_SHA_256 => Some(Algorithm::HmacSha256),
_ => None,
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum KeyId {
Binary(Vec<u8>),
String(String),
}
impl KeyId {
pub fn binary<T: Into<Vec<u8>>>(data: T) -> Self {
KeyId::Binary(data.into())
}
pub fn string<T: Into<String>>(data: T) -> Self {
KeyId::String(data.into())
}
pub fn as_bytes(&self) -> &[u8] {
match self {
KeyId::Binary(data) => data,
KeyId::String(data) => data.as_bytes(),
}
}
}
#[derive(Debug, Clone, PartialEq)]
pub enum CborValue {
Integer(i64),
Bytes(Vec<u8>),
Text(String),
Map(BTreeMap<i32, CborValue>),
Array(Vec<CborValue>),
Null,
}
pub type HeaderMap = BTreeMap<i32, CborValue>;
pub mod labels {
use crate::constants::cose_labels;
pub const ALG: i32 = cose_labels::ALG;
pub const KID: i32 = cose_labels::KID;
}
#[derive(Debug, Clone, Default)]
pub struct Header {
pub protected: HeaderMap,
pub unprotected: HeaderMap,
}
impl Header {
pub fn new() -> Self {
Self::default()
}
pub fn with_algorithm(mut self, alg: Algorithm) -> Self {
self.protected
.insert(labels::ALG, CborValue::Integer(alg.identifier() as i64));
self
}
pub fn with_protected_key_id(mut self, kid: KeyId) -> Self {
match kid {
KeyId::Binary(data) => {
self.protected.insert(labels::KID, CborValue::Bytes(data));
}
KeyId::String(data) => {
self.protected.insert(labels::KID, CborValue::Text(data));
}
}
self
}
pub fn with_unprotected_key_id(mut self, kid: KeyId) -> Self {
match kid {
KeyId::Binary(data) => {
self.unprotected.insert(labels::KID, CborValue::Bytes(data));
}
KeyId::String(data) => {
self.unprotected.insert(labels::KID, CborValue::Text(data));
}
}
self
}
pub fn algorithm(&self) -> Option<Algorithm> {
if let Some(CborValue::Integer(alg)) = self.protected.get(&labels::ALG) {
Algorithm::from_identifier(*alg as i32)
} else {
None
}
}
pub fn key_id(&self) -> Option<KeyId> {
if let Some(kid) = self.protected.get(&labels::KID) {
return match kid {
CborValue::Bytes(data) => Some(KeyId::Binary(data.clone())),
CborValue::Text(data) => Some(KeyId::String(data.clone())),
_ => None,
};
}
if let Some(kid) = self.unprotected.get(&labels::KID) {
return match kid {
CborValue::Bytes(data) => Some(KeyId::Binary(data.clone())),
CborValue::Text(data) => Some(KeyId::String(data.clone())),
_ => None,
};
}
None
}
}