diff --git a/src/ikm.rs b/src/ikm.rs
index 07861ec..9fbeb1d 100644
--- a/src/ikm.rs
+++ b/src/ikm.rs
@@ -5,8 +5,17 @@ use std::time::{Duration, SystemTime};
pub(crate) const IKM_BASE_STRUCT_SIZE: usize = 25;
pub(crate) type CounterId = u32;
+/// Abstract type representing the identifier of an [InputKeyMaterial].
pub type IkmId = u32;
+/// An input key material (IKM) is a secret random seed that is used to derive cryptographic keys.
+///
+/// In order to manage your IKMs, each one of them has an unique identifier. An IKM is also tight
+/// to a specific context in which it may be used. Keep in mind that an IKM is linked to a specific
+/// algorithm, as an expiration date and can be revoked.
+///
+/// This struct is exposed so you can display its informations when managing your IKMs using an
+/// [InputKeyMaterialList]. It it not meant to be used otherwise.
#[derive(Debug)]
pub struct InputKeyMaterial {
pub id: IkmId,
@@ -71,6 +80,68 @@ impl InputKeyMaterial {
}
}
+/// A list of [InputKeyMaterial] (IKM). This is where you should manage your secrets.
+///
+/// The way coffio works is quite simple: you generate a secret random seed (an input key material,
+/// IKM) that is used to derive cryptographic keys, which are used to encrypt your data. However,
+/// if your IKM or any derived key has leaked, or if you wishes to change the encryption algorithm,
+/// you need to generate an other IKM. This is why coffio uses a single opaque token capable of
+/// containing several IKMs, the [InputKeyMaterialList]. This way, the transition between two IKMs
+/// is smooth: you can use the new IKM to encrypt all new secrets and keep the revoked one to
+/// decrypt secrets it has already encrypted and you haven't re-encrypted using the new IKM yet.
+///
+/// This list is ordered. To encrypt new data, coffio will always use the last IKM that is not
+/// revoked and is within its validity period.
+///
+/// Encrypted data contains the [IkmId] of the IKM used to derive the key. To decrypt data, coffio
+/// will therefore search for this specific IKM in the [InputKeyMaterialList].
+///
+///
+/// Never remove an IKM from the list unless you are absolutely sure that all data encrypted using
+/// this IKM have been either deleted or re-encrypted using another IKM.
+///
+///
+/// # Examples
+///
+/// ```
+/// use coffio::{InputKeyMaterialList, Scheme};
+/// use std::time::Duration;
+///
+/// // Create an empty IKM list.
+/// let mut ikml = InputKeyMaterialList::new();
+/// assert_eq!(ikml.len(), 0);
+///
+/// // Add an IKM to the list with the default settings.
+/// let _ = ikml.add_ikm();
+/// assert_eq!(ikml.len(), 1);
+///
+/// // Add an IKM to the list with custom settings.
+/// let _ = ikml.add_custom_ikm(
+/// Scheme::Aes128GcmWithSha256,
+/// Duration::from_secs(315_569_252),
+/// );
+/// assert_eq!(ikml.len(), 2);
+///
+/// // Retreive the id of the first IKM.
+/// let ikm_id = ikml[0].id.clone();
+///
+/// // Revoke the first IKM.
+/// ikml.revoke_ikm(ikm_id);
+/// assert_eq!(ikml.len(), 2);
+///
+/// // Delete the first IKM.
+/// ikml.delete_ikm(ikm_id);
+/// assert_eq!(ikml.len(), 1);
+///
+/// // Export the IKM list
+/// let exported_ikml = ikml.export()?;
+/// println!("My secret IKM list: {exported_ikml}");
+///
+/// // Import an IKM list
+/// let ikml2 = InputKeyMaterialList::import(&exported_ikml)?;
+/// assert_eq!(ikml2.len(), 1);
+/// # Ok::<(), coffio::Error>(())
+/// ```
#[derive(Debug, Default)]
pub struct InputKeyMaterialList {
pub(crate) ikm_lst: Vec,
diff --git a/src/lib.rs b/src/lib.rs
index 7183f7b..2d4343c 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,3 +1,5 @@
+#![feature(doc_auto_cfg)]
+
#[cfg(feature = "encryption")]
mod canonicalization;
#[cfg(feature = "encryption")]
diff --git a/src/scheme.rs b/src/scheme.rs
index 7df5976..bb8bb85 100644
--- a/src/scheme.rs
+++ b/src/scheme.rs
@@ -23,9 +23,44 @@ pub(crate) type EncryptionFunction = dyn Fn(&[u8], &[u8], &[u8], &str) -> Result
pub(crate) type GenNonceFunction = dyn Fn() -> Result>;
pub(crate) type SchemeSerializeType = u32;
+/// The cryptographic primitives used to encrypt the data.
+///
+/// Coffio does not impose an unique way to encrypt data. You can therefore choose between one of
+/// the supported scheme. Each scheme has advantages and drawbacks.
+///
+/// Before choosing a scheme, you should run the benchmark on the hardware where the encryption and
+/// decryption process will take place. Some scheme may have hardware optimizations that you want
+/// to take advantage of. Regarding the key length, the following website may help you choose one
+/// that suits your requirements: [https://www.keylength.com/](https://www.keylength.com/)
+///
+/// In the following scheme description, the following terms are used:
+/// - `Max data size` describes the maximal size of data that can safely be encrypted using a
+/// single key and nonce, which means you should never pass a `data` parameter to
+/// [encrypt][crate::CipherBox::encrypt] that has a higher size. Coffio will not enforce this
+/// limit, it is your responsibility to do so.
+/// - `Max invocations` describes the maximal number of times you can safely call
+/// [encrypt][crate::CipherBox::encrypt] with a single key, which means you should either rotate
+/// your IKM or use an appropriate key periodicity before reaching this number. Coffio will neither
+/// enforce this limit nor count the number of invocations, it is your responsibility to do so.
#[derive(Copy, Clone, Debug, PartialEq)]
pub enum Scheme {
+ /// `default`
+ /// - Key derivation: BLAKE3 derive_key mode
+ /// - Encryption: XChaCha20-Poly1305
+ /// - Key size: 256 bits
+ /// - Nonce size: 192 bits
+ /// - Max data size: 256 GB
+ /// - Max invocations: no limitation
+ /// - Resources: [RFC 7539](https://datatracker.ietf.org/doc/html/rfc7539),
+ /// [draft-irtf-cfrg-xchacha](https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-xchacha)
XChaCha20Poly1305WithBlake3 = 1,
+ /// - Key derivation: HKDF-SHA256
+ /// - Encryption: AES-GCM
+ /// - Key size: 128 bits
+ /// - Nonce size: 96 bits
+ /// - Max data size: 64 GB
+ /// - Max invocations: 232
+ /// - Resources: [NIST SP 800-38D](https://doi.org/10.6028/NIST.SP.800-38D)
Aes128GcmWithSha256 = 2,
}