1use chrono::prelude::*;
2use chrono::{Duration, NaiveDate};
3use eznacl::*;
4use std::collections::HashMap;
5use std::fmt;
6
7use crate::base::*;
8use crate::verifiers::*;
9
10static ORG_PERMITTED_FIELDS: [&str; 14] = [
11 "Type",
12 "Index",
13 "Name",
14 "Domain",
15 "Contact-Admin",
16 "Contact-Abuse",
17 "Contact-Support",
18 "Language",
19 "Primary-Verification-Key",
20 "Secondary-Verification-Key",
21 "Encryption-Key",
22 "Time-To-Live",
23 "Expires",
24 "Timestamp",
25];
26
27static ORG_REQUIRED_FIELDS: [&str; 10] = [
28 "Type",
29 "Index",
30 "Name",
31 "Domain",
32 "Contact-Admin",
33 "Primary-Verification-Key",
34 "Encryption-Key",
35 "Time-To-Live",
36 "Expires",
37 "Timestamp",
38];
39
40static USER_PERMITTED_FIELDS: [&str; 13] = [
41 "Type",
42 "Index",
43 "Name",
44 "User-ID",
45 "Workspace-ID",
46 "Domain",
47 "Contact-Request-Verification-Key",
48 "Contact-Request-Encryption-Key",
49 "Encryption-Key",
50 "Verification-Key",
51 "Time-To-Live",
52 "Expires",
53 "Timestamp",
54];
55
56static USER_REQUIRED_FIELDS: [&str; 11] = [
57 "Type",
58 "Index",
59 "Workspace-ID",
60 "Domain",
61 "Contact-Request-Verification-Key",
62 "Contact-Request-Encryption-Key",
63 "Encryption-Key",
64 "Verification-Key",
65 "Time-To-Live",
66 "Expires",
67 "Timestamp",
68];
69
70#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Hash)]
72#[cfg_attr(feature = "use_serde", derive(serde::Serialize, serde::Deserialize))]
73pub enum EntryType {
74 Organization,
75 User,
76 None,
77}
78
79impl fmt::Display for EntryType {
80 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
81 match self {
82 EntryType::None => write!(f, "None"),
83 EntryType::Organization => write!(f, "Organization"),
84 EntryType::User => write!(f, "User"),
85 }
86 }
87}
88
89#[derive(Clone, Debug)]
92#[cfg_attr(feature = "use_serde", derive(serde::Serialize, serde::Deserialize))]
93pub struct Entry {
94 _type: EntryType,
95 fields: HashMap<String, String>,
96 sigs: HashMap<String, CryptoString>,
97}
98
99impl Entry {
100 pub fn new_from_str(entrytype: &str) -> Result<Entry, LKCError> {
103 match entrytype {
104 "Organization" => Entry::new(EntryType::Organization),
105 "User" => Entry::new(EntryType::User),
106 "" => Entry::new(EntryType::None),
107 _ => Err(LKCError::ErrBadValue),
108 }
109 }
110
111 pub fn new(entrytype: EntryType) -> Result<Entry, LKCError> {
113 let mut out = Entry {
114 _type: entrytype,
115 fields: HashMap::<String, String>::new(),
116 sigs: HashMap::<String, CryptoString>::new(),
117 };
118
119 match entrytype {
120 EntryType::Organization => out.set_field("Type", "Organization")?,
121 EntryType::User => out.set_field("Type", "User")?,
122 EntryType::None => (),
123 }
124
125 out.set_field("Timestamp", &get_timestamp())?;
127 out.set_field("Time-To-Live", "14")?;
128 match entrytype {
129 EntryType::User => out.set_expiration(90)?,
130 EntryType::Organization => out.set_expiration(365)?,
131 _ => (),
132 }
133
134 Ok(out)
135 }
136
137 pub fn from(s: &str) -> Result<Entry, LKCError> {
142 if s.len() < 160 {
146 return Err(LKCError::ErrBadValue);
147 }
148
149 let mut out = Entry::new(EntryType::None)?;
150 for line in s.split("\r\n") {
151 if line.len() == 0 {
152 continue;
153 }
154
155 let trimmed = line.trim();
156 if trimmed.len() == 0 {
157 continue;
158 }
159
160 let parts = trimmed.splitn(2, ":").collect::<Vec<&str>>();
161 if parts.len() != 2 {
162 return Err(LKCError::ErrBadFieldValue(String::from(trimmed)));
163 }
164
165 if parts[1].len() > 6144 {
166 return Err(LKCError::ErrOutOfRange);
167 }
168
169 let field_value = match parts.get(1) {
170 Some(v) => v.clone(),
171 None => return Err(LKCError::ErrBadFieldValue(String::from(parts[0]))),
172 };
173
174 match parts[0] {
175 "Custody-Signature"
176 | "Organization-Signature"
177 | "Previous-Hash"
178 | "Hash"
179 | "User-Signature" => match CryptoString::from(field_value) {
180 Some(cs) => {
181 out.add_authstr(parts[0], &cs)?;
182 continue;
183 }
184 None => return Err(LKCError::ErrBadFieldValue(String::from(parts[0]))),
185 },
186 _ => (),
187 }
188
189 match out.set_field(parts[0], field_value) {
190 Ok(_) => { }
191 Err(e) => return Err(e),
192 }
193 }
194
195 Ok(out)
196 }
197
198 pub fn has_field(&self, field: &str) -> bool {
200 match self.fields.get(field) {
201 Some(_) => true,
202 None => false,
203 }
204 }
205
206 pub fn get_field(&self, field: &str) -> Result<String, LKCError> {
208 match self.fields.get(field) {
209 Some(v) => Ok(v.clone()),
210 None => Err(LKCError::ErrNotFound),
211 }
212 }
213
214 pub fn set_field(&mut self, field: &str, value: &str) -> Result<(), LKCError> {
216 verify_field(field, value)?;
217
218 if field == "Type" {
219 self._type = match value {
220 "Organization" => EntryType::Organization,
221 "User" => EntryType::User,
222 _ => EntryType::None,
223 };
224 }
225 let _ = self.fields.insert(String::from(field), String::from(value));
226 Ok(())
227 }
228
229 pub fn set_fields(&mut self, fields: &Vec<(String, String)>) -> Result<(), LKCError> {
231 for (k, v) in fields.iter() {
232 self.set_field(&k, &v)?;
233 }
234 Ok(())
235 }
236
237 pub fn delete_field(&mut self, field: &str) -> Result<(), LKCError> {
239 let _ = self.fields.remove(field);
240 Ok(())
241 }
242
243 pub fn get_owner(&self) -> Result<String, LKCError> {
247 match self._type {
248 EntryType::Organization => self.get_field("Domain"),
249 EntryType::User => {
250 let mut widstr = self.get_field("Workspace-ID")?;
251 let domain = self.get_field("Domain")?;
252 widstr.push('/');
253 widstr.push_str(&domain);
254
255 Ok(widstr)
256 }
257 _ => return Err(LKCError::ErrNoInit),
258 }
259 }
260
261 pub fn is_data_compliant(&self) -> Result<(), LKCError> {
265 match self._type {
268 EntryType::Organization => {
269 for f in ORG_REQUIRED_FIELDS {
270 match self.fields.get(f) {
271 Some(_) => { }
272 None => return Err(LKCError::ErrMissingField(String::from(f))),
273 }
274 }
275 }
276 EntryType::User => {
277 for f in USER_REQUIRED_FIELDS {
278 match self.fields.get(f) {
279 Some(_) => { }
280 None => return Err(LKCError::ErrMissingField(String::from(f))),
281 }
282 }
283 }
284 _ => return Err(LKCError::ErrNoInit),
285 }
286
287 Ok(())
288 }
289
290 pub fn is_compliant(&self) -> Result<(), LKCError> {
336 self.is_data_compliant()?;
337
338 match self._type {
339 EntryType::Organization => {
340 if self.get_field("Index")? == "1" {
341 if self.has_field("Revoke") {
344 return Err(LKCError::ErrInvalidKeycard);
345 }
346 } else {
347 if !self.has_field("Revoke") {
351 _ = self.get_authstr("Custody-Signature")?;
352 _ = self.get_authstr("Previous-Hash")?;
353 }
354 }
355 _ = self.get_authstr("Hash")?;
356 _ = self.get_authstr("Organization-Signature")?;
357 }
358 EntryType::User => {
359 if self.get_field("Index")? == "1" {
360 if self.has_field("Revoke") {
362 return Err(LKCError::ErrInvalidKeycard);
363 }
364 } else {
365 if !self.has_field("Revoke") {
368 _ = self.get_authstr("Custody-Signature")?;
369 }
370 }
371 _ = self.get_authstr("Organization-Signature")?;
372 _ = self.get_authstr("Previous-Hash")?;
373 _ = self.get_authstr("Hash")?;
374 _ = self.get_authstr("User-Signature")?;
375 }
376 EntryType::None => return Err(LKCError::ErrNoInit),
377 }
378
379 Ok(())
380 }
381
382 pub fn set_expiration(&mut self, numdays: u16) -> Result<(), LKCError> {
385 if numdays > 1095 || numdays < 1 {
386 return Err(LKCError::ErrBadValue);
387 }
388
389 let offdate = match get_offset_date(Duration::days(numdays as i64)) {
390 Some(v) => v,
391 None => {
392 return Err(LKCError::ErrProgramException(String::from(
393 "set_expiration: failure to create expiration date",
394 )))
395 }
396 };
397 self.set_field("Expires", &offdate)?;
398
399 Ok(())
400 }
401
402 pub fn is_expired(&self) -> Result<bool, LKCError> {
404 let expdate = match self.fields.get("Expires") {
409 Some(v) => {
410 match NaiveDate::parse_from_str(v, "%Y%m%d") {
411 Ok(d) => d,
412 Err(e) => {
413 return Err(LKCError::ErrProgramException(e.to_string()));
415 }
416 }
417 }
418 None => return Err(LKCError::ErrNotFound),
419 };
420
421 let now = Utc::now().date().naive_utc();
422
423 Ok(now > expdate)
424 }
425
426 pub fn get_text(&self) -> Result<String, LKCError> {
428 let mut lines = Vec::<String>::new();
429
430 match self._type {
433 EntryType::Organization => {
434 for i in ORG_PERMITTED_FIELDS.iter() {
435 match self.fields.get(*i) {
436 Some(v) => {
437 let parts = [*i, v];
438 lines.push(parts.join(":"));
439 }
440 None => { }
441 }
442 }
443 }
444 EntryType::User => {
445 for i in USER_PERMITTED_FIELDS.iter() {
446 match self.fields.get(*i) {
447 Some(v) => {
448 let parts = [*i, v];
449 lines.push(parts.join(":"));
450 }
451 None => { }
452 }
453 }
454 }
455 _ => return Err(LKCError::ErrNoInit),
456 };
457
458 lines.push(String::from(""));
460
461 Ok(lines.join("\r\n"))
462 }
463
464 pub fn get_full_text(&self, siglevel: &str) -> Result<String, LKCError> {
483 match self._type {
484 EntryType::Organization => self.org_get_full_text(siglevel),
485 EntryType::User => self.user_get_full_text(siglevel),
486 _ => return Err(LKCError::ErrNoInit),
487 }
488 }
489
490 pub fn has_authstr(&self, astype: &str) -> bool {
492 match self.sigs.get(astype) {
493 Some(_) => true,
494 None => false,
495 }
496 }
497
498 pub fn get_authstr(&self, astype: &str) -> Result<&CryptoString, LKCError> {
500 match self.sigs.get(astype) {
501 Some(v) => Ok(v),
502 None => Err(LKCError::ErrMissingField(String::from(astype))),
503 }
504 }
505
506 pub fn add_authstr(&mut self, astype: &str, astr: &CryptoString) -> Result<(), LKCError> {
510 verify_authstr(astype, astr)?;
511
512 let _ = self.sigs.insert(String::from(astype), astr.clone());
513 Ok(())
514 }
515
516 pub fn sign(&mut self, astype: &str, signing_pair: &SigningPair) -> Result<(), LKCError> {
521 let totaldata = self.get_full_text(astype)?;
522 let signature = signing_pair.sign(totaldata.as_bytes())?;
523 self.add_authstr(&astype, &signature)
524 }
525
526 pub fn verify_signature<K: VerifySignature>(
530 &self,
531 astype: &str,
532 verify_key: &K,
533 ) -> Result<(), LKCError> {
534 let sig = self.get_authstr(astype)?;
535 let totaldata = match self._type {
536 EntryType::Organization => self.org_get_full_text(astype)?,
537 EntryType::User => self.user_get_full_text(astype)?,
538 EntryType::None => return Err(LKCError::ErrNoInit),
539 };
540
541 if verify_key.verify(totaldata.as_bytes(), &sig)? {
542 Ok(())
543 } else {
544 Err(LKCError::ErrVerificationFailure)
545 }
546 }
547
548 pub fn hash(&mut self, algorithm: &str) -> Result<(), LKCError> {
554 let totaldata = self.get_full_text("Hash")?;
555 let hash = get_hash(algorithm, totaldata.as_bytes())?;
556 self.add_authstr("Hash", &hash)
557 }
558
559 pub fn verify_hash(&self) -> Result<(), LKCError> {
562 let currenthash = self.get_authstr("Hash")?;
563
564 let totaldata = self.get_full_text("Hash")?;
565 let hash = get_hash(currenthash.prefix(), totaldata.as_bytes())?;
566
567 if *currenthash == hash {
568 Ok(())
569 } else {
570 Err(LKCError::ErrHashMismatch)
571 }
572 }
573
574 pub fn chain(
579 &self,
580 spair: &SigningPair,
581 expires: u16,
582 ) -> Result<(Entry, HashMap<&'static str, CryptoString>), LKCError> {
583 match self._type {
584 EntryType::Organization => self.org_chain(spair, expires),
585 EntryType::User => self.user_chain(spair, expires),
586 EntryType::None => Err(LKCError::ErrNoInit),
587 }
588 }
589
590 pub fn verify_chain(&self, previous: &Entry) -> Result<(), LKCError> {
594 previous.is_compliant()?;
595 self.is_compliant()?;
596
597 match self._type {
598 EntryType::Organization => self.org_verify_chain(previous),
599 EntryType::User => self.user_verify_chain(previous),
600 EntryType::None => Err(LKCError::ErrNoInit),
601 }
602 }
603
604 pub fn revoke(
610 &self,
611 expires: u16,
612 ) -> Result<(Entry, HashMap<&'static str, CryptoString>), LKCError> {
613 self.is_compliant()?;
614
615 match self._type {
616 EntryType::Organization => self.org_revoke(expires),
617 EntryType::User => self.user_revoke(expires),
618 EntryType::None => Err(LKCError::ErrNoInit),
619 }
620 }
621
622 fn copy(&self) -> Self {
626 let entrytype = self
627 .get_field("Type")
628 .expect("Failed to get type in Entry::copy()");
629
630 let mut out = Entry::new_from_str(&entrytype).expect("Failed to create new ");
631
632 for (k, v) in self.fields.iter() {
633 match k.as_str() {
634 "Index"
635 | "PrimaryVerificationKey"
636 | "SecondaryVerificationKey"
637 | "EncryptionKey"
638 | "Expires"
639 | "Timestamp" => { }
640 _ => {
641 out.set_field(k, v)
642 .expect("Failed to copy field in OrgEntry::copy()");
643 }
644 }
645 }
646
647 let index = self
650 .get_field("Index")
651 .expect("Missing Index field in OrgEntry::copy()");
652 let new_index = increment_index_string(&index)
653 .expect("Failed to increment Index field in OrgEntry::copy()");
654 out.set_field("Index", &new_index)
655 .expect("Failed to set Index field to new value in OrgEntry::copy()");
656
657 out
658 }
659
660 fn org_get_full_text(&self, siglevel: &str) -> Result<String, LKCError> {
663 let mut strings = Vec::<String>::new();
664 strings.push(self.get_text()?);
665
666 let require_previous = self.get_field("Index")? != "1" && !self.has_field("Revoke");
667
668 match siglevel {
669 "User-Signature" => {
670 return Err(LKCError::ErrBadValue);
672 }
673 "Custody-Signature" => {
674 }
676 "Previous-Hash" => {
677 match &self.sigs.get("Custody-Signature") {
678 Some(v) => {
679 strings.push(format!("Custody-Signature:{}\r\n", v.to_string()));
680 }
681 None => {
682 if require_previous {
683 return Err(LKCError::ErrMissingField(String::from(
684 "Custody-Signature",
685 )));
686 }
687 }
688 };
689 }
690 "Hash" => {
691 match &self.sigs.get("Custody-Signature") {
692 Some(v) => {
693 strings.push(format!("Custody-Signature:{}\r\n", v.to_string()));
694 }
695 None => {
696 if require_previous {
697 return Err(LKCError::ErrMissingField(String::from(
698 "Custody-Signature",
699 )));
700 }
701 }
702 };
703 match &self.sigs.get("Previous-Hash") {
704 Some(v) => {
705 strings.push(format!("Previous-Hash:{}\r\n", v.to_string()));
706 }
707 None => {
708 if require_previous {
709 return Err(LKCError::ErrMissingField(String::from("Previous-Hash")));
710 }
711 }
712 };
713 }
714 "Organization-Signature" => {
715 match &self.sigs.get("Custody-Signature") {
716 Some(v) => {
717 strings.push(format!("Custody-Signature:{}\r\n", v.to_string()));
718 }
719 None => {
720 if require_previous {
721 return Err(LKCError::ErrMissingField(String::from(
722 "Custody-Signature",
723 )));
724 }
725 }
726 };
727 match &self.sigs.get("Previous-Hash") {
728 Some(v) => {
729 strings.push(format!("Previous-Hash:{}\r\n", v.to_string()));
730 }
731 None => {
732 if require_previous {
733 return Err(LKCError::ErrMissingField(String::from("Previous-Hash")));
734 }
735 }
736 };
737 match &self.sigs.get("Hash") {
738 Some(v) => {
739 strings.push(format!("Hash:{}\r\n", v.to_string()));
740 }
741 None => {
742 if require_previous {
743 return Err(LKCError::ErrMissingField(String::from("Hash")));
744 }
745 }
746 };
747 }
748 "" => {
749 match &self.sigs.get("Custody-Signature") {
750 Some(v) => {
751 strings.push(format!("Custody-Signature:{}\r\n", v.to_string()));
752 }
753 None => {
754 if require_previous {
755 return Err(LKCError::ErrMissingField(String::from(
756 "Custody-Signature",
757 )));
758 }
759 }
760 };
761 match &self.sigs.get("Previous-Hash") {
762 Some(v) => {
763 strings.push(format!("Previous-Hash:{}\r\n", v.to_string()));
764 }
765 None => {
766 if require_previous {
767 return Err(LKCError::ErrMissingField(String::from("Previous-Hash")));
768 }
769 }
770 };
771 match &self.sigs.get("Hash") {
772 Some(v) => {
773 strings.push(format!("Hash:{}\r\n", v.to_string()));
774 }
775 None => {
776 if require_previous {
777 return Err(LKCError::ErrMissingField(String::from("Hash")));
778 }
779 }
780 };
781 match &self.sigs.get("Organization-Signature") {
782 Some(v) => {
783 strings.push(format!("Organization-Signature:{}\r\n", v.to_string()));
784 }
785 None => {
786 return Err(LKCError::ErrMissingField(String::from(
787 "Organization-Signature",
788 )))
789 }
790 };
791 }
792 _ => return Err(LKCError::ErrBadValue),
793 };
794
795 Ok(strings.join(""))
796 }
797
798 fn user_get_full_text(&self, siglevel: &str) -> Result<String, LKCError> {
799 let mut strings = Vec::<String>::new();
800 strings.push(self.get_text()?);
801
802 let require_previous = self.get_field("Index")? != "1" && !self.has_field("Revoke");
803
804 match siglevel {
805 "Custody-Signature" => {
806 }
808 "Organization-Signature" => {
809 match &self.sigs.get("Custody-Signature") {
810 Some(v) => {
811 strings.push(format!("Custody-Signature:{}\r\n", v.to_string()));
812 }
813 None => {
814 if require_previous {
815 return Err(LKCError::ErrMissingField(String::from(
816 "Custody-Signature",
817 )));
818 }
819 }
820 };
821 }
822 "Previous-Hash" => {
823 match &self.sigs.get("Custody-Signature") {
824 Some(v) => {
825 strings.push(format!("Custody-Signature:{}\r\n", v.to_string()));
826 }
827 None => {
828 if require_previous {
829 return Err(LKCError::ErrMissingField(String::from(
830 "Custody-Signature",
831 )));
832 }
833 }
834 };
835 match &self.sigs.get("Organization-Signature") {
836 Some(v) => {
837 strings.push(format!("Organization-Signature:{}\r\n", v.to_string()));
838 }
839 None => {
840 return Err(LKCError::ErrMissingField(String::from(
841 "Organization-Signature",
842 )))
843 }
844 };
845 }
846 "Hash" => {
847 match &self.sigs.get("Custody-Signature") {
848 Some(v) => {
849 strings.push(format!("Custody-Signature:{}\r\n", v.to_string()));
850 }
851 None => {
852 if require_previous {
853 return Err(LKCError::ErrMissingField(String::from(
854 "Custody-Signature",
855 )));
856 }
857 }
858 };
859 match &self.sigs.get("Organization-Signature") {
860 Some(v) => {
861 strings.push(format!("Organization-Signature:{}\r\n", v.to_string()));
862 }
863 None => {
864 return Err(LKCError::ErrMissingField(String::from(
865 "Organization-Signature",
866 )))
867 }
868 };
869 match &self.sigs.get("Previous-Hash") {
870 Some(v) => {
871 strings.push(format!("Previous-Hash:{}\r\n", v.to_string()));
872 }
873 None => {
874 if require_previous {
875 return Err(LKCError::ErrMissingField(String::from("Previous-Hash")));
876 }
877 }
878 };
879 }
880 "User-Signature" => {
881 match &self.sigs.get("Custody-Signature") {
882 Some(v) => {
883 strings.push(format!("Custody-Signature:{}\r\n", v.to_string()));
884 }
885 None => {
886 if require_previous {
887 return Err(LKCError::ErrMissingField(String::from(
888 "Custody-Signature",
889 )));
890 }
891 }
892 };
893 match &self.sigs.get("Organization-Signature") {
894 Some(v) => {
895 strings.push(format!("Organization-Signature:{}\r\n", v.to_string()));
896 }
897 None => {
898 return Err(LKCError::ErrMissingField(String::from(
899 "Organization-Signature",
900 )))
901 }
902 };
903 match &self.sigs.get("Previous-Hash") {
904 Some(v) => {
905 strings.push(format!("Previous-Hash:{}\r\n", v.to_string()));
906 }
907 None => {
908 if require_previous {
909 return Err(LKCError::ErrMissingField(String::from("Previous-Hash")));
910 }
911 }
912 };
913 match &self.sigs.get("Hash") {
914 Some(v) => {
915 strings.push(format!("Hash:{}\r\n", v.to_string()));
916 }
917 None => return Err(LKCError::ErrMissingField(String::from("Hash"))),
918 };
919 }
920 "" => {
921 match &self.sigs.get("Custody-Signature") {
922 Some(v) => {
923 strings.push(format!("Custody-Signature:{}\r\n", v.to_string()));
924 }
925 None => {
926 if require_previous {
927 return Err(LKCError::ErrMissingField(String::from(
928 "Custody-Signature",
929 )));
930 }
931 }
932 };
933 match &self.sigs.get("Organization-Signature") {
934 Some(v) => {
935 strings.push(format!("Organization-Signature:{}\r\n", v.to_string()));
936 }
937 None => {
938 return Err(LKCError::ErrMissingField(String::from(
939 "Organization-Signature",
940 )))
941 }
942 };
943 match &self.sigs.get("Previous-Hash") {
944 Some(v) => {
945 strings.push(format!("Previous-Hash:{}\r\n", v.to_string()));
946 }
947 None => {
948 if require_previous {
949 return Err(LKCError::ErrMissingField(String::from("Previous-Hash")));
950 }
951 }
952 };
953 match &self.sigs.get("Hash") {
954 Some(v) => {
955 strings.push(format!("Hash:{}\r\n", v.to_string()));
956 }
957 None => return Err(LKCError::ErrMissingField(String::from("Hash"))),
958 };
959 match &self.sigs.get("User-Signature") {
960 Some(v) => {
961 strings.push(format!("User-Signature:{}\r\n", v.to_string()));
962 }
963 None => return Err(LKCError::ErrMissingField(String::from("User-Signature"))),
964 };
965 }
966 _ => return Err(LKCError::ErrBadValue),
967 };
968
969 Ok(strings.join(""))
970 }
971
972 fn org_chain(
973 &self,
974 spair: &SigningPair,
975 expires: u16,
976 ) -> Result<(Entry, HashMap<&'static str, CryptoString>), LKCError> {
977 let mut map = HashMap::<&str, CryptoString>::new();
978 let mut entry = self.copy();
979
980 let newspair = SigningPair::generate("ED25519")?;
982 map.insert(
983 "primary.public",
984 CryptoString::from(&newspair.get_public_str())
985 .expect("Error getting inserting primary verification key in OrgEntry::chain()"),
986 );
987 map.insert(
988 "primary.private",
989 CryptoString::from(&newspair.get_private_str())
990 .expect("Error getting inserting primary signing key in OrgEntry::chain()"),
991 );
992 match entry.set_field("Primary-Verification-Key", &newspair.get_public_str()) {
993 Ok(_) => (),
994 Err(e) => {
995 return Err(LKCError::ErrProgramException(format!(
996 "Error setting primary verification key in OrgEntry::chain(): {}",
997 e.to_string()
998 )))
999 }
1000 }
1001
1002 let epair = EncryptionPair::generate("CURVE25519")?;
1004 map.insert(
1005 "encryption.public",
1006 CryptoString::from(&epair.get_public_str())
1007 .expect("Error getting inserting encryption key in OrgEntry::chain()"),
1008 );
1009 map.insert(
1010 "encryption.private",
1011 CryptoString::from(&epair.get_private_str())
1012 .expect("Error getting inserting decryption key in OrgEntry::chain()"),
1013 );
1014 match entry.set_field("Encryption-Key", &epair.get_public_str()) {
1015 Ok(_) => (),
1016 Err(e) => {
1017 return Err(LKCError::ErrProgramException(format!(
1018 "Error setting encryption key in OrgEntry::chain(): {}",
1019 e.to_string()
1020 )))
1021 }
1022 }
1023
1024 match entry.set_field(
1026 "Secondary-Verification-Key",
1027 &self.get_field("Primary-Verification-Key").expect(""),
1028 ) {
1029 Ok(_) => (),
1030 Err(e) => {
1031 return Err(LKCError::ErrProgramException(format!(
1032 "Error moving primary key to secondary in OrgEntry::chain(): {}",
1033 e.to_string()
1034 )))
1035 }
1036 }
1037
1038 let hash = self.get_authstr("Hash")?;
1039 entry.add_authstr("Previous-Hash", hash)?;
1040 entry.set_expiration(expires)?;
1041 entry.sign("Custody-Signature", &spair)?;
1042 entry.hash(hash.prefix())?;
1043 entry.sign("Organization-Signature", &newspair)?;
1044
1045 Ok((entry, map))
1046 }
1047
1048 fn user_chain(
1049 &self,
1050 spair: &SigningPair,
1051 expires: u16,
1052 ) -> Result<(Entry, HashMap<&'static str, CryptoString>), LKCError> {
1053 let mut map = HashMap::<&str, CryptoString>::new();
1054 let mut entry = self.copy();
1055
1056 let newcrspair = SigningPair::generate("ED25519")?;
1058 map.insert(
1059 "crsigning.public",
1060 CryptoString::from(&newcrspair.get_public_str())
1061 .expect("Error getting inserting CR verification key in UserEntry::chain()"),
1062 );
1063 map.insert(
1064 "crsigning.private",
1065 CryptoString::from(&newcrspair.get_private_str())
1066 .expect("Error getting inserting CR signing key in UserEntry::chain()"),
1067 );
1068 match entry.set_field(
1069 "Contact-Request-Verification-Key",
1070 &newcrspair.get_public_str(),
1071 ) {
1072 Ok(_) => (),
1073 Err(e) => {
1074 return Err(LKCError::ErrProgramException(format!(
1075 "Error setting CR verification key in UserEntry::chain(): {}",
1076 e.to_string()
1077 )))
1078 }
1079 }
1080
1081 let newcrepair = EncryptionPair::generate("CURVE25519")?;
1083 map.insert(
1084 "crencryption.public",
1085 CryptoString::from(&newcrepair.get_public_str())
1086 .expect("Error getting inserting CR encryption key in UserEntry::chain()"),
1087 );
1088 map.insert(
1089 "crencryption.private",
1090 CryptoString::from(&newcrepair.get_private_str())
1091 .expect("Error getting inserting CR decryption key in UserEntry::chain()"),
1092 );
1093 match entry.set_field(
1094 "Contact-Request-Encryption-Key",
1095 &newcrepair.get_public_str(),
1096 ) {
1097 Ok(_) => (),
1098 Err(e) => {
1099 return Err(LKCError::ErrProgramException(format!(
1100 "Error setting CR encryption key in UserEntry::chain(): {}",
1101 e.to_string()
1102 )))
1103 }
1104 }
1105
1106 let newspair = SigningPair::generate("ED25519")?;
1108 map.insert(
1109 "signing.public",
1110 CryptoString::from(&newspair.get_public_str())
1111 .expect("Error getting inserting verification key in UserEntry::chain()"),
1112 );
1113 map.insert(
1114 "signing.private",
1115 CryptoString::from(&newspair.get_private_str())
1116 .expect("Error getting inserting signing key in UserEntry::chain()"),
1117 );
1118 match entry.set_field("Verification-Key", &newspair.get_public_str()) {
1119 Ok(_) => (),
1120 Err(e) => {
1121 return Err(LKCError::ErrProgramException(format!(
1122 "Error setting verification key in UserEntry::chain(): {}",
1123 e.to_string()
1124 )))
1125 }
1126 }
1127
1128 let newepair = EncryptionPair::generate("CURVE25519")?;
1130 map.insert(
1131 "encryption.public",
1132 CryptoString::from(&newepair.get_public_str())
1133 .expect("Error getting inserting encryption key in UserEntry::chain()"),
1134 );
1135 map.insert(
1136 "encryption.private",
1137 CryptoString::from(&newepair.get_private_str())
1138 .expect("Error getting inserting decryption key in UserEntry::chain()"),
1139 );
1140 match entry.set_field("Encryption-Key", &newepair.get_public_str()) {
1141 Ok(_) => (),
1142 Err(e) => {
1143 return Err(LKCError::ErrProgramException(format!(
1144 "Error setting encryption key in UserEntry::chain(): {}",
1145 e.to_string()
1146 )))
1147 }
1148 }
1149
1150 let hash = self.get_authstr("Hash")?;
1151 entry.add_authstr("Previous-Hash", hash)?;
1152 entry.set_expiration(expires)?;
1153 entry.sign("Custody-Signature", &spair)?;
1154
1155 Ok((entry, map))
1156 }
1157
1158 fn org_verify_chain(&self, previous: &Entry) -> Result<(), LKCError> {
1159 if previous._type != EntryType::Organization {
1160 return Err(LKCError::ErrTypeMismatch);
1161 }
1162
1163 let previndex = match previous.get_field("Index") {
1165 Ok(v) => v,
1166 Err(_) => return Err(LKCError::ErrInvalidKeycard),
1167 };
1168 let currentindex = match self.get_field("Index") {
1169 Ok(v) => v,
1170 Err(_) => return Err(LKCError::ErrInvalidKeycard),
1171 };
1172 match increment_index_string(&previndex) {
1173 Ok(v) => {
1174 if v != currentindex {
1175 return Err(LKCError::ErrBadValue);
1176 }
1177 }
1178 Err(_) => return Err(LKCError::ErrBadFieldValue(String::from("Index"))),
1179 }
1180
1181 let verkeystr = previous.get_field("Primary-Verification-Key")?;
1182 let verkey = match VerificationKey::from_string(&verkeystr) {
1183 Some(v) => v,
1184 None => return Err(LKCError::ErrInvalidKey),
1185 };
1186
1187 self.verify_signature("Custody-Signature", &verkey)
1188 }
1189
1190 fn user_verify_chain(&self, previous: &Entry) -> Result<(), LKCError> {
1191 match previous._type {
1194 EntryType::User => {
1195 if self.get_field("Index")? == "1" {
1196 return Err(LKCError::ErrTypeMismatch);
1197 }
1198 }
1199 EntryType::Organization => {
1200 if self.get_field("Index")? != "1" && !self.has_field("Revoke") {
1201 return Err(LKCError::ErrTypeMismatch);
1202 }
1203 }
1204 _ => return Err(LKCError::ErrTypeMismatch),
1205 }
1206
1207 if previous.get_authstr("Hash")? != self.get_authstr("Previous-Hash")? {
1210 return Err(LKCError::ErrHashMismatch);
1211 }
1212
1213 if previous.get_field("Type")? == self.get_field("Type")? {
1214 let previndex = match previous.get_field("Index") {
1215 Ok(v) => v,
1216 Err(_) => return Err(LKCError::ErrInvalidKeycard),
1217 };
1218 let currentindex = match self.get_field("Index") {
1219 Ok(v) => v,
1220 Err(_) => return Err(LKCError::ErrInvalidKeycard),
1221 };
1222 match increment_index_string(&previndex) {
1223 Ok(v) => {
1224 if v != currentindex {
1225 return Err(LKCError::ErrBadValue);
1226 }
1227 }
1228 Err(_) => return Err(LKCError::ErrBadFieldValue(String::from("Index"))),
1229 }
1230 }
1231
1232 match previous._type {
1233 EntryType::User => {
1234 let verkeystr = previous.get_field("Contact-Request-Verification-Key")?;
1235 let verkey = match VerificationKey::from_string(&verkeystr) {
1236 Some(v) => v,
1237 None => return Err(LKCError::ErrInvalidKey),
1238 };
1239 self.verify_signature("Custody-Signature", &verkey)
1240 }
1241 EntryType::Organization => {
1242 let verkeystr = previous.get_field("Primary-Verification-Key")?;
1243 let verkey = match VerificationKey::from_string(&verkeystr) {
1244 Some(v) => v,
1245 None => return Err(LKCError::ErrInvalidKey),
1246 };
1247 self.verify_signature("Organization-Signature", &verkey)
1248 }
1249 _ => unreachable!(),
1250 }
1251 }
1252
1253 fn org_revoke(
1254 &self,
1255 expires: u16,
1256 ) -> Result<(Entry, HashMap<&'static str, CryptoString>), LKCError> {
1257 let mut map = HashMap::<&str, CryptoString>::new();
1258 let mut entry = self.copy();
1259
1260 let newspair = SigningPair::generate("ED25519")?;
1262 map.insert(
1263 "primary.public",
1264 CryptoString::from(&newspair.get_public_str())
1265 .expect("Error getting inserting primary verification key in org_revoke()"),
1266 );
1267 map.insert(
1268 "primary.private",
1269 CryptoString::from(&newspair.get_private_str())
1270 .expect("Error getting inserting primary signing key in org_revoke()"),
1271 );
1272 match entry.set_field("Primary-Verification-Key", &newspair.get_public_str()) {
1273 Ok(_) => (),
1274 Err(e) => {
1275 return Err(LKCError::ErrProgramException(format!(
1276 "Error setting primary verification key in org_revoke(): {}",
1277 e.to_string()
1278 )))
1279 }
1280 }
1281
1282 let epair = EncryptionPair::generate("CURVE25519")?;
1284 map.insert(
1285 "encryption.public",
1286 CryptoString::from(&epair.get_public_str())
1287 .expect("Error getting inserting encryption key in org_revoke()"),
1288 );
1289 map.insert(
1290 "encryption.private",
1291 CryptoString::from(&epair.get_private_str())
1292 .expect("Error getting inserting decryption key in org_revoke()"),
1293 );
1294 match entry.set_field("Encryption-Key", &epair.get_public_str()) {
1295 Ok(_) => (),
1296 Err(e) => {
1297 return Err(LKCError::ErrProgramException(format!(
1298 "Error setting encryption key in org_revoke(): {}",
1299 e.to_string()
1300 )))
1301 }
1302 }
1303
1304 let hash = self.get_authstr("Hash")?;
1307 entry.set_field("Revoke", hash.as_str())?;
1308 entry.set_expiration(expires)?;
1309 entry.hash(hash.prefix())?;
1310 entry.sign("Organization-Signature", &newspair)?;
1311
1312 Ok((entry, map))
1313 }
1314
1315 fn user_revoke(
1316 &self,
1317 expires: u16,
1318 ) -> Result<(Entry, HashMap<&'static str, CryptoString>), LKCError> {
1319 let mut map = HashMap::<&str, CryptoString>::new();
1320 let mut entry = self.copy();
1321
1322 let newcrspair = SigningPair::generate("ED25519")?;
1324 map.insert(
1325 "crsigning.public",
1326 CryptoString::from(&newcrspair.get_public_str())
1327 .expect("Error getting inserting CR verification key in user_revoke()"),
1328 );
1329 map.insert(
1330 "crsigning.private",
1331 CryptoString::from(&newcrspair.get_private_str())
1332 .expect("Error getting inserting CR signing key in user_revoke()"),
1333 );
1334 match entry.set_field(
1335 "Contact-Request-Verification-Key",
1336 &newcrspair.get_public_str(),
1337 ) {
1338 Ok(_) => (),
1339 Err(e) => {
1340 return Err(LKCError::ErrProgramException(format!(
1341 "Error setting CR verification key in user_revoke(): {}",
1342 e.to_string()
1343 )))
1344 }
1345 }
1346
1347 let newcrepair = EncryptionPair::generate("CURVE25519")?;
1349 map.insert(
1350 "crencryption.public",
1351 CryptoString::from(&newcrepair.get_public_str())
1352 .expect("Error getting inserting CR encryption key in user_revoke()"),
1353 );
1354 map.insert(
1355 "crencryption.private",
1356 CryptoString::from(&newcrepair.get_private_str())
1357 .expect("Error getting inserting CR decryption key in user_revoke()"),
1358 );
1359 match entry.set_field(
1360 "Contact-Request-Encryption-Key",
1361 &newcrepair.get_public_str(),
1362 ) {
1363 Ok(_) => (),
1364 Err(e) => {
1365 return Err(LKCError::ErrProgramException(format!(
1366 "Error setting CR encryption key in user_revoke(): {}",
1367 e.to_string()
1368 )))
1369 }
1370 }
1371
1372 let newspair = SigningPair::generate("ED25519")?;
1374 map.insert(
1375 "signing.public",
1376 CryptoString::from(&newspair.get_public_str())
1377 .expect("Error getting inserting verification key in user_revoke()"),
1378 );
1379 map.insert(
1380 "signing.private",
1381 CryptoString::from(&newspair.get_private_str())
1382 .expect("Error getting inserting signing key in user_revoke()"),
1383 );
1384 match entry.set_field("Verification-Key", &newspair.get_public_str()) {
1385 Ok(_) => (),
1386 Err(e) => {
1387 return Err(LKCError::ErrProgramException(format!(
1388 "Error setting verification key in user_revoke(): {}",
1389 e.to_string()
1390 )))
1391 }
1392 }
1393
1394 let newepair = EncryptionPair::generate("CURVE25519")?;
1396 map.insert(
1397 "encryption.public",
1398 CryptoString::from(&newepair.get_public_str())
1399 .expect("Error getting inserting encryption key in user_revoke()"),
1400 );
1401 map.insert(
1402 "encryption.private",
1403 CryptoString::from(&newepair.get_private_str())
1404 .expect("Error getting inserting decryption key in user_revoke()"),
1405 );
1406 match entry.set_field("Encryption-Key", &newepair.get_public_str()) {
1407 Ok(_) => (),
1408 Err(e) => {
1409 return Err(LKCError::ErrProgramException(format!(
1410 "Error setting encryption key in user_revoke(): {}",
1411 e.to_string()
1412 )))
1413 }
1414 }
1415
1416 entry.set_field("Revoke", self.get_authstr("Hash")?.as_str())?;
1417 entry.set_expiration(expires)?;
1418
1419 Ok((entry, map))
1420 }
1421}
1422
1423fn increment_index_string(s: &str) -> Result<String, LKCError> {
1425 let mut val: u32 = match s.parse::<u32>() {
1426 Ok(v) => v,
1427 Err(_) => return Err(LKCError::ErrBadValue),
1428 };
1429
1430 val += 1;
1431 Ok(val.to_string())
1432}
1433
1434fn get_offset_date(d: Duration) -> Option<String> {
1435 let offset_date = Utc::now()
1436 .date()
1437 .naive_utc()
1438 .checked_add_signed(d)
1439 .expect("Unable to create date 365 days from now");
1440
1441 Some(offset_date.format("%Y%m%d").to_string())
1442}