1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
//! **extendhash** is a Rust crate to compute hash extensions.
//!
//! Supported hash algorithms:
//! 
//!   * MD5
//!   * SHA-0
//!   * SHA-1
//!
//! # Example
//!
//! ```
//! use extendhash::sha1;
//!
//! let secret_data = "This is a secret!".as_bytes();
//! let hash = sha1::compute_hash(secret_data);
//! let secret_data_length = secret_data.len();
//! 
//! // Now we try computing a hash extension, assuming that `secret_data`
//! // is not available. We only need `hash` and `secret_data_length`.
//! let appended_message = "Appended message.".as_bytes();
//! let combined_hash = sha1::extend_hash(hash, secret_data_length, appended_message);
//! 
//! // Now we verify that `combined_hash` matches the
//! // concatenation (note the intermediate padding):
//! let mut combined_data = Vec::<u8>::new();
//! combined_data.extend_from_slice(secret_data);
//! let intermediate_padding = sha1::padding_for_length(secret_data_length);
//! combined_data.extend_from_slice(intermediate_padding.as_slice());
//! combined_data.extend_from_slice(appended_message);
//! assert_eq!(combined_hash, sha1::compute_hash(combined_data.as_slice()));
//! ```

#![doc(html_root_url = "https://docs.rs/extendhash/0.2.2")]

/// Compute MD5 hashes and hash extensions.
///
/// # Example
///
/// ```
/// # use extendhash::md5;
/// let secret_data = "This is a secret!".as_bytes();
/// let hash = md5::compute_hash(secret_data);
/// let secret_data_length = secret_data.len();
/// 
/// // Now we try computing a hash extension, assuming that `secret_data`
/// // is not available. We only need `hash` and `secret_data_length`.
/// let appended_message = "Appended message.".as_bytes();
/// let combined_hash = md5::extend_hash(hash, secret_data_length, appended_message);
/// 
/// // Now we verify that `combined_hash` matches the
/// // concatenation (note the intermediate padding):
/// let mut combined_data = Vec::<u8>::new();
/// combined_data.extend_from_slice(secret_data);
/// let intermediate_padding = md5::padding_for_length(secret_data_length);
/// combined_data.extend_from_slice(intermediate_padding.as_slice());
/// combined_data.extend_from_slice(appended_message);
/// assert_eq!(combined_hash, md5::compute_hash(combined_data.as_slice()));
/// ```
pub mod md5;

/// Shared code for SHA-0 and SHA-1.
pub(crate) mod sha01;

/// Compute SHA-0 hashes and hash extensions.
///
/// # Example
///
/// ```
/// # use extendhash::sha0;
/// let secret_data = "This is a secret!".as_bytes();
/// let hash = sha0::compute_hash(secret_data);
/// let secret_data_length = secret_data.len();
/// 
/// // Now we try computing a hash extension, assuming that `secret_data`
/// // is not available. We only need `hash` and `secret_data_length`.
/// let appended_message = "Appended message.".as_bytes();
/// let combined_hash = sha0::extend_hash(hash, secret_data_length, appended_message);
/// 
/// // Now we verify that `combined_hash` matches the
/// // concatenation (note the intermediate padding):
/// let mut combined_data = Vec::<u8>::new();
/// combined_data.extend_from_slice(secret_data);
/// let intermediate_padding = sha0::padding_for_length(secret_data_length);
/// combined_data.extend_from_slice(intermediate_padding.as_slice());
/// combined_data.extend_from_slice(appended_message);
/// assert_eq!(combined_hash, sha0::compute_hash(combined_data.as_slice()));
/// ```
pub mod sha0;

/// Compute SHA-1 hashes and hash extensions.
///
/// # Example
///
/// ```
/// # use extendhash::sha1;
/// let secret_data = "This is a secret!".as_bytes();
/// let hash = sha1::compute_hash(secret_data);
/// let secret_data_length = secret_data.len();
/// 
/// // Now we try computing a hash extension, assuming that `secret_data`
/// // is not available. We only need `hash` and `secret_data_length`.
/// let appended_message = "Appended message.".as_bytes();
/// let combined_hash = sha1::extend_hash(hash, secret_data_length, appended_message);
/// 
/// // Now we verify that `combined_hash` matches the
/// // concatenation (note the intermediate padding):
/// let mut combined_data = Vec::<u8>::new();
/// combined_data.extend_from_slice(secret_data);
/// let intermediate_padding = sha1::padding_for_length(secret_data_length);
/// combined_data.extend_from_slice(intermediate_padding.as_slice());
/// combined_data.extend_from_slice(appended_message);
/// assert_eq!(combined_hash, sha1::compute_hash(combined_data.as_slice()));
/// ```
pub mod sha1;