Add some basic documentation

This commit is contained in:
Rodolphe Bréard 2024-04-05 00:17:01 +02:00
parent 0aac6402eb
commit de9d4777aa
3 changed files with 108 additions and 0 deletions

View file

@ -5,8 +5,17 @@ use std::time::{Duration, SystemTime};
pub(crate) const IKM_BASE_STRUCT_SIZE: usize = 25; pub(crate) const IKM_BASE_STRUCT_SIZE: usize = 25;
pub(crate) type CounterId = u32; pub(crate) type CounterId = u32;
/// Abstract type representing the identifier of an [InputKeyMaterial].
pub type IkmId = u32; 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)] #[derive(Debug)]
pub struct InputKeyMaterial { pub struct InputKeyMaterial {
pub id: IkmId, 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].
///
/// <div class="warning">
/// 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.
/// </div>
///
/// # 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)] #[derive(Debug, Default)]
pub struct InputKeyMaterialList { pub struct InputKeyMaterialList {
pub(crate) ikm_lst: Vec<InputKeyMaterial>, pub(crate) ikm_lst: Vec<InputKeyMaterial>,

View file

@ -1,3 +1,5 @@
#![feature(doc_auto_cfg)]
#[cfg(feature = "encryption")] #[cfg(feature = "encryption")]
mod canonicalization; mod canonicalization;
#[cfg(feature = "encryption")] #[cfg(feature = "encryption")]

View file

@ -23,9 +23,44 @@ pub(crate) type EncryptionFunction = dyn Fn(&[u8], &[u8], &[u8], &str) -> Result
pub(crate) type GenNonceFunction = dyn Fn() -> Result<Vec<u8>>; pub(crate) type GenNonceFunction = dyn Fn() -> Result<Vec<u8>>;
pub(crate) type SchemeSerializeType = u32; 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)] #[derive(Copy, Clone, Debug, PartialEq)]
pub enum Scheme { 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, XChaCha20Poly1305WithBlake3 = 1,
/// - Key derivation: HKDF-SHA256
/// - Encryption: AES-GCM
/// - Key size: 128 bits
/// - Nonce size: 96 bits
/// - Max data size: 64 GB
/// - Max invocations: 2<sup>32</sup>
/// - Resources: [NIST SP 800-38D](https://doi.org/10.6028/NIST.SP.800-38D)
Aes128GcmWithSha256 = 2, Aes128GcmWithSha256 = 2,
} }