use crate::common;
#[cfg(feature = "json")]
use crate::errors::CoseResult;
use crate::errors::{CoseError, CoseResultWithRet};
use crate::headers;
#[cfg(feature = "json")]
use crate::keys;
use crate::message;
#[cfg(feature = "json")]
use crate::message::CoseMessage;
use cbor::{types::Tag, Config, Decoder};
#[cfg(feature = "json")]
use hex;
#[cfg(feature = "json")]
use serde_json::Value;
use std::io::Cursor;
pub fn cose_type_finder(bytes: &Vec<u8>) -> CoseResultWithRet<String> {
let input = Cursor::new(bytes);
let mut decoder = Decoder::new(Config::default(), input);
let tag = decoder.tag()?;
if tag == Tag::Unassigned(message::ENC0_TAG) {
Ok(message::ENC0_TYPE.to_string())
} else if tag == Tag::Unassigned(message::MAC0_TAG) {
Ok(message::MAC0_TYPE.to_string())
} else if tag == Tag::Unassigned(message::SIG1_TAG) {
Ok(message::SIG1_TYPE.to_string())
} else if tag == Tag::Unassigned(message::ENC_TAG) {
Ok(message::ENC_TYPE.to_string())
} else if tag == Tag::Unassigned(message::MAC_TAG) {
Ok(message::MAC_TYPE.to_string())
} else if tag == Tag::Unassigned(message::SIG_TAG) {
Ok(message::SIG_TYPE.to_string())
} else {
Err(CoseError::InvalidCoseStructure())
}
}
#[cfg(feature = "json")]
pub fn decode_json(
message_json: &str,
key: &keys::CoseKey,
tag: u64,
) -> CoseResultWithRet<Vec<u8>> {
let message_value: Value = serde_json::from_str(message_json)?;
let mut header = headers::CoseHeader::new();
decode_json_header(&mut header, &message_value["protected"].to_string(), true)?;
decode_json_header(
&mut header,
&message_value["unprotected"].to_string(),
false,
)?;
let payload = match &message_value["payload"] {
Value::String(r) => r.as_bytes().to_vec(),
_ => Vec::new(),
};
if tag == message::SIG1_TAG {
let mut sign = CoseMessage::new_sign();
sign.payload(payload);
sign.add_header(header);
sign.key(&key)?;
sign.secure_content(None)?;
sign.encode(true)?;
Ok(sign.bytes)
} else if tag == message::ENC0_TAG {
let mut enc = CoseMessage::new_encrypt();
enc.payload(payload);
enc.add_header(header);
enc.key(&key)?;
enc.secure_content(None)?;
enc.encode(true)?;
Ok(enc.bytes)
} else if tag == message::MAC0_TAG {
let mut mac = CoseMessage::new_mac();
mac.payload(payload);
mac.add_header(header);
mac.key(&key)?;
mac.secure_content(None)?;
mac.encode(true)?;
Ok(mac.bytes)
} else {
Ok(Vec::new())
}
}
#[cfg(feature = "json")]
fn decode_json_header(
header: &mut headers::CoseHeader,
json_header: &str,
prot: bool,
) -> CoseResult {
let json_value: Value = serde_json::from_str(json_header)?;
if json_value.get("crit") != None {
for i in json_value["crit"].as_array().unwrap().to_vec() {
header.crit.push(i.as_i64().unwrap() as i32);
}
}
if json_value.get("alg") != None {
let alg = match &json_value["alg"] {
Value::String(r) => common::get_alg_id(r.to_string())?,
Value::Number(v) => v.as_i64().unwrap() as i32,
_ => 0,
};
header.alg(alg, prot, false);
}
if json_value.get("kid") != None {
header.kid(
json_value["kid"].as_str().unwrap().as_bytes().to_vec(),
prot,
false,
);
}
if json_value.get("iv") != None {
header.iv(
hex::decode(json_value["iv"].as_str().unwrap().to_string())?,
prot,
false,
);
}
if json_value.get("partial iv") != None {
header.partial_iv(
hex::decode(json_value["partial iv"].as_str().unwrap().to_string())?,
prot,
false,
);
}
if json_value.get("content type") != None {
match &json_value["content_type"] {
Value::String(r) => {
header.content_type(
headers::ContentTypeTypes::Tstr(r.as_str().to_string()),
prot,
false,
);
}
Value::Number(v) => {
header.content_type(
headers::ContentTypeTypes::Uint(v.as_u64().unwrap() as u32),
prot,
false,
);
}
_ => (),
};
}
Ok(())
}
#[cfg(feature = "json")]
pub fn decode_json_key(json_key: &str) -> CoseResultWithRet<keys::CoseKey> {
let json_value: Value = serde_json::from_str(json_key)?;
let mut key = keys::CoseKey::new();
if json_value.get("alg") != None {
let alg = match &json_value["alg"] {
Value::String(r) => common::get_alg_id(r.to_string())?,
Value::Number(v) => v.as_i64().unwrap() as i32,
_ => 0,
};
key.alg(alg);
}
if json_value.get("kty") != None {
let kty = match &json_value["kty"] {
Value::String(r) => common::get_kty_id(r.to_string())?,
Value::Number(v) => v.as_i64().unwrap() as i32,
_ => 0,
};
key.kty(kty);
}
if json_value.get("crv") != None {
let crv = match &json_value["crv"] {
Value::String(r) => common::get_crv_id(r.to_string())?,
Value::Number(v) => v.as_i64().unwrap() as i32,
_ => 0,
};
key.crv(crv);
}
if json_value.get("key ops") != None {
let mut key_ops = Vec::new();
for i in json_value["key ops"].as_array().unwrap().to_vec() {
key_ops.push(match i {
Value::String(r) => common::get_key_op_id(r.to_string())?,
Value::Number(v) => v.as_i64().unwrap() as i32,
_ => 0,
});
}
key.key_ops(key_ops);
}
if json_value.get("x") != None {
key.x(hex::decode(json_value["x"].as_str().unwrap().to_string())?);
}
if json_value.get("y") != None {
match &json_value["y"] {
Value::String(r) => {
key.y(hex::decode(r.as_str().to_string())?);
}
_ => {}
};
}
if json_value.get("d") != None {
key.d(hex::decode(json_value["d"].as_str().unwrap().to_string())?);
}
if json_value.get("k") != None {
key.k(hex::decode(json_value["k"].as_str().unwrap().to_string())?);
}
Ok(key)
}