1use rasn::prelude::*;
11
12pub type AsymmetricDecryptKeyIdentifier = rasn::types::OctetString;
15pub type CsrAttrs = SequenceOf<AttrOrOid>;
17
18pub const ASYMMETRIC_DECRYPT_KEY_OID: &Oid =
20 Oid::ISO_MEMBER_BODY_US_RSADSI_PKCS9_SMIME_AA_ASYMMETRIC_DECRYPT_KEY;
21
22#[derive(AsnType, Decode, Encode, Debug, PartialEq, Clone)]
25#[rasn(choice)]
26pub enum AttrOrOid {
27 Oid(ObjectIdentifier),
28 Attribute(Attribute),
29}
30
31#[derive(AsnType, Decode, Encode, Debug, PartialEq, Clone)]
32pub struct Attribute {
33 pub r#type: ObjectIdentifier,
34 pub values: SetOf<Any>,
35}
36
37#[cfg(test)]
38mod tests {
39 use pretty_assertions::assert_eq;
40
41 use alloc::{borrow::Cow, collections::BTreeSet, string::ToString, vec};
42
43 use super::*;
44
45 #[test]
46 fn csr_attributes_encode() {
47 let data = vec![
48 AttrOrOid::Oid(rasn::types::ObjectIdentifier::new_unchecked(Cow::from(
50 vec![1, 2, 840, 10045, 4, 3, 2],
51 ))),
52 AttrOrOid::Oid(rasn::types::ObjectIdentifier::new_unchecked(Cow::from(
54 vec![2, 5, 4, 3],
55 ))),
56 AttrOrOid::Oid(rasn::types::ObjectIdentifier::new_unchecked(Cow::from(
58 vec![1, 2, 840, 113549, 1, 9, 1],
59 ))),
60 AttrOrOid::Oid(rasn::types::ObjectIdentifier::new_unchecked(Cow::from(
62 vec![1, 2, 840, 113549, 1, 9, 7],
63 ))),
64 AttrOrOid::Oid(rasn::types::ObjectIdentifier::new_unchecked(Cow::from(
66 vec![1, 3, 6, 1, 5, 5, 7, 48, 1],
67 ))),
68 AttrOrOid::Oid(rasn::types::ObjectIdentifier::new_unchecked(Cow::from(
70 vec![1, 3, 6, 1, 4, 1, 311, 21, 20],
71 ))),
72 AttrOrOid::Oid(rasn::types::ObjectIdentifier::new_unchecked(Cow::from(
74 vec![1, 2, 840, 113549, 1, 1, 5],
75 ))),
76 AttrOrOid::Attribute(Attribute {
77 r#type: rasn::types::ObjectIdentifier::new_unchecked(Cow::from(vec![
78 1, 3, 6, 1, 5, 5, 7, 48, 1,
79 ])),
80 values: {
81 let mut b = BTreeSet::new();
82 b.insert(rasn::types::Any::new(
83 rasn::der::encode(
84 &rasn::types::PrintableString::try_from("And me second".to_string())
85 .unwrap(),
86 )
87 .unwrap(),
88 ));
89 b.insert(rasn::types::Any::new(rasn::der::encode(&false).unwrap()));
90 b.insert(rasn::types::Any::new(
91 rasn::der::encode(&rasn::types::Open::Null).unwrap(),
92 ));
93 b.insert(rasn::types::Any::new(
94 rasn::der::encode(
95 &rasn::types::VisibleString::try_from("Me first!").unwrap(),
96 )
97 .unwrap(),
98 ));
99 b
100 },
101 }),
102 ];
103
104 let bin = rasn::der::encode(&data).unwrap();
105 assert_eq!(
106 bin,
107 [
108 48, 114, 6, 8, 42, 134, 72, 206, 61, 4, 3, 2, 6, 3, 85, 4, 3, 6, 9, 42, 134, 72,
109 134, 247, 13, 1, 9, 1, 6, 9, 42, 134, 72, 134, 247, 13, 1, 9, 7, 6, 8, 43, 6, 1, 5,
110 5, 7, 48, 1, 6, 9, 43, 6, 1, 4, 1, 130, 55, 21, 20, 6, 9, 42, 134, 72, 134, 247,
111 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,
112 65, 110, 100, 32, 109, 101, 32, 115, 101, 99, 111, 110, 100, 26, 9, 77, 101, 32,
113 102, 105, 114, 115, 116, 33
114 ]
115 );
116 }
117
118 #[test]
119 fn csr_attributes_decode_1() {
120 let data = vec![
121 AttrOrOid::Oid(rasn::types::ObjectIdentifier::new_unchecked(Cow::from(
123 vec![1, 2, 840, 113549, 1, 9, 7],
124 ))),
125 AttrOrOid::Attribute(Attribute {
127 r#type: rasn::types::ObjectIdentifier::new_unchecked(Cow::from(vec![
128 1, 2, 840, 10045, 2, 1,
129 ])),
130 values: {
131 let mut b = BTreeSet::new();
132 b.insert(rasn::types::Any::new(
133 rasn::der::encode(&rasn::types::ObjectIdentifier::new_unchecked(
135 Cow::from(vec![1, 3, 132, 0, 34]),
136 ))
137 .unwrap(),
138 ));
139 b
140 },
141 }),
142 AttrOrOid::Attribute(Attribute {
143 r#type: rasn::types::ObjectIdentifier::new_unchecked(Cow::from(vec![
145 1, 2, 840, 113549, 1, 9, 14,
146 ])),
147 values: {
148 let mut b = BTreeSet::new();
149 b.insert(rasn::types::Any::new(
150 rasn::der::encode(&rasn::types::ObjectIdentifier::new_unchecked(
151 Cow::from(vec![1, 3, 6, 1, 1, 1, 1, 22]),
152 ))
153 .unwrap(),
154 ));
155 b
156 },
157 }),
158 AttrOrOid::Oid(rasn::types::ObjectIdentifier::new_unchecked(Cow::from(
160 vec![1, 2, 840, 10045, 4, 3, 3],
161 ))),
162 ];
163
164 let data_bin = rasn::der::encode(&data).unwrap();
165 let txt = "MEEGCSqGSIb3DQEJBzASBgcqhkjOPQIBMQcGBSuBBAAiMBYGCSqGSIb3DQEJDjEJBgcrBgEBAQEWBggqhkjOPQQDAw==";
166 let bin = base64::decode(txt).unwrap();
167 assert_eq!(data_bin, bin);
168 let decoded_data = rasn::der::decode::<CsrAttrs>(&bin);
169 assert!(decoded_data.is_ok());
170 let decoded_data = decoded_data.unwrap();
171 assert_eq!(decoded_data, data);
172 }
173
174 #[test]
175 fn csr_attributes_decode_2() {
176 let data = vec![
177 AttrOrOid::Oid(rasn::types::ObjectIdentifier::new_unchecked(Cow::from(
178 vec![1, 3, 6, 1, 1, 1, 1, 22],
179 ))),
180 AttrOrOid::Attribute(Attribute {
182 r#type: rasn::types::ObjectIdentifier::new_unchecked(Cow::from(vec![2, 999, 1])),
183 values: {
184 let mut b = BTreeSet::new();
185 b.insert(rasn::types::Any::new(
186 rasn::der::encode(
187 &rasn::types::PrintableString::try_from(
188 "Parse SET as 2.999.1 data".to_string(),
189 )
190 .unwrap(),
191 )
192 .unwrap(),
193 ));
194 b
195 },
196 }),
197 AttrOrOid::Oid(rasn::types::ObjectIdentifier::new_unchecked(Cow::from(
199 vec![1, 2, 840, 113549, 1, 9, 7],
200 ))),
201 AttrOrOid::Attribute(Attribute {
202 r#type: rasn::types::ObjectIdentifier::new_unchecked(Cow::from(vec![2, 999, 2])),
203 values: {
204 let mut b = BTreeSet::new();
205 b.insert(rasn::types::Any::new(
206 rasn::der::encode(&rasn::types::ObjectIdentifier::new_unchecked(
207 Cow::from(vec![2, 999, 3]),
208 ))
209 .unwrap(),
210 ));
211 b.insert(rasn::types::Any::new(
212 rasn::der::encode(&rasn::types::ObjectIdentifier::new_unchecked(
213 Cow::from(vec![2, 999, 4]),
214 ))
215 .unwrap(),
216 ));
217 b.insert(rasn::types::Any::new(
218 rasn::der::encode(
219 &rasn::types::PrintableString::try_from(
220 "Parse SET as 2.999.2 data".to_string(),
221 )
222 .unwrap(),
223 )
224 .unwrap(),
225 ));
226 b
227 },
228 }),
229 AttrOrOid::Oid(rasn::types::ObjectIdentifier::new_unchecked(Cow::from(
231 vec![1, 3, 36, 3, 3, 2, 8, 1, 1, 11],
232 ))),
233 AttrOrOid::Oid(rasn::types::ObjectIdentifier::new_unchecked(Cow::from(
235 vec![2, 16, 840, 1, 101, 3, 4, 2, 2],
236 ))),
237 ];
238
239 let data_bin = rasn::der::encode(&data).unwrap();
240 let txt = "MHwGBysGAQEBARYwIgYDiDcBMRsTGVBhcnNlIFNFVCBhcyAyLjk5OS4xIGRhdGEGCSqGSIb3DQEJBzAsBgOINwIxJQYDiDcDBgOINwQTGVBhcnNlIFNFVCBhcyAyLjk5OS4yIGRhdGEGCSskAwMCCAEBCwYJYIZIAWUDBAIC";
241 let bin = base64::decode(txt).unwrap();
242 assert_eq!(bin, data_bin);
243 let decoded_data = rasn::der::decode::<CsrAttrs>(&bin);
244 assert!(decoded_data.is_ok());
245 let decoded_data = decoded_data.unwrap();
246 assert_eq!(decoded_data, data);
247 }
248}