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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
use ;
pub use ;
/// The Merkle-Damgard construction, used as a building block for [hash
/// functions](crate::Hash).
///
/// The Merkle-Damgard construction builds a hash function from a [compression
/// function](CompressionFn). Internally, the hash function maintains a state
/// and splits the preimage into blocks with [padding](MerkleDamgardPad). Each
/// block is fed into the compression function along with the current state, and
/// the output of the compression function becomes the new state. The final
/// state is the hash of the input. The initial state is a fixed value called
/// the initialization vector (IV).
///
/// If the compression function is [secure](CompressionFn) and the padding
/// scheme is secure [secure](MerkleDamgardPad), the Merkle-Damgard construction
/// is provably secure, meaning that a collision in the Merkle-Damgard hash
/// function must stem from a collision in the underlying compression function.
/// (Note that the opposite is not necessarily true: if the underlying
/// compression function has known collision vulnerabilities, these might still
/// not affect the Merkle-Damgard construction. But this is a dangerous
/// situation nonetheless.)
///
/// # Length-extension Attacks
///
/// Imagine an attacker which knows some hash $H$ but doesn't know the preimage
/// $M$ which was hashed. If the Merkle-Damgard construction was used for
/// hashing, the hash $H$ corresponds to the internal state $S$ at the end of
/// the hashing process.
///
/// Imagine that the Merkle-Damgard construction was used with the padding
/// function $Pad$. The attacker can initialize the Merkle-Damgard construction
/// with the internal state $S = H$ and calculate the hash of $Pad(M) \parallel
/// X$ by simply feeding the message $X$ into the Merkle-Damgard construction.
///
/// This vulnerability can be practically exploited, for example, in a scheme
/// where a cloud storage provider is supposed to prove to a user that it has
/// stored some data $D$. The most inefficient way to do this would be for the
/// user to simply request all the data (possibly many tens of GiBs) from the
/// server. A more efficient way would be for the user to send a challenge $C$
/// and expect the server to respond with $Hash(D \parallel C)$. The user
/// compares this hash with his own $Hash(D \parallel C)$. The server shouldn't
/// be able to do any pre-computation since the challenge $C$ is unpredictable,
/// and hence must have the data stored to calculate the hash.
///
/// However, if the $Hash$ function is vulnerable to length-extension attacks,
/// this is not the case. The server can simply store $Hash(D)$ instead of $D$
/// and calculate $Hash(D \parallel C)$ using a length extension.
///
/// To mitigate this issue, the Merkle-Damgard state can be truncated to
/// generate the hash digest instead of being used in full. Alternatively, the
/// above challenge-response scheme can be amended to prepend $C$ instead
/// of appending it: require $Hash(C \parallel D)$ rather than $Hash(D \parallel
/// C)$.
///
/// [SHA-256](crate::Sha256) is a widely used hash function vulnerable to this
/// attack.
/// A compression function used internally by the [Merkle-Damgard
/// construction](MerkleDamgard).
///
/// The compression function takes the current state and an input block, and
/// produces a new state. To be secure, the output of the compression function
/// should be unpredictable and one-way, meaning it should be impossible to get
/// to an old state given the current state. Ideally, it should also be
/// impossible to get to an old state given the current state and the
/// corresponding preimage block.
/// The padding scheme used by the [Merkle-Damgard construction](MerkleDamgard).
///
/// The padding scheme splits the hash input into blocks of fixed size,
/// with padding. To be formally secure ("Merkle-Damgard compliant"), the
/// padding scheme $Pad$ must uphold the following contracts:
///
/// 1. Given the message $M$, $M$ must be a prefix of $Pad(M)$.
/// 2. Given two messages $M_1$ and $M_2$, if $len(M_1) = len(M_2)$, then
/// $len(Pad(M_1)) = len(Pad(M_2))$.
/// 3. If $len(M_1) \neq len(M_2)$, then the last blocks of $Pad(M_1)$ and
/// $Pad(M_2)$ must be different.
/// Implementation of the Merkle-Damgard construction.