From 392d0ca31527c7e5c65b7834720e9420c9f5c7aa Mon Sep 17 00:00:00 2001 From: K Shiva Kiran Date: Tue, 9 Apr 2024 22:18:33 +0530 Subject: [PATCH] Docs: Add documentation comments --- Cargo.toml | 10 ++++++++-- src/algo.rs | 17 +++++++++++++---- src/encoding.rs | 11 +++++++++++ src/errors.rs | 4 ++++ src/fbkey.rs | 9 +++++++++ src/fbobj.rs | 1 + src/fbobj/fb128.rs | 1 + src/lib.rs | 42 +++++++++++++++++++++++++++++++++++++++++- 8 files changed, 88 insertions(+), 7 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 459bddf..9d0c0fc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,13 +1,19 @@ [package] name = "false-bottom" version = "0.1.0" +description = "A deniable encryption scheme" +repository = "https://codeberg.org/skran/false-bottom" +author = ["K Shiva Kiran "] +license = "GPL-3.0-or-later" edition = "2021" -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] rand = "0.8.5" crypto-bigint = {version = "0.5.5", features = ["generic-array"]} base64 = "0.21.7" bincode = "1.3.3" -typenum = "1.17.0" \ No newline at end of file +typenum = "1.17.0" + +[lib] +doctest = false \ No newline at end of file diff --git a/src/algo.rs b/src/algo.rs index 3b93f5b..f462bea 100644 --- a/src/algo.rs +++ b/src/algo.rs @@ -9,21 +9,27 @@ where { const MODULUS: NonZero; - fn init(n: usize, k: usize) -> Result, FBError> { - if n < k || k < 2 { + /// Creates a new [`FBObj`]. + /// The keybase and ciphertext are initialized from random values. + /// Bounds: `2 <= keybase_len <= cipher_len` + /// # Errors + /// [InvalidParams](FBError::InvalidParams) + fn init(cipher_len: usize, keybase_len: usize) -> Result, FBError> { + if cipher_len < keybase_len || keybase_len < 2 { return Err(FBError::InvalidParams); } let mut rng = rand::thread_rng(); - let r = (0..k) + let r = (0..keybase_len) .map(|_| T::random_mod(&mut rng, &Self::MODULUS)) .collect(); - let c = (0..n) + let c = (0..cipher_len) .map(|_| T::random_mod(&mut rng, &Self::MODULUS)) .collect(); Ok(FBObj { c, r }) } + /// Adds the provided message to the ciphertext. fn add(&mut self, msg: &[u8]) -> FBKey { let indices = T::pack(msg) .into_iter() @@ -33,6 +39,9 @@ where FBKey { indices } } + /// Decrypts the message that corresponds to the provided key. + /// # Errors + /// [InvalidKey](FBError::InvalidKey) fn decrypt(&self, key: &FBKey) -> Result, FBError> { let decr = key.indices .iter() diff --git a/src/encoding.rs b/src/encoding.rs index 3ffe5ec..d54cf82 100644 --- a/src/encoding.rs +++ b/src/encoding.rs @@ -7,6 +7,7 @@ where Self: FBObjTrait, T: ArrayEncoding + Bounded, { + /// Returns the byte representation of the ciphertext and keybase. fn to_bytes(&self) -> (Vec, Vec) { let c = self.cipher().iter() .flat_map(|bigint| bigint.to_le_byte_array()) @@ -18,12 +19,17 @@ where (c, r) } + /// Returns the base64 encoded representation of the ciphertext and keybase. fn export(&self) -> (String, String) { let (c, r) = self.to_bytes(); (BASE64_STANDARD.encode(c), BASE64_STANDARD.encode(r)) } + /// Constructs the [`FBObj`] from the provided byte representations of + /// ciphertext and keybase. + /// # Errors + /// - [InvalidParams](FBError::InvalidParams) - Are the parameters in the wrong order? fn from_bytes(cipher: &[u8], keybase: &[u8]) -> Result, FBError> { let chunk_to_uint = |chunk| { T::from_le_byte_array( @@ -42,6 +48,11 @@ where Ok(FBObj {c, r}) } + /// Constructs the [`FBObj`] from the provided base64 encoded forms of + /// ciphertext and keybase. + /// # Errors + /// - [DecodeError](FBError::DecodeError) + /// - [InvalidParams](FBError::InvalidParams) - Are the parameters in the wrong order? fn import(cipher: &str, keybase: &str) -> Result, FBError> { let c_bytes = BASE64_STANDARD.decode(cipher) .map_err(|_| FBError::DecodeError)?; diff --git a/src/errors.rs b/src/errors.rs index ac4d5bc..4d33a84 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -2,8 +2,12 @@ use std::fmt; #[derive(Debug)] pub enum FBError { + /// Unable to decode the given data. DecodeError, + /// The provided key is invalid w.r.t this False Bottom Object. InvalidKey, + /// Keybase length (k) or Cipher length (n) out of bounds. + /// Valid bounds: (2 <= k <= n). InvalidParams, } diff --git a/src/fbkey.rs b/src/fbkey.rs index 18ae16c..10fc980 100644 --- a/src/fbkey.rs +++ b/src/fbkey.rs @@ -2,22 +2,28 @@ use crate::FBError; use base64::prelude::{BASE64_STANDARD, Engine}; use bincode::{Options, DefaultOptions}; +/// A key object that is specific to a message. pub struct FBKey { pub(crate) indices: Vec>, } impl FBKey { + /// Returns the byte representation of the key. pub fn to_bytes(&self) -> Vec { let binc = DefaultOptions::new(); binc.serialize(&self.indices) .expect("Should be fine") } + /// Returns the base64 encoded representation of the key. pub fn export(&self) -> String { BASE64_STANDARD.encode(&self.to_bytes()) } + /// Constructs the key from the provided bytes. + /// # Errors + /// [DecodeError](FBError::DecodeError) pub fn from_bytes(fbkey: &[u8]) -> Result { let binc = DefaultOptions::new(); let indices: Vec<_> = binc.deserialize(&fbkey) @@ -29,6 +35,9 @@ impl FBKey { Ok (FBKey {indices}) } + /// Constructs the key from the provided base64 encoded form. + /// # Errors + /// [DecodeError](FBError::DecodeError) pub fn import(key_str: &str) -> Result { let indice_bytes = BASE64_STANDARD.decode(key_str) .map_err(|_| FBError::DecodeError)?; diff --git a/src/fbobj.rs b/src/fbobj.rs index 3212be7..5661919 100644 --- a/src/fbobj.rs +++ b/src/fbobj.rs @@ -3,6 +3,7 @@ pub mod fb128; use crate::{BlockOps, Encode, FieldOps}; use crypto_bigint::{ArrayEncoding, Bounded, RandomMod}; +/// The False Bottom Object holds the ciphertext and the keybase. The provided type aliases can be used to pick a block size. pub struct FBObj { pub(crate) c: Vec, pub(crate) r: Vec, diff --git a/src/fbobj/fb128.rs b/src/fbobj/fb128.rs index c0b80db..1ba830e 100644 --- a/src/fbobj/fb128.rs +++ b/src/fbobj/fb128.rs @@ -1,6 +1,7 @@ use crate::{FBAlgo, FBObj, FieldOps, Packing, WrappingOps}; use crypto_bigint::{Limb, NonZero, U128}; +/// [`FBObj`] with a block size of 128 bits. pub type FB128 = FBObj; const PRIME_POS_VAL: u16 = 159; diff --git a/src/lib.rs b/src/lib.rs index 8ca4dea..55864ab 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,3 +1,42 @@ +//! ## Usage +//! Unlike traditional encryption algorithms that output ciphertext to a given plaintext, +//! False Bottom works by "adding" messages to an existing ciphertext. +//! As such, the initial ciphertext and the keybase are generated from random data. +//! The ciphertext then grows as messages are added whereas the keybase is fixed +//! after initialization and is used to generate the keys for the ciphertext. +//! The parameters for the [`init()`](FBObj::init()) function determine the size +//! (in number of blocks) of the initial ciphertext and keybase respectively. +//! Type aliases over [`FBObj`] are provided to pick a block size. +//! Ex: [`FB128`] corresponds to a block size of 128 bits. +//! +//! ### Cipher Initialization: +//! ```rust +//! use false_bottom::{FB128, FBAlgo}; +//! // 15 blocks of ciphertext and 12 blocks of keybase with a block size of 128 bits. +//! let fb = FB128::init(15, 12); +//! ``` +//! +//! ### Adding Messages: +//! Messages can be added using the [`add()`](FBObj::add()) method. +//! This method returns an object [`FBKey`] that represents the corresponding key for this message. +//! This key can only be used to decrypt this message. +//! ```rust +//! let msg = b"Hello World!"; +//! let key = fb.add(&msg); +//! ``` +//! +//! ### Decryption: +//! The [`decrypt()`](FBObj::decrypt()) method returns the message that corresponds +//! to the provided [`FBKey`]. +//! ```rust +//! let decrypted = fb.decrypt(&key); +//! ``` +//! There is also an example [here](examples/encryption.rs). +//! +//! ### Import and Export +//! Available formats: Raw bytes and Base64 encoded. +//! Refer to the [example](examples/export.rs). + mod algo; mod arithmetic; mod encoding; @@ -9,6 +48,7 @@ mod packing; pub use crate::{ errors::FBError, fbobj::{ + FBObj, fb128::FB128, }, algo::FBAlgo, @@ -19,6 +59,6 @@ pub use crate::{ use crate::{ algo::BlockOps, arithmetic::{FieldOps, WrappingOps}, - fbobj::{FBObj, FBObjTrait}, + fbobj::FBObjTrait, packing::Packing, };