From c675aaa5f683e134f06dd27bb60af708dbe9f8a7 Mon Sep 17 00:00:00 2001 From: Adam Wick Date: Sat, 8 Jun 2019 11:39:47 -0700 Subject: [PATCH] Add a bunch of documentation and examples. --- src/lib.rs | 4 +-- src/sha/mod.rs | 63 +++++++++++++++++++++++++++++++++++++-- src/sha/sha1.rs | 19 ++++++++++++ src/sha/sha2.rs | 76 +++++++++++++++++++++++++++++++++++++++++++++++ src/sha/sha3.rs | 78 ++++++++++++++++++++++++++++++++++++++++++++++++- 5 files changed, 234 insertions(+), 6 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 8f74920..c429a4d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -45,8 +45,8 @@ pub mod ssh; /// used by TLS and others. pub mod x509; /// An implementation of the SHA family of hashes, including the relatively -/// weak SHA1 and a bunch of hashes you should use, like SHA2-256, SHA2-384, -/// and SHA2-512. +/// weak SHA1 and a bunch of hashes you should use, like the SHA2 and SHA3 +/// hashes. pub mod sha; /// A generic trait for defining what a key pair looks like. This is useful diff --git a/src/sha/mod.rs b/src/sha/mod.rs index 2dc66d0..3eca5ff 100644 --- a/src/sha/mod.rs +++ b/src/sha/mod.rs @@ -1,6 +1,63 @@ +//! The SHA family of hash functions, as defined by NIST; specifically, from +//! NIST 180-4 (for SHA1 and SHA2) and NIST 202 (for SHA3). +//! +//! These hash functions are used through their instantiation of the `Hash` +//! trait, located in the parent `simple_crypto` module and re-exported +//! here for convenience. Thus, you're not going to see a lot of functions +//! or macros, here, just the type declarations. +//! +//! To use SHA2-384, as an example, you could run the following code: +//! +//! ```rust +//! use simple_crypto::sha::{Hash,SHA384}; +//! +//! let empty: [u8; 0] = [0; 0]; +//! let mut digest_incremental = SHA384::new(); +//! digest_incremental.update(&empty); +//! digest_incremental.update(&empty); +//! digest_incremental.update(&empty); +//! let result = digest_incremental.finalize(); +//! +//! assert_eq!(result, vec![0x38,0xb0,0x60,0xa7,0x51,0xac,0x96,0x38, +//! 0x4c,0xd9,0x32,0x7e,0xb1,0xb1,0xe3,0x6a, +//! 0x21,0xfd,0xb7,0x11,0x14,0xbe,0x07,0x43, +//! 0x4c,0x0c,0xc7,0xbf,0x63,0xf6,0xe1,0xda, +//! 0x27,0x4e,0xde,0xbf,0xe7,0x6f,0x65,0xfb, +//! 0xd5,0x1a,0xd2,0xf1,0x48,0x98,0xb9,0x5b]); +//! ``` +//! +//! For other hashes, just substitute the appropriate hash structure for +//! `SHA384`. The `Hash` trait also includes a do-it-all-at-once built-in +//! function for those cases when you just have a single blob of data +//! you want to hash, rather than an incremental set of data: +//! +//! ```rust +//! use simple_crypto::sha::{Hash,SHA3_256}; +//! +//! let empty: [u8; 0] = [0; 0]; +//! let result = SHA3_256::hash(&empty); +//! +//! assert_eq!(result, vec![0xa7,0xff,0xc6,0xf8,0xbf,0x1e,0xd7,0x66, +//! 0x51,0xc1,0x47,0x56,0xa0,0x61,0xd6,0x62, +//! 0xf5,0x80,0xff,0x4d,0xe4,0x3b,0x49,0xfa, +//! 0x82,0xd8,0x0a,0x4b,0x80,0xf8,0x43,0x4a]); +//! ``` +//! +//! In general, you should not use SHA1 for anything but supporting legacy +//! systems. We recommend either SHA2 or SHA3 at their 256-, 384-, or 512-bit +//! sizes. NIST claims (in FIPS 202, page 23-24) that SHA2 and SHA3 are +//! approximately equivalent in terms of security for collision, preimate, +//! and second preimage attacks, but that SHA3 improves upon SHA2 against +//! length-extension and other attacks. On the other hand, SHA2 has been +//! banged on for a little longer, and there's some claims that it's more +//! resistant to quantum attacks. So ... make your own decisions. #[macro_use] mod shared; +mod sha1; +mod sha2; +mod sha3; -pub mod sha1; -pub mod sha2; -pub mod sha3; \ No newline at end of file +pub use super::Hash; +pub use self::sha1::SHA1; +pub use self::sha2::{SHA224,SHA256,SHA384,SHA512}; +pub use self::sha3::{SHA3_224,SHA3_256,SHA3_384,SHA3_512}; \ No newline at end of file diff --git a/src/sha/sha1.rs b/src/sha/sha1.rs index 515d8c8..2ee32e7 100644 --- a/src/sha/sha1.rs +++ b/src/sha/sha1.rs @@ -2,6 +2,25 @@ use byteorder::{BigEndian,WriteBytesExt}; use super::super::Hash; use sha::shared::calculate_k; +/// The SHA1 hash. Don't use this except to support legacy systems. +/// +/// To use, you can run it in incremental mode -- by calling new(), +/// update() zero or more times, and then finalize() -- or you can +/// just invoke the hash directly. For example: +/// +/// ```rust +/// use simple_crypto::sha::{Hash,SHA1}; +/// +/// let empty = [0; 0]; +/// // Do the hash using the incremental API +/// let mut hashf = SHA1::new(); +/// hashf.update(&empty); +/// let result_incremental = hashf.finalize(); +/// // Do the hash using the direct API +/// let result_direct = SHA1::hash(&empty); +/// // ... and they should be the same +/// assert_eq!(result_incremental,result_direct); +/// ``` pub struct SHA1 { state: [u32; 5], buffer: Vec, diff --git a/src/sha/sha2.rs b/src/sha/sha2.rs index 5e5968b..21dd66b 100644 --- a/src/sha/sha2.rs +++ b/src/sha/sha2.rs @@ -2,6 +2,25 @@ use byteorder::{BigEndian,ByteOrder,WriteBytesExt}; use sha::shared::calculate_k; use super::super::Hash; +/// The SHA2-224 hash. +/// +/// To use, you can run it in incremental mode -- by calling new(), +/// update() zero or more times, and then finalize() -- or you can +/// just invoke the hash directly. For example: +/// +/// ```rust +/// use simple_crypto::sha::{Hash,SHA224}; +/// +/// let empty = [0; 0]; +/// // Do the hash using the incremental API +/// let mut hashf = SHA224::new(); +/// hashf.update(&empty); +/// let result_incremental = hashf.finalize(); +/// // Do the hash using the direct API +/// let result_direct = SHA224::hash(&empty); +/// // ... and they should be the same +/// assert_eq!(result_incremental,result_direct); +/// ``` pub struct SHA224 { state: SHA256State } @@ -37,6 +56,25 @@ impl Hash for SHA224 { } } +/// The SHA2-256 hash. [GOOD] +/// +/// To use, you can run it in incremental mode -- by calling new(), +/// update() zero or more times, and then finalize() -- or you can +/// just invoke the hash directly. For example: +/// +/// ```rust +/// use simple_crypto::sha::{Hash,SHA256}; +/// +/// let empty = [0; 0]; +/// // Do the hash using the incremental API +/// let mut hashf = SHA256::new(); +/// hashf.update(&empty); +/// let result_incremental = hashf.finalize(); +/// // Do the hash using the direct API +/// let result_direct = SHA256::hash(&empty); +/// // ... and they should be the same +/// assert_eq!(result_incremental,result_direct); +/// ``` pub struct SHA256 { state: SHA256State } @@ -73,6 +111,25 @@ impl Hash for SHA256 { } } +/// The SHA2-384 hash. [BETTER] +/// +/// To use, you can run it in incremental mode -- by calling new(), +/// update() zero or more times, and then finalize() -- or you can +/// just invoke the hash directly. For example: +/// +/// ```rust +/// use simple_crypto::sha::{Hash,SHA384}; +/// +/// let empty = [0; 0]; +/// // Do the hash using the incremental API +/// let mut hashf = SHA384::new(); +/// hashf.update(&empty); +/// let result_incremental = hashf.finalize(); +/// // Do the hash using the direct API +/// let result_direct = SHA384::hash(&empty); +/// // ... and they should be the same +/// assert_eq!(result_incremental,result_direct); +/// ``` pub struct SHA384 { state: SHA512State } @@ -109,6 +166,25 @@ impl Hash for SHA384 { } } +/// The SHA2-512 hash. [BEST] +/// +/// To use, you can run it in incremental mode -- by calling new(), +/// update() zero or more times, and then finalize() -- or you can +/// just invoke the hash directly. For example: +/// +/// ```rust +/// use simple_crypto::sha::{Hash,SHA512}; +/// +/// let empty = [0; 0]; +/// // Do the hash using the incremental API +/// let mut hashf = SHA512::new(); +/// hashf.update(&empty); +/// let result_incremental = hashf.finalize(); +/// // Do the hash using the direct API +/// let result_direct = SHA512::hash(&empty); +/// // ... and they should be the same +/// assert_eq!(result_incremental,result_direct); +/// ``` pub struct SHA512 { state: SHA512State } diff --git a/src/sha/sha3.rs b/src/sha/sha3.rs index fa88617..dd500ee 100644 --- a/src/sha/sha3.rs +++ b/src/sha/sha3.rs @@ -225,7 +225,26 @@ impl Keccak { } } -struct SHA3_224 { +/// The SHA3-224 hash. +/// +/// To use, you can run it in incremental mode -- by calling new(), +/// update() zero or more times, and then finalize() -- or you can +/// just invoke the hash directly. For example: +/// +/// ```rust +/// use simple_crypto::sha::{Hash,SHA3_224}; +/// +/// let empty = [0; 0]; +/// // Do the hash using the incremental API +/// let mut hashf = SHA3_224::new(); +/// hashf.update(&empty); +/// let result_incremental = hashf.finalize(); +/// // Do the hash using the direct API +/// let result_direct = SHA3_224::hash(&empty); +/// // ... and they should be the same +/// assert_eq!(result_incremental,result_direct); +/// ``` +pub struct SHA3_224 { state: Keccak } @@ -292,6 +311,25 @@ mod sha224 { } } +/// The SHA3-256 hash. [GOOD] +/// +/// To use, you can run it in incremental mode -- by calling new(), +/// update() zero or more times, and then finalize() -- or you can +/// just invoke the hash directly. For example: +/// +/// ```rust +/// use simple_crypto::sha::{Hash,SHA3_256}; +/// +/// let empty = [0; 0]; +/// // Do the hash using the incremental API +/// let mut hashf = SHA3_256::new(); +/// hashf.update(&empty); +/// let result_incremental = hashf.finalize(); +/// // Do the hash using the direct API +/// let result_direct = SHA3_256::hash(&empty); +/// // ... and they should be the same +/// assert_eq!(result_incremental,result_direct); +/// ``` pub struct SHA3_256 { state: Keccak } @@ -360,6 +398,25 @@ mod sha256 { } } +/// The SHA3-384 hash. [BETTER] +/// +/// To use, you can run it in incremental mode -- by calling new(), +/// update() zero or more times, and then finalize() -- or you can +/// just invoke the hash directly. For example: +/// +/// ```rust +/// use simple_crypto::sha::{Hash,SHA3_384}; +/// +/// let empty = [0; 0]; +/// // Do the hash using the incremental API +/// let mut hashf = SHA3_384::new(); +/// hashf.update(&empty); +/// let result_incremental = hashf.finalize(); +/// // Do the hash using the direct API +/// let result_direct = SHA3_384::hash(&empty); +/// // ... and they should be the same +/// assert_eq!(result_incremental,result_direct); +/// ``` pub struct SHA3_384 { state: Keccak } @@ -432,6 +489,25 @@ mod sha384 { } } +/// The SHA3-512 hash. [BEST] +/// +/// To use, you can run it in incremental mode -- by calling new(), +/// update() zero or more times, and then finalize() -- or you can +/// just invoke the hash directly. For example: +/// +/// ```rust +/// use simple_crypto::sha::{Hash,SHA3_512}; +/// +/// let empty = [0; 0]; +/// // Do the hash using the incremental API +/// let mut hashf = SHA3_512::new(); +/// hashf.update(&empty); +/// let result_incremental = hashf.finalize(); +/// // Do the hash using the direct API +/// let result_direct = SHA3_512::hash(&empty); +/// // ... and they should be the same +/// assert_eq!(result_incremental,result_direct); +/// ``` pub struct SHA3_512 { state: Keccak }