1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
//! Libkeycard is an MPL2.0-licensed library for interacting with Mensago digital certificates called keycards. 
//! 
//! No guarantees of any kind are provided with the library even though it has been written with care.
//! 
//! The Mensago [Identity Services](https://gitlab.com/mensago/mensago-docs/-/blob/master/Identity%20Services.adoc) design document is required reading to use this library effectively.
//! 
//! # Usage
//! 
//! The main tasks for interacting with keycards can be broken down into a few tasks:
//! 
//! - Verifying a keycard
//! - Retrieving an encryption or signature verification key
//! - Adding a new entry
//! - Revoking a keycard
//! 
//! ## Verifying a Keycard
//! 
//! The most common case for interacting with a keycard is obtaining a person's most recent encryption or verification keys. For starters, you will need to obtain the complete keycard for the user's organization along with the user's complete keycard.
//! 
//! Once you have obtained a keycard's raw text data from an organization's server, verifying the organization's keycard is relatively simple:
//! 
//! 1. Instantiate a [`Keycard`](struct.Keycard.html) object using [`from()`](struct.Keycard.html#method.from)
//! 2. Call [`verify()`](struct.Keycard.html#method.verify).
//! 
//! A user's keycard is more involved to verify:
//! 
//! 1. Obtain, instantiate, and verify the organization's keycard
//! 2. Obtain, instantiate, and verify the users's keycard
//! 3. Find the branch point in the organization's keycard for the user's root keycard entry using [`find()`](struct.Keycard.html#method.find)
//! 4. Get the root entry from the user's keycard and use it to call [`verify_chain()`](struct.Entry.html#method.verify_chain) on the branch point entry
//! 
//! ## Retrieving a Key
//! 
//! Obtaining a key is as simple as getting the current entry of a keycard and getting the appropriate field using [`get_field()`](struct.Entry.html#method.get_field). Once obtained, it can be passed directly to `from_string()`/`from_strings()` for encryption or signing keys/pairs or `CryptoString::from()`, depending on the usage needs.
//! 
//! ## Adding a New Organization Entry
//! 
//! Creating a brand-new root organization entry is done during the setup process of the organization's server. New entries are added by creating a [`Keycard`](struct.Keycard.html) instance from the organization's keycard data and then calling [`chain()`](struct.Entry.html#method.chain), which generates a new entry, signs it and returns the new entry and the new key set. From there, the new entry is uploaded to the server via the `ORGCHAIN` command sent by the client.
//! 
//! ## Adding a New User Entry
//! 
//! Creating a new root user entry is the most complicated of all the keycard-related processes because the server and the user don't trust one another.
//! 
//! 1. Generate a new user key set, consisting of a signing key pair for contact requests, an encryption key pair for contact requests, a signing key pair for general purpose use, an encryption key pair for general purpose use.
//! 2. Create a new Entry instance using [`new()`](struct.Entry.html#method.new) or [`new_from_str()`](struct.Entry.html#method.new_from_str).
//! 3. Set field data as appropriate, including the entry lifespan (expiration). The "Time-To-Live" field is set to the recommended 14 days and a timestamp is also automatically generated by the constructor.
//! 4. Confirm that the entry meets basic data compliance using [`is_data_compliant()`](struct.Entry.html#method.is_data_compliant).
//! 5. Begin the signing process by submitting the entry data in its current form to the server to populate the `Organization-Signature` auth string.
//! 6. Set the `Previous-Hash` field using the value from the `Hash` field of the current entry on the organization's keycard.
//! 7. Generate a hash of all current entry data by calling [`hash()`](struct.Entry.html#method.hash) with the desired hash algorithm.
//! 8. Add a "User-Signature" signature using the contact request signing pair.
//! 9. Upload the entry to the server
//! 
//! Adding new non-root entries to a keycard is significantly less-involved.
//! 
//! 1. Create a new Keycard instance of the user's keycard data.
//! 2. Call the keycard's [`chain()`](struct.Entry.html#method.chain) method with the current entry's contact request signing pair to generate the chain-of-custody signature and return the new entry and key set.
//! 3. A client will then upload the new entry to the server for signing. A server utilizing this library will call [`cross_sign()`](struct.Keycard.html#method.cross_sign) to accomplish this.
//! 4. Generate a hash of all current entry data by calling [`hash()`](struct.Entry.html#method.hash) with the desired hash algorithm.
//! 5. Add a "User-Signature" signature using the contact request signing pair.
//! 6. Upload the entry to the server
//! 
//! ## Revoking a User Keycard
//! 
//! Revoking a user keycard is not terribly involved.
//! 
//! 1. Create a new Keycard instance of the user's keycard data.
//! 2. Call the keycard's [`revoke()`](struct.Entry.html#method.revoke) method to create a new root entry with an updated `Index` field and new key set.
//! 3. A client will then upload the new entry to the server for signing. A server utilizing this library will call [`cross_sign()`](struct.Keycard.html#method.cross_sign) to accomplish this.
//! 4. Set the `Previous-Hash` field using the value from the `Hash` field of the current entry on the organization's keycard.
//! 5. Generate a hash of all current entry data by calling [`hash()`](struct.Entry.html#method.hash) with the desired hash algorithm.
//! 6. Add a "User-Signature" signature using the contact request signing pair.
//! 7. Upload the entry to the server using the `REVOKE` command
//! 
//! ## Revoking an Organization Keycard
//! 
//! In terms of time-to-recovery, this is the worst-case scenario, but the process itself isn't difficult at all.
//! 
//! 1. Create a new Keycard instance of the user's keycard data.
//! 2. Call the keycard's [`revoke()`](struct.Entry.html#method.revoke) method to create a new root entry with an updated `Index` field and new key set.
//! 3. A client will then upload the new entry to the server for signing. A server utilizing this library will call [`cross_sign()`](struct.Keycard.html#method.cross_sign) to accomplish this.
//! 4. Set the `Previous-Hash` field using the value from the `Hash` field of the current entry on the organization's keycard.
//! 5. Generate a hash of all current entry data by calling [`hash()`](struct.Entry.html#method.hash) with the desired hash algorithm.
//! 6. Add a "User-Signature" signature using the contact request signing pair.
//! 7. Upload the entry to the server using the `ORGREVOKE` command
//! 
//! By sending the `ORGREVOKE` command, the server will replace the organization's keycard tree with a new one and send revocation requests to all users.

mod base;
mod entry;
mod entry_tests;
mod keycard;
mod types;
mod verifiers;

pub use base::*;
pub use entry::*;
pub use keycard::*;
pub use types::*;