From 9333e994f2fa00096277711966774e92e205c931 Mon Sep 17 00:00:00 2001 From: Avril Date: Thu, 8 Apr 2021 21:54:53 +0100 Subject: [PATCH] document key/iv encoding/decoding --- Cargo.toml | 2 +- src/key.rs | 106 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 105 insertions(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 31cfe9e..e03a33f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "chacha20stream" -version = "1.0.1" +version = "1.0.2" keywords = ["chacha20_poly1305", "stream", "wrapper", "encryption", "decryption"] description = "A writable wrapper stream for encryption and decryption with the stream cipher chacha20_poly1305" homepage = "https://git.flanchan.moe/flanchan/chacha20stream" diff --git a/src/key.rs b/src/key.rs index 6a49f1c..f494143 100644 --- a/src/key.rs +++ b/src/key.rs @@ -21,6 +21,24 @@ use crate::ext::*; /// ``` /// /// You can also generate a random key/IV pair with `chacha20stream::keygen()`. +/// +/// # Encoding +/// This type implements `std::fmt::Display`, which prints the key as a base64 string. +/// Additionally, it implements `std::str::FromStr`, which decodes a base64 string into a `Key` instance. +/// If the input base64 string data decoded is shorter than `KEY_SIZE`, the rest of the key instance is padded with 0s. +/// If it is longer, the rest is ignored. +/// +/// The key can also be lazily formatted as a hex string, with the method `to_hex_string()`. +/// ``` +/// # use chacha20stream::Key; +/// let key = Key::new(); +/// let key_encoded = key.to_string(); +/// +/// println!("Key base64: {}", key_encoded); +/// println!("Key hex: {}", key.to_hex_string()); +/// +/// assert_eq!(key_encoded.parse::().unwrap(), key); +/// ``` #[derive(Debug, Clone, PartialEq, Eq, Hash, Copy, Default)] #[repr(transparent)] pub struct Key([u8; KEY_SIZE]); @@ -38,6 +56,24 @@ pub struct Key([u8; KEY_SIZE]); /// ``` /// /// You can also generate a random key/IV pair with `chacha20stream::keygen()`. +/// +/// # Encoding +/// This type implements `std::fmt::Display`, which prints the IV as a base64 string. +/// Additionally, it implements `std::str::FromStr`, which decodes a base64 string into a `IV` instance. +/// If the input base64 string data decoded is shorter than `IV_SIZE`, the rest of the IV instance is padded with 0s. +/// If it is longer, the rest is ignored. +/// +/// The IV can also be lazily formatted as a hex string, with the method `to_hex_string()`. +/// ``` +/// # use chacha20stream::IV; +/// let iv = IV::new(); +/// let iv_encoded = iv.to_string(); +/// +/// println!("IV base64: {}", iv_encoded); +/// println!("IV hex: {}", iv.to_hex_string()); +/// +/// assert_eq!(iv_encoded.parse::().unwrap(), iv); +/// ``` #[derive(Debug, Clone, PartialEq, Eq, Hash, Copy, Default)] #[repr(transparent)] pub struct IV([u8; IV_SIZE]); @@ -56,6 +92,29 @@ impl Key getrandom(&mut output[..]).expect("rng fatal"); Self(output) } + + /// Format this key as a hex string + /// + /// Returns an opaque type that lazily formats the key into a hex string when written. + /// + /// # Example + /// ``` + /// # use chacha20stream::Key; + /// fn print_key_info(key: &Key) { + /// println!("Key base64: {}", key); + /// println!("Key hex: {}", key.to_hex_string()); + /// } + /// ``` + /// Formatting to `String` + /// ``` + /// # use chacha20stream::Key; + /// # let key = Key::new(); + /// let key_hex_string = key.to_hex_string().to_string(); + /// ``` + pub fn to_hex_string(&self) -> impl fmt::Display + '_ + { + self.0.iter().copied().into_hex() + } } impl IV @@ -73,6 +132,29 @@ impl IV getrandom(&mut output[..]).expect("rng fatal"); Self(output) } + + /// Format this IV as a hex string + /// + /// Returns an opaque type that lazily formats the IV into a hex string when written. + /// + /// # Example + /// ``` + /// # use chacha20stream::IV; + /// fn print_iv_info(iv: &IV) { + /// println!("IV base64: {}", iv); + /// println!("IV hex: {}", iv.to_hex_string()); + /// } + /// ``` + /// Formatting to `String` + /// ``` + /// # use chacha20stream::IV; + /// # let iv = IV::new(); + /// let iv_hex_string = iv.to_hex_string().to_string(); + /// ``` + pub fn to_hex_string(&self) -> impl fmt::Display + '_ + { + self.0.iter().copied().into_hex() + } } impl From<[u8; KEY_SIZE]> for Key @@ -142,7 +224,7 @@ impl fmt::Display for Key { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{}", self.0.iter().copied().into_hex()) + write!(f, "{}", base64::encode(&self.0[..])) } } @@ -150,7 +232,7 @@ impl fmt::Display for IV { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{}", self.0.iter().copied().into_hex()) + write!(f, "{}", base64::encode(&self.0[..])) } } @@ -183,3 +265,23 @@ impl str::FromStr for IV Ok(this) } } + +#[cfg(test)] +mod tests +{ + use super::{Key, IV}; + #[test] + fn enc_dec() + { + let (key, iv) = crate::keygen(); + + let key_str = key.to_string(); + let iv_str = iv.to_string(); + + let (key2, iv2): (Key, IV) = (key_str.parse().expect("key"), + iv_str.parse().expect("iv")); + + assert_eq!(key, key2); + assert_eq!(iv, iv2); + } +}