use rasn::prelude::*;
pub type AsymmetricDecryptKeyIdentifier = rasn::types::OctetString;
pub type CsrAttrs = SequenceOf<AttrOrOid>;
pub const ASYMMETRIC_DECRYPT_KEY_OID: &'static Oid =
Oid::ISO_MEMBER_BODY_US_RSADSI_PKCS9_SMIME_AA_ASYMMETRIC_DECRYPT_KEY;
#[derive(AsnType, Decode, Encode, Debug, PartialEq, Clone)]
#[rasn(choice)]
pub enum AttrOrOid {
Oid(ObjectIdentifier),
Attribute(Attribute),
}
#[derive(AsnType, Decode, Encode, Debug, PartialEq, Clone)]
pub struct Attribute {
pub r#type: ObjectIdentifier,
pub values: SetOf<Any>,
}
#[cfg(test)]
mod tests {
use pretty_assertions::assert_eq;
use alloc::{borrow::Cow, collections::BTreeSet, string::ToString, vec};
use super::*;
#[test]
fn csr_attributes_encode() {
let data = vec![
AttrOrOid::Oid(rasn::types::ObjectIdentifier::new_unchecked(Cow::from(
vec![1, 2, 840, 10045, 4, 3, 2],
))),
AttrOrOid::Oid(rasn::types::ObjectIdentifier::new_unchecked(Cow::from(
vec![2, 5, 4, 3],
))),
AttrOrOid::Oid(rasn::types::ObjectIdentifier::new_unchecked(Cow::from(
vec![1, 2, 840, 113549, 1, 9, 1],
))),
AttrOrOid::Oid(rasn::types::ObjectIdentifier::new_unchecked(Cow::from(
vec![1, 2, 840, 113549, 1, 9, 7],
))),
AttrOrOid::Oid(rasn::types::ObjectIdentifier::new_unchecked(Cow::from(
vec![1, 3, 6, 1, 5, 5, 7, 48, 1],
))),
AttrOrOid::Oid(rasn::types::ObjectIdentifier::new_unchecked(Cow::from(
vec![1, 3, 6, 1, 4, 1, 311, 21, 20],
))),
AttrOrOid::Oid(rasn::types::ObjectIdentifier::new_unchecked(Cow::from(
vec![1, 2, 840, 113549, 1, 1, 5],
))),
AttrOrOid::Attribute(Attribute {
r#type: rasn::types::ObjectIdentifier::new_unchecked(Cow::from(vec![
1, 3, 6, 1, 5, 5, 7, 48, 1,
])),
values: (|| {
let mut b = BTreeSet::new();
b.insert(rasn::types::Any::new(
rasn::der::encode(
&rasn::types::PrintableString::try_from("And me second".to_string())
.unwrap(),
)
.unwrap(),
));
b.insert(rasn::types::Any::new(rasn::der::encode(&false).unwrap()));
b.insert(rasn::types::Any::new(
rasn::der::encode(&rasn::types::Open::Null).unwrap(),
));
b.insert(rasn::types::Any::new(
rasn::der::encode(
&rasn::types::VisibleString::try_from("Me first!").unwrap(),
)
.unwrap(),
));
b
})(),
}),
];
let bin = rasn::der::encode(&data).unwrap();
assert_eq!(
bin,
[
48, 114, 6, 8, 42, 134, 72, 206, 61, 4, 3, 2, 6, 3, 85, 4, 3, 6, 9, 42, 134, 72,
134, 247, 13, 1, 9, 1, 6, 9, 42, 134, 72, 134, 247, 13, 1, 9, 7, 6, 8, 43, 6, 1, 5,
5, 7, 48, 1, 6, 9, 43, 6, 1, 4, 1, 130, 55, 21, 20, 6, 9, 42, 134, 72, 134, 247,
13, 1, 1, 5, 48, 43, 6, 8, 43, 6, 1, 5, 5, 7, 48, 1, 49, 31, 1, 1, 0, 5, 0, 19, 13,
65, 110, 100, 32, 109, 101, 32, 115, 101, 99, 111, 110, 100, 26, 9, 77, 101, 32,
102, 105, 114, 115, 116, 33
]
);
}
#[test]
fn csr_attributes_decode_1() {
let data = vec![
AttrOrOid::Oid(rasn::types::ObjectIdentifier::new_unchecked(Cow::from(
vec![1, 2, 840, 113549, 1, 9, 7],
))),
AttrOrOid::Attribute(Attribute {
r#type: rasn::types::ObjectIdentifier::new_unchecked(Cow::from(vec![
1, 2, 840, 10045, 2, 1,
])),
values: (|| {
let mut b = BTreeSet::new();
b.insert(rasn::types::Any::new(
rasn::der::encode(&rasn::types::ObjectIdentifier::new_unchecked(
Cow::from(vec![1, 3, 132, 0, 34]),
))
.unwrap(),
));
b
})(),
}),
AttrOrOid::Attribute(Attribute {
r#type: rasn::types::ObjectIdentifier::new_unchecked(Cow::from(vec![
1, 2, 840, 113549, 1, 9, 14,
])),
values: (|| {
let mut b = BTreeSet::new();
b.insert(rasn::types::Any::new(
rasn::der::encode(&rasn::types::ObjectIdentifier::new_unchecked(
Cow::from(vec![1, 3, 6, 1, 1, 1, 1, 22]),
))
.unwrap(),
));
b
})(),
}),
AttrOrOid::Oid(rasn::types::ObjectIdentifier::new_unchecked(Cow::from(
vec![1, 2, 840, 10045, 4, 3, 3],
))),
];
let data_bin = rasn::der::encode(&data).unwrap();
let txt = "MEEGCSqGSIb3DQEJBzASBgcqhkjOPQIBMQcGBSuBBAAiMBYGCSqGSIb3DQEJDjEJBgcrBgEBAQEWBggqhkjOPQQDAw==";
let bin = base64::decode(&txt).unwrap();
assert_eq!(data_bin, bin);
let decoded_data = rasn::der::decode::<CsrAttrs>(&bin);
assert!(decoded_data.is_ok());
let decoded_data = decoded_data.unwrap();
assert_eq!(decoded_data, data);
}
#[test]
fn csr_attributes_decode_2() {
let data = vec![
AttrOrOid::Oid(rasn::types::ObjectIdentifier::new_unchecked(Cow::from(
vec![1, 3, 6, 1, 1, 1, 1, 22],
))),
AttrOrOid::Attribute(Attribute {
r#type: rasn::types::ObjectIdentifier::new_unchecked(Cow::from(vec![2, 999, 1])),
values: (|| {
let mut b = BTreeSet::new();
b.insert(rasn::types::Any::new(
rasn::der::encode(
&rasn::types::PrintableString::try_from(
"Parse SET as 2.999.1 data".to_string(),
)
.unwrap(),
)
.unwrap(),
));
b
})(),
}),
AttrOrOid::Oid(rasn::types::ObjectIdentifier::new_unchecked(Cow::from(
vec![1, 2, 840, 113549, 1, 9, 7],
))),
AttrOrOid::Attribute(Attribute {
r#type: rasn::types::ObjectIdentifier::new_unchecked(Cow::from(vec![2, 999, 2])),
values: (|| {
let mut b = BTreeSet::new();
b.insert(rasn::types::Any::new(
rasn::der::encode(&rasn::types::ObjectIdentifier::new_unchecked(
Cow::from(vec![2, 999, 3]),
))
.unwrap(),
));
b.insert(rasn::types::Any::new(
rasn::der::encode(&rasn::types::ObjectIdentifier::new_unchecked(
Cow::from(vec![2, 999, 4]),
))
.unwrap(),
));
b.insert(rasn::types::Any::new(
rasn::der::encode(
&rasn::types::PrintableString::try_from(
"Parse SET as 2.999.2 data".to_string(),
)
.unwrap(),
)
.unwrap(),
));
b
})(),
}),
AttrOrOid::Oid(rasn::types::ObjectIdentifier::new_unchecked(Cow::from(
vec![1, 3, 36, 3, 3, 2, 8, 1, 1, 11],
))),
AttrOrOid::Oid(rasn::types::ObjectIdentifier::new_unchecked(Cow::from(
vec![2, 16, 840, 1, 101, 3, 4, 2, 2],
))),
];
let data_bin = rasn::der::encode(&data).unwrap();
let txt = "MHwGBysGAQEBARYwIgYDiDcBMRsTGVBhcnNlIFNFVCBhcyAyLjk5OS4xIGRhdGEGCSqGSIb3DQEJBzAsBgOINwIxJQYDiDcDBgOINwQTGVBhcnNlIFNFVCBhcyAyLjk5OS4yIGRhdGEGCSskAwMCCAEBCwYJYIZIAWUDBAIC";
let bin = base64::decode(&txt).unwrap();
assert_eq!(bin, data_bin);
let decoded_data = rasn::der::decode::<CsrAttrs>(&bin);
assert!(decoded_data.is_ok());
let decoded_data = decoded_data.unwrap();
assert_eq!(decoded_data, data);
}
}