1use std::io::{BufRead, Write};
5use linked_hash_map::LinkedHashMap;
6
7use cbor_event::{self, de::Deserializer, se::{Serialize, Serializer}};
8
9pub mod builders;
10pub mod cbor;
11mod crypto;
12pub mod error;
13mod serialization;
14#[macro_use]
15pub mod utils;
16
17use builders::*;
18use cbor::*;
19use error::*;
20use utils::*;
21
22
23#[derive(Clone, Debug)]
24pub struct ProtectedHeaderMap(Vec<u8>);
25
26to_from_bytes!(ProtectedHeaderMap);
27
28
29impl ProtectedHeaderMap {
30 pub fn new_empty() -> Self {
31 Self(Vec::new())
32 }
33
34 pub fn new(header_map: &HeaderMap) -> Self {
36 if header_map.keys().len() == 0 {
37 Self::new_empty()
38 } else {
39 Self(header_map.to_bytes())
40 }
41 }
42
43 pub fn deserialized_headers(&self) -> HeaderMap {
44 if self.0.is_empty() {
45 HeaderMap::new()
46 } else {
47 HeaderMap::from_bytes(self.0.clone())
48 .expect("ProtectedHeaderMap shouldn't be able to be constructed without being valid HeaderMap bytes")
49 }
50 }
51}
52
53
54#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
55pub enum LabelKind {
56 Int,
57 Text,
58}
59
60#[derive(Clone, Debug, Hash, Eq, Ord, PartialEq, PartialOrd)]
61enum LabelEnum {
62 Int(Int),
63 Text(String),
64}
65
66
67#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
68pub struct Label(LabelEnum);
69
70to_from_bytes!(Label);
71
72
73impl Label {
74 pub fn new_int(int: &Int) -> Self {
75 Self(LabelEnum::Int(int.clone()))
76 }
77
78 pub fn new_text(text: String) -> Self {
79 Self(LabelEnum::Text(text))
80 }
81
82 pub fn kind(&self) -> LabelKind {
83 match &self.0 {
84 LabelEnum::Int(_) => LabelKind::Int,
85 LabelEnum::Text(_) => LabelKind::Text,
86 }
87 }
88
89 pub fn as_int(&self) -> Option<Int> {
90 match &self.0 {
91 LabelEnum::Int(x) => Some(x.clone()),
92 _ => None,
93 }
94 }
95
96 pub fn as_text(&self) -> Option<String> {
97 match &self.0 {
98 LabelEnum::Text(x) => Some(x.clone()),
99 _ => None,
100 }
101 }
102
103 pub fn from_algorithm_id(id: AlgorithmId) -> Self {
107 id.into()
108 }
109
110 pub fn from_key_type(key_type: KeyType) -> Self {
111 key_type.into()
112 }
113
114 pub fn from_ec_key(ec_key: ECKey) -> Self {
115 ec_key.into()
116 }
117
118 pub fn from_curve_type(curve_type: CurveType)-> Self {
119 curve_type.into()
120 }
121
122 pub fn from_key_operation(key_op: KeyOperation) -> Self {
123 key_op.into()
124 }
125}
126
127
128#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
129pub struct Labels(Vec<Label>);
130
131to_from_bytes!(Labels);
132
133
134impl Labels {
135 pub fn new() -> Self {
136 Self(Vec::new())
137 }
138
139 pub fn len(&self) -> usize {
140 self.0.len()
141 }
142
143 pub fn get(&self, index: usize) -> Label {
144 self.0[index].clone()
145 }
146
147 pub fn add(&mut self, elem: &Label) {
148 self.0.push(elem.clone());
149 }
150}
151
152
153#[derive(Clone, Debug)]
154pub struct COSESignatures(Vec<COSESignature>);
155
156to_from_bytes!(COSESignatures);
157
158
159impl COSESignatures {
160 pub fn new() -> Self {
161 Self(Vec::new())
162 }
163
164 pub fn len(&self) -> usize {
165 self.0.len()
166 }
167
168 pub fn get(&self, index: usize) -> COSESignature {
169 self.0[index].clone()
170 }
171
172 pub fn add(&mut self, elem: &COSESignature) {
173 self.0.push(elem.clone());
174 }
175}
176
177
178#[derive(Clone, Debug)]
179pub struct CounterSignature(COSESignatures);
180
181to_from_bytes!(CounterSignature);
182
183
184impl CounterSignature {
185 pub fn new_single(cose_signature: &COSESignature) -> Self {
186 let mut sigs = COSESignatures::new();
187 sigs.add(cose_signature);
188 Self(sigs)
189 }
190
191 pub fn new_multi(cose_signatures: &COSESignatures) -> Self {
192 Self(cose_signatures.clone())
193 }
194
195 pub fn signatures(&self) -> COSESignatures {
196 self.0.clone()
197 }
198}
199
200
201#[derive(Clone, Debug)]
202pub struct HeaderMap {
203 algorithm_id: Option<Label>,
205 criticality: Option<Labels>,
207 content_type: Option<Label>,
209 key_id: Option<Vec<u8>>,
211 init_vector: Option<Vec<u8>>,
213 partial_init_vector: Option<Vec<u8>>,
215 counter_signature: Option<Box<CounterSignature>>,
217 other_headers: LinkedHashMap<Label, CBORValue>,
219}
220
221to_from_bytes!(HeaderMap);
222
223
224impl HeaderMap {
225 pub fn set_algorithm_id(&mut self, algorithm_id: &Label) {
226 self.algorithm_id = Some(algorithm_id.clone())
227 }
228
229 pub fn algorithm_id(&self) -> Option<Label> {
230 self.algorithm_id.clone()
231 }
232
233 pub fn set_criticality(&mut self, criticality: &Labels) {
234 self.criticality = Some(criticality.clone())
235 }
236
237 pub fn criticality(&self) -> Option<Labels> {
238 self.criticality.clone()
239 }
240
241 pub fn set_content_type(&mut self, content_type: &Label) {
242 self.content_type = Some(content_type.clone())
243 }
244
245 pub fn content_type(&self) -> Option<Label> {
246 self.content_type.clone()
247 }
248
249 pub fn set_key_id(&mut self, key_id: Vec<u8>) {
250 self.key_id = Some(key_id)
251 }
252
253 pub fn key_id(&self) -> Option<Vec<u8>> {
254 self.key_id.clone()
255 }
256
257 pub fn set_init_vector(&mut self, init_vector: Vec<u8>) {
258 self.init_vector = Some(init_vector)
259 }
260
261 pub fn init_vector(&self) -> Option<Vec<u8>> {
262 self.init_vector.clone()
263 }
264
265 pub fn set_partial_init_vector(&mut self, partial_init_vector: Vec<u8>) {
266 self.partial_init_vector = Some(partial_init_vector)
267 }
268
269 pub fn partial_init_vector(&self) -> Option<Vec<u8>> {
270 self.partial_init_vector.clone()
271 }
272
273 pub fn set_counter_signature(&mut self, counter_signature: &CounterSignature) {
274 self.counter_signature = Some(Box::new(counter_signature.clone()))
275 }
276
277 pub fn counter_signature(&self) -> Option<CounterSignature> {
278 use std::ops::Deref;
279 self.counter_signature.as_ref().map(|sig| sig.deref().clone())
280 }
281
282 pub fn header(&self, label: &Label) -> Option<CBORValue> {
283 match label.0 {
284 LabelEnum::Int(Int(1)) => self.algorithm_id.as_ref().map(label_to_value),
285 LabelEnum::Int(Int(2)) => self.criticality.as_ref().map(labels_to_value),
286 LabelEnum::Int(Int(3)) => self.content_type.as_ref().map(label_to_value),
287 LabelEnum::Int(Int(4)) => self.key_id.as_ref().map(|kid| CBORValue::new_bytes(kid.clone())),
288 LabelEnum::Int(Int(5)) => self.init_vector.as_ref().map(|iv| CBORValue::new_bytes(iv.clone())),
289 LabelEnum::Int(Int(6)) => self.partial_init_vector.as_ref().map(|piv| CBORValue::new_bytes(piv.clone())),
290 LabelEnum::Int(Int(7)) => {
291 let bytes = self.counter_signature.as_ref()?.to_bytes();
292 let mut raw = Deserializer::from(std::io::Cursor::new(bytes));
293 Some(CBORValue::deserialize(&mut raw).unwrap())
294 },
295 _ => self.other_headers.get(label).map(|val| val.clone()),
296 }
297 }
298
299 pub fn set_header(&mut self, label: &Label, value: &CBORValue) -> Result<(), JsError> {
300 match label.0 {
301 LabelEnum::Int(Int(1)) => {
302 self.algorithm_id = Some(value_to_label(value)?);
303 },
304 LabelEnum::Int(Int(2)) => {
305 let labels = match &value.0 {
306 CBORValueEnum::Array(vals) => vals,
307 _ => return Err(JsError::from_str(&format!("Expected array of labels, found: {:?}", value))),
308 }.values.iter().map(value_to_label).collect::<Result<_, JsError>>()?;
309 self.criticality = Some(Labels(labels));
310 },
311 LabelEnum::Int(Int(3)) => {
312 self.content_type = Some(value_to_label(value)?);
313 },
314 LabelEnum::Int(Int(4)) => {
315 self.key_id = Some(value_to_bytes(value)?);
316 },
317 LabelEnum::Int(Int(5)) => {
318 self.init_vector = Some(value_to_bytes(value)?);
319 },
320 LabelEnum::Int(Int(6)) => {
321 self.partial_init_vector = Some(value_to_bytes(value)?);
322 },
323 LabelEnum::Int(Int(7)) => {
324 let mut buf = Serializer::new_vec();
325 value.serialize(&mut buf).unwrap();
326 let bytes = buf.finalize();
327 self.counter_signature = Some(Box::new(CounterSignature::from_bytes(bytes)?));
328 },
329 _ => {
330 self.other_headers.insert(label.clone(), value.clone());
331 },
332 }
333 Ok(())
334 }
335
336 pub fn keys(&self) -> Labels {
337 let mut keys = self.other_headers.keys().into_iter().map(|k| k.clone()).collect::<Vec<Label>>();
338 if self.algorithm_id.is_some() {
339 keys.push(Label::new_int(&Int::new_i32(1)));
340 }
341 if self.criticality.is_some() {
342 keys.push(Label::new_int(&Int::new_i32(2)));
343 }
344 if self.content_type.is_some() {
345 keys.push(Label::new_int(&Int::new_i32(3)));
346 }
347 if self.key_id.is_some() {
348 keys.push(Label::new_int(&Int::new_i32(4)));
349 }
350 if self.init_vector.is_some() {
351 keys.push(Label::new_int(&Int::new_i32(5)));
352 }
353 if self.partial_init_vector.is_some() {
354 keys.push(Label::new_int(&Int::new_i32(6)));
355 }
356 if self.counter_signature.is_some() {
357 keys.push(Label::new_int(&Int::new_i32(7)));
358 }
359 Labels(keys)
360 }
361
362 pub fn new() -> Self {
363 Self {
364 algorithm_id: None,
365 criticality: None,
366 content_type: None,
367 key_id: None,
368 init_vector: None,
369 partial_init_vector: None,
370 counter_signature: None,
371 other_headers: LinkedHashMap::new(),
372 }
373 }
374}
375
376
377#[derive(Clone, Debug)]
378pub struct Headers {
379 protected: ProtectedHeaderMap,
380 unprotected: HeaderMap,
381}
382
383to_from_bytes!(Headers);
384
385
386impl Headers {
387 pub fn protected(&self) -> ProtectedHeaderMap {
388 self.protected.clone()
389 }
390
391 pub fn unprotected(&self) -> HeaderMap {
392 self.unprotected.clone()
393 }
394
395 pub fn new(protected_: &ProtectedHeaderMap, unprotected_: &HeaderMap) -> Self {
396 Self {
397 protected: protected_.clone(),
398 unprotected: unprotected_.clone(),
399 }
400 }
401}
402
403
404#[derive(Clone, Debug)]
405pub struct COSESignature {
406 headers: Headers,
407 signature: Vec<u8>,
408}
409
410to_from_bytes!(COSESignature);
411
412
413impl COSESignature {
414 pub fn headers(&self) -> Headers {
415 self.headers.clone()
416 }
417
418 pub fn signature(&self) -> Vec<u8> {
419 self.signature.clone()
420 }
421
422 pub fn new(headers: &Headers, signature: Vec<u8>) -> Self {
423 Self {
424 headers: headers.clone(),
425 signature: signature,
426 }
427 }
428}
429
430
431#[derive(Clone, Debug)]
432pub struct COSESign1 {
433 headers: Headers,
434 payload: Option<Vec<u8>>,
435 signature: Vec<u8>,
436}
437
438to_from_bytes!(COSESign1);
439
440
441impl COSESign1 {
442 pub fn headers(&self) -> Headers {
443 self.headers.clone()
444 }
445
446 pub fn payload(&self) -> Option<Vec<u8>> {
447 self.payload.clone()
448 }
449
450 pub fn signature(&self) -> Vec<u8> {
451 self.signature.clone()
452 }
453
454 pub fn signed_data(&self, external_aad: Option<Vec<u8>>, external_payload: Option<Vec<u8>>) -> Result<SigStructure, JsError> {
458 let payload = match external_payload {
459 Some(p) => p.clone(),
460 None => self.payload.clone().ok_or_else(|| JsError::from_str("Payload was not present but no external payload supplied"))?,
461 };
462 Ok(SigStructure::new(
463 SigContext::Signature1,
464 &self.headers.protected,
465 external_aad.clone().unwrap_or(vec![]),
466 payload))
467 }
468
469 pub fn new(headers: &Headers, payload: Option<Vec<u8>>, signature: Vec<u8>) -> Self {
470 Self {
471 headers: headers.clone(),
472 payload: payload,
473 signature: signature,
474 }
475 }
476}
477
478
479#[derive(Clone, Debug)]
480pub struct COSESign {
481 headers: Headers,
482 payload: Option<Vec<u8>>,
483 signatures: COSESignatures,
484}
485
486to_from_bytes!(COSESign);
487
488
489impl COSESign {
490 pub fn headers(&self) -> Headers {
491 self.headers.clone()
492 }
493
494 pub fn payload(&self) -> Option<Vec<u8>> {
495 self.payload.clone()
496 }
497
498 pub fn signatures(&self) -> COSESignatures {
499 self.signatures.clone()
500 }
501
502 pub fn new(headers: &Headers, payload: Option<Vec<u8>>, signatures: &COSESignatures) -> Self {
503 Self {
504 headers: headers.clone(),
505 payload: payload,
506 signatures: signatures.clone(),
507 }
508 }
509}
510
511
512#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
513pub enum SignedMessageKind {
514 COSESIGN,
515 COSESIGN1,
516}
517
518#[derive(Clone, Debug)]
519enum SignedMessageEnum {
520 COSESIGN(COSESign),
521 COSESIGN1(COSESign1),
522}
523
524
525#[derive(Clone, Debug)]
526pub struct SignedMessage(SignedMessageEnum);
527
528to_from_bytes!(SignedMessage);
529
530
531impl SignedMessage {
532 pub fn new_cose_sign(cose_sign: &COSESign) -> Self {
533 Self(SignedMessageEnum::COSESIGN(cose_sign.clone()))
534 }
535
536 pub fn new_cose_sign1(cose_sign1: &COSESign1) -> Self {
537 Self(SignedMessageEnum::COSESIGN1(cose_sign1.clone()))
538 }
539
540 pub fn from_user_facing_encoding(s: &str) -> Result<SignedMessage, JsError> {
541 use std::io::Cursor;
542 use byteorder::{BigEndian, ReadBytesExt};
543
544 if !s.starts_with("cms_") {
545 return Err(JsError::from_str("SignedMessage user facing encoding must start with \"cms_\""));
546 }
547 let without_prefix = &s[4..];
548 let without_checksum_padding = without_prefix.trim_end_matches('=');
552 if without_checksum_padding.len() < 8 {
554 return Err(JsError::from_str("insufficient length - missing checksum"));
555 }
556 let (body_base64, checksum_base64) = without_checksum_padding.split_at(without_checksum_padding.len() - 6);
557 let body_bytes = base64_url::decode(body_base64)
558 .map_err(|e| JsError::from_str(&format!("Could not decode body from base64url: {:?}", e)))?;
559 let checksum_bytes = base64_url::decode(checksum_base64)
560 .map_err(|e| JsError::from_str(&format!("Could not decode checksum from base64url: {:?}", e)))?;
561 let expected_checksum = Cursor::new(checksum_bytes).read_u32::<BigEndian>().unwrap();
562 let computed_checksum = crypto::fnv32a(&body_bytes);
563 if expected_checksum != computed_checksum {
564 return Err(JsError::from_str(&format!("checksum does not match body. shown: {}, computed from body: {}", expected_checksum, computed_checksum)));
565 }
566 Self::from_bytes(body_bytes).map_err(|e| JsError::from_str(&format!("Invalid body: {:?}", e)))
567 }
568
569 pub fn to_user_facing_encoding(&self) -> String {
570 use byteorder::{BigEndian, WriteBytesExt};
571
572 let body_bytes = self.to_bytes();
573 let checksum = crypto::fnv32a(&body_bytes);
574 let mut checksum_bytes = vec![];
575 checksum_bytes.write_u32::<BigEndian>(checksum).unwrap();
576 format!("cms_{}{}", base64_url::encode(&body_bytes), base64_url::encode(&checksum_bytes))
577 }
578
579 pub fn kind(&self) -> SignedMessageKind {
580 match &self.0 {
581 SignedMessageEnum::COSESIGN(_) => SignedMessageKind::COSESIGN,
582 SignedMessageEnum::COSESIGN1(_) => SignedMessageKind::COSESIGN1,
583 }
584 }
585
586 pub fn as_cose_sign(&self) -> Option<COSESign> {
587 match &self.0 {
588 SignedMessageEnum::COSESIGN(x) => Some(x.clone()),
589 _ => None,
590 }
591 }
592
593 pub fn as_cose_sign1(&self) -> Option<COSESign1> {
594 match &self.0 {
595 SignedMessageEnum::COSESIGN1(x) => Some(x.clone()),
596 _ => None,
597 }
598 }
599}
600
601
602#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
603pub enum SigContext {
604 Signature,
605 Signature1,
606 CounterSignature
607}
608
609
610#[derive(Clone, Debug)]
613pub struct SigStructure {
614 context: SigContext,
615 body_protected: ProtectedHeaderMap,
616 sign_protected: Option<ProtectedHeaderMap>,
617 external_aad: Vec<u8>,
618 payload: Vec<u8>,
619}
620
621to_from_bytes!(SigStructure);
622
623
624impl SigStructure {
625 pub fn context(&self) -> SigContext {
626 self.context.clone()
627 }
628
629 pub fn body_protected(&self) -> ProtectedHeaderMap {
630 self.body_protected.clone()
631 }
632
633 pub fn sign_protected(&self) -> Option<ProtectedHeaderMap> {
634 self.sign_protected.clone()
635 }
636
637 pub fn external_aad(&self) -> Vec<u8> {
638 self.external_aad.clone()
639 }
640
641 pub fn payload(&self) -> Vec<u8> {
642 self.payload.clone()
643 }
644
645 pub fn set_sign_protected(&mut self, sign_protected: &ProtectedHeaderMap) {
646 self.sign_protected = Some(sign_protected.clone());
647 }
648
649 pub fn new(context: SigContext, body_protected: &ProtectedHeaderMap, external_aad: Vec<u8>, payload: Vec<u8>) -> Self {
650 Self {
651 context,
652 body_protected: body_protected.clone(),
653 sign_protected: None,
654 external_aad,
655 payload,
656 }
657 }
658}
659
660
661#[derive(Clone, Debug)]
662pub struct COSEEncrypt0 {
663 headers: Headers,
664 ciphertext: Option<Vec<u8>>,
665}
666
667to_from_bytes!(COSEEncrypt0);
668
669
670impl COSEEncrypt0 {
671 pub fn headers(&self) -> Headers {
672 self.headers.clone()
673 }
674
675 pub fn ciphertext(&self) -> Option<Vec<u8>> {
676 self.ciphertext.clone()
677 }
678
679 pub fn new(headers: &Headers, ciphertext: Option<Vec<u8>>) -> Self {
680 Self {
681 headers: headers.clone(),
682 ciphertext: ciphertext,
683 }
684 }
685}
686
687
688#[derive(Clone, Debug)]
689pub struct PasswordEncryption(COSEEncrypt0);
690
691to_from_bytes!(PasswordEncryption);
692
693
694impl PasswordEncryption {
695 pub fn new(data: &COSEEncrypt0) -> Self {
696 Self(data.clone())
697 }
698}
699
700
701#[derive(Clone, Debug)]
702pub struct COSERecipients(Vec<COSERecipient>);
703
704to_from_bytes!(COSERecipients);
705
706
707impl COSERecipients {
708 pub fn new() -> Self {
709 Self(Vec::new())
710 }
711
712 pub fn len(&self) -> usize {
713 self.0.len()
714 }
715
716 pub fn get(&self, index: usize) -> COSERecipient {
717 self.0[index].clone()
718 }
719
720 pub fn add(&mut self, elem: &COSERecipient) {
721 self.0.push(elem.clone());
722 }
723}
724
725
726#[derive(Clone, Debug)]
727pub struct COSEEncrypt {
728 headers: Headers,
729 ciphertext: Option<Vec<u8>>,
730 recipients: COSERecipients,
731}
732
733to_from_bytes!(COSEEncrypt);
734
735
736impl COSEEncrypt {
737 pub fn headers(&self) -> Headers {
738 self.headers.clone()
739 }
740
741 pub fn ciphertext(&self) -> Option<Vec<u8>> {
742 self.ciphertext.clone()
743 }
744
745 pub fn recipients(&self) -> COSERecipients {
746 self.recipients.clone()
747 }
748
749 pub fn new(headers: &Headers, ciphertext: Option<Vec<u8>>, recipients: &COSERecipients) -> Self {
750 Self {
751 headers: headers.clone(),
752 ciphertext: ciphertext,
753 recipients: recipients.clone(),
754 }
755 }
756}
757
758
759#[derive(Clone, Debug)]
760pub struct COSERecipient {
761 headers: Headers,
762 ciphertext: Option<Vec<u8>>,
763}
764
765to_from_bytes!(COSERecipient);
766
767
768impl COSERecipient {
769 pub fn headers(&self) -> Headers {
770 self.headers.clone()
771 }
772
773 pub fn ciphertext(&self) -> Option<Vec<u8>> {
774 self.ciphertext.clone()
775 }
776
777 pub fn new(headers: &Headers, ciphertext: Option<Vec<u8>>) -> Self {
778 Self {
779 headers: headers.clone(),
780 ciphertext: ciphertext,
781 }
782 }
783}
784
785
786#[derive(Clone, Debug)]
787pub struct PubKeyEncryption(COSEEncrypt);
788
789to_from_bytes!(PubKeyEncryption);
790
791
792impl PubKeyEncryption {
793 pub fn new(data: &COSEEncrypt) -> Self {
794 Self(data.clone())
795 }
796}
797
798
799#[derive(Clone, Debug)]
800pub struct COSEKey {
801 key_type: Label,
803 key_id: Option<Vec<u8>>,
805 algorithm_id: Option<Label>,
807 key_ops: Option<Labels>,
809 base_init_vector: Option<Vec<u8>>,
811 other_headers: LinkedHashMap<Label, CBORValue>,
813}
814
815to_from_bytes!(COSEKey);
816
817
818impl COSEKey {
819 pub fn set_key_type(&mut self, key_type: &Label) {
820 self.key_type = key_type.clone()
821 }
822
823 pub fn key_type(&self) -> Label {
824 self.key_type.clone()
825 }
826
827 pub fn set_key_id(&mut self, key_id: Vec<u8>) {
828 self.key_id = Some(key_id)
829 }
830
831 pub fn key_id(&self) -> Option<Vec<u8>> {
832 self.key_id.clone()
833 }
834
835 pub fn set_algorithm_id(&mut self, algorithm_id: &Label) {
836 self.algorithm_id = Some(algorithm_id.clone())
837 }
838
839 pub fn algorithm_id(&self) -> Option<Label> {
840 self.algorithm_id.clone()
841 }
842
843 pub fn set_key_ops(&mut self, key_ops: &Labels) {
844 self.key_ops = Some(key_ops.clone())
845 }
846
847 pub fn key_ops(&self) -> Option<Labels> {
848 self.key_ops.clone()
849 }
850
851 pub fn set_base_init_vector(&mut self, base_init_vector: Vec<u8>) {
852 self.base_init_vector = Some(base_init_vector)
853 }
854
855 pub fn base_init_vector(&self) -> Option<Vec<u8>> {
856 self.base_init_vector.clone()
857 }
858
859 pub fn header(&self, label: &Label) -> Option<CBORValue> {
860 fn label_to_value(label: &Label) -> CBORValue {
861 match &label.0 {
862 LabelEnum::Int(x) => CBORValue::new_int(x),
863 LabelEnum::Text(x) => CBORValue::new_text(x.to_string()),
864 }
865 }
866 match label.0 {
867 LabelEnum::Int(Int(1)) => Some(label_to_value(&self.key_type)),
868 LabelEnum::Int(Int(2)) => self.key_id.as_ref().map(|kid| CBORValue::new_bytes(kid.clone())),
869 LabelEnum::Int(Int(3)) => self.algorithm_id.as_ref().map(label_to_value),
870 LabelEnum::Int(Int(4)) => self.key_ops.as_ref().map(labels_to_value),
871 LabelEnum::Int(Int(5)) => self.base_init_vector.as_ref().map(|biv| CBORValue::new_bytes(biv.clone())),
872 _ => self.other_headers.get(label).map(|val| val.clone()),
873 }
874 }
875
876 pub fn set_header(&mut self, label: &Label, value: &CBORValue) -> Result<(), JsError> {
877 match label.0 {
878 LabelEnum::Int(Int(1)) => {
879 self.key_type = value_to_label(value)?;
880 },
881 LabelEnum::Int(Int(2)) => {
882 self.key_id = Some(value_to_bytes(value)?);
883 },
884 LabelEnum::Int(Int(3)) => {
885 self.algorithm_id = Some(value_to_label(value)?);
886 },
887 LabelEnum::Int(Int(4)) => {
888 let labels = match &value.0 {
889 CBORValueEnum::Array(vals) => vals,
890 _ => return Err(JsError::from_str(&format!("Expected array of labels, found: {:?}", value))),
891 }.values.iter().map(value_to_label).collect::<Result<_, JsError>>()?;
892 self.key_ops = Some(Labels(labels));
893 },
894 LabelEnum::Int(Int(5)) => {
895 self.base_init_vector = Some(value_to_bytes(value)?);
896 },
897 _ => {
898 self.other_headers.insert(label.clone(), value.clone());
899 },
900 }
901 Ok(())
902 }
903
904 pub fn new(key_type: &Label) -> Self {
905 Self {
906 key_type: key_type.clone(),
907 key_id: None,
908 algorithm_id: None,
909 key_ops: None,
910 base_init_vector: None,
911 other_headers: LinkedHashMap::new(),
912 }
913 }
914}
915
916#[cfg(test)]
917mod tests {
918 use super::*;
919
920 fn label_int(x: i32) -> Label {
921 Label::new_int(&Int::new_i32(x))
922 }
923
924 fn label_str(s: &str) -> Label {
925 Label::new_text(String::from(s))
926 }
927
928 #[test]
929 fn cose_key_other_headers_overlap() {
930 let kty1 = label_str("key type 1");
931 let kid1 = vec![1u8, 2u8, 5u8, 10u8, 20u8, 40u8, 50u8];
932 let alg1 = label_int(-10);
933 let mut ops1 = Labels::new();
934 ops1.add(&label_str("dfdsfds"));
935 ops1.add(&label_int(-130));
936 let biv1 = vec![0u8; 128];
937
938 let kty1_value = CBORValue::new_text(String::from("key type 1"));
939 let kid1_value = CBORValue::new_bytes(kid1.clone());
940 let alg1_value = CBORValue::new_int(&Int::new_i32(-10));
941 let ops1_value = CBORValue::new_array(&vec![CBORValue::new_text(String::from("dfdsfds")), CBORValue::new_int(&Int::new_i32(-130))].into());
942 let biv1_value = CBORValue::new_bytes(biv1.clone());
943
944 let kty2 = label_int(352);
945 let kid2 = vec![7u8; 23];
946 let alg2 = label_str("algorithm 2");
947 let mut ops2 = Labels::new();
948 ops2.add(&label_str("89583249384"));
949 let biv2 = vec![10u8, 0u8, 5u8, 9u8, 50u8, 100u8, 30u8];
950
951 let kty2_value = CBORValue::new_int(&Int::new_i32(352));
952 let kid2_value = CBORValue::new_bytes(kid2.clone());
953 let alg2_value = CBORValue::new_text(String::from("algorithm 2"));
954 let ops2_value = CBORValue::new_array(&vec![CBORValue::new_text(String::from("89583249384"))].into());
955 let biv2_value = CBORValue::new_bytes(biv2.clone());
956
957 let mut ck = COSEKey::new(&kty1);
958 ck.set_key_id(kid1.clone());
959 ck.set_algorithm_id(&alg1);
960 ck.set_key_ops(&ops1);
961 ck.set_base_init_vector(biv1.clone());
962
963 assert_eq!(ck.header(&label_int(1)), Some(kty1_value));
964 assert_eq!(ck.header(&label_int(2)), Some(kid1_value));
965 assert_eq!(ck.header(&label_int(3)), Some(alg1_value));
966 assert_eq!(ck.header(&label_int(4)), Some(ops1_value));
967 assert_eq!(ck.header(&label_int(5)), Some(biv1_value));
968
969 ck.set_header(&label_int(1), &kty2_value).unwrap();
970 ck.set_header(&label_int(2), &kid2_value).unwrap();
971 ck.set_header(&label_int(3), &alg2_value).unwrap();
972 ck.set_header(&label_int(4), &ops2_value).unwrap();
973 ck.set_header(&label_int(5), &biv2_value).unwrap();
974
975 assert_eq!(ck.key_type(), kty2);
976 assert_eq!(ck.key_id(), Some(kid2));
977 assert_eq!(ck.algorithm_id(), Some(alg2));
978 assert_eq!(ck.key_ops(), Some(ops2));
979 assert_eq!(ck.base_init_vector(), Some(biv2));
980 }
981
982 #[test]
983 fn signed_message_user_facing_encoding() {
984 let mut header_map = HeaderMap::new();
986 header_map.set_content_type(&Label::new_int(&Int::new_i32(-1000)));
987 let headers = Headers::new(&ProtectedHeaderMap::new_empty(), &header_map);
988 let signed_message = SignedMessage::new_cose_sign1(&COSESign1::new(&headers, Some(vec![64u8; 39]), vec![1u8, 2u8, 100u8]));
989 let user_facing_encoding = signed_message.to_user_facing_encoding();
990 let from_ufe = SignedMessage::from_user_facing_encoding(&user_facing_encoding).unwrap();
991 assert_eq!(from_ufe.to_bytes(), signed_message.to_bytes());
992 let pad1 = SignedMessage::from_user_facing_encoding("cms_hEChAzkD51gnQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQwECZACyaZmw==").unwrap();
994 let pad2 = SignedMessage::from_user_facing_encoding("cms_hEChAzkD51gnQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQwECZA==CyaZmw").unwrap();
995 let pad3 = SignedMessage::from_user_facing_encoding("cms_hEChAzkD51gnQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQwECZA==CyaZmw==").unwrap();
996 assert_eq!(signed_message.to_bytes(), pad1.to_bytes());
997 assert_eq!(pad1.to_bytes(), pad2.to_bytes());
998 assert_eq!(pad2.to_bytes(), pad3.to_bytes());
999 }
1000}