Mercurial > projects > dcrypt
comparison dcrypt/crypto/hashes/SHA512.d @ 27:8b5eaf3c2979
Fixed error in hash message padding reported by Glenn Haecker.
author | Thomas Dixon <reikon@reikon.us> |
---|---|
date | Sat, 09 May 2009 23:29:20 -0400 |
parents | 176c933827a8 |
children | ad687db713a4 |
comparison
equal
deleted
inserted
replaced
26:176c933827a8 | 27:8b5eaf3c2979 |
---|---|
14 * Implementation of the US NSA's SHA-512. | 14 * Implementation of the US NSA's SHA-512. |
15 * | 15 * |
16 * Conforms: FIPS-180-2 | 16 * Conforms: FIPS-180-2 |
17 * References: http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf | 17 * References: http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf |
18 */ | 18 */ |
19 class SHA512 : Hash { | 19 class SHA512 : Hash |
20 { | |
20 private const ulong[] K = [ | 21 private const ulong[] K = [ |
21 0x428a2f98d728ae22u, 0x7137449123ef65cdu, 0xb5c0fbcfec4d3b2fu, 0xe9b5dba58189dbbcu, | 22 0x428a2f98d728ae22u, 0x7137449123ef65cdu, 0xb5c0fbcfec4d3b2fu, 0xe9b5dba58189dbbcu, |
22 0x3956c25bf348b538u, 0x59f111f1b605d019u, 0x923f82a4af194f9bu, 0xab1c5ed5da6d8118u, | 23 0x3956c25bf348b538u, 0x59f111f1b605d019u, 0x923f82a4af194f9bu, 0xab1c5ed5da6d8118u, |
23 0xd807aa98a3030242u, 0x12835b0145706fbeu, 0x243185be4ee4b28cu, 0x550c7dc3d5ffb4e2u, | 24 0xd807aa98a3030242u, 0x12835b0145706fbeu, 0x243185be4ee4b28cu, 0x550c7dc3d5ffb4e2u, |
24 0x72be5d74f27b896fu, 0x80deb1fe3b1696b1u, 0x9bdc06a725c71235u, 0xc19bf174cf692694u, | 25 0x72be5d74f27b896fu, 0x80deb1fe3b1696b1u, 0x9bdc06a725c71235u, 0xc19bf174cf692694u, |
37 0xca273eceea26619cu, 0xd186b8c721c0c207u, 0xeada7dd6cde0eb1eu, 0xf57d4f7fee6ed178u, | 38 0xca273eceea26619cu, 0xd186b8c721c0c207u, 0xeada7dd6cde0eb1eu, 0xf57d4f7fee6ed178u, |
38 0x06f067aa72176fbau, 0x0a637dc5a2c898a6u, 0x113f9804bef90daeu, 0x1b710b35131c471bu, | 39 0x06f067aa72176fbau, 0x0a637dc5a2c898a6u, 0x113f9804bef90daeu, 0x1b710b35131c471bu, |
39 0x28db77f523047d84u, 0x32caab7b40c72493u, 0x3c9ebe0a15c9bebcu, 0x431d67c49c100d4cu, | 40 0x28db77f523047d84u, 0x32caab7b40c72493u, 0x3c9ebe0a15c9bebcu, 0x431d67c49c100d4cu, |
40 0x4cc5d4becb3e42b6u, 0x597f299cfc657e2au, 0x5fcb6fab3ad6faecu, 0x6c44198c4a475817u | 41 0x4cc5d4becb3e42b6u, 0x597f299cfc657e2au, 0x5fcb6fab3ad6faecu, 0x6c44198c4a475817u |
41 ]; | 42 ]; |
43 | |
42 protected ulong h0, h1, h2, h3, h4, h5, h6, h7; | 44 protected ulong h0, h1, h2, h3, h4, h5, h6, h7; |
43 | 45 |
44 this (void[] input_=null) { | 46 this (void[] input_=null) |
47 { | |
45 reset(); | 48 reset(); |
46 super(input_); | 49 super(input_); |
47 } | 50 } |
48 | 51 |
49 uint blockSize() { | 52 uint blockSize() |
53 { | |
50 return 128; | 54 return 128; |
51 } | 55 } |
52 | 56 |
53 uint digestSize() { | 57 uint digestSize() |
58 { | |
54 return 64; | 59 return 64; |
55 } | 60 } |
56 | 61 |
57 char[] name() { | 62 char[] name() |
63 { | |
58 return "SHA512"; | 64 return "SHA512"; |
59 } | 65 } |
60 | 66 |
61 void transform(ubyte[] input) { | 67 void transform(ubyte[] input) |
68 { | |
62 ulong[] w = new ulong[80]; | 69 ulong[] w = new ulong[80]; |
63 | 70 |
64 for (int i = 0, j = 0; i < 16; i++,j+=long.sizeof) | 71 for (int i = 0, j = 0; i < 16; i++,j+=long.sizeof) |
65 w[i] = ByteConverter.BigEndian.to!(ulong)(input[j..j+long.sizeof]); | 72 w[i] = ByteConverter.BigEndian.to!(ulong)(input[j..j+long.sizeof]); |
66 | 73 |
74 e = h4, | 81 e = h4, |
75 f = h5, | 82 f = h5, |
76 g = h6, | 83 g = h6, |
77 h = h7; | 84 h = h7; |
78 | 85 |
79 for (int i = 0; i < 80; i++) { | 86 for (int i = 0; i < 80; i++) |
87 { | |
80 ulong t1 = h + sum1(e) + ch(e,f,g) + K[i] + w[i], | 88 ulong t1 = h + sum1(e) + ch(e,f,g) + K[i] + w[i], |
81 t2 = sum0(a) + maj(a,b,c); | 89 t2 = sum0(a) + maj(a,b,c); |
82 h = g; | 90 h = g; |
83 g = f; | 91 g = f; |
84 f = e; | 92 f = e; |
97 h5 += f; | 105 h5 += f; |
98 h6 += g; | 106 h6 += g; |
99 h7 += h; | 107 h7 += h; |
100 } | 108 } |
101 | 109 |
102 private ulong ch(ulong x, ulong y, ulong z) { | 110 private ulong ch(ulong x, ulong y, ulong z) |
111 { | |
103 return (x&y)^(~x&z); | 112 return (x&y)^(~x&z); |
104 } | 113 } |
105 | 114 |
106 private ulong maj(ulong x, ulong y, ulong z) { | 115 private ulong maj(ulong x, ulong y, ulong z) |
116 { | |
107 return (x&y)^(x&z)^(y&z); | 117 return (x&y)^(x&z)^(y&z); |
108 } | 118 } |
109 | 119 |
110 private ulong sum0(ulong x) { | 120 private ulong sum0(ulong x) |
121 { | |
111 return (Bitwise.rotateRight(x,28)^ | 122 return (Bitwise.rotateRight(x,28)^ |
112 Bitwise.rotateRight(x,34)^ | 123 Bitwise.rotateRight(x,34)^ |
113 Bitwise.rotateRight(x,39)); | 124 Bitwise.rotateRight(x,39)); |
114 } | 125 } |
115 | 126 |
116 private ulong sum1(ulong x) { | 127 private ulong sum1(ulong x) |
128 { | |
117 return (Bitwise.rotateRight(x,14)^ | 129 return (Bitwise.rotateRight(x,14)^ |
118 Bitwise.rotateRight(x,18)^ | 130 Bitwise.rotateRight(x,18)^ |
119 Bitwise.rotateRight(x,41)); | 131 Bitwise.rotateRight(x,41)); |
120 } | 132 } |
121 | 133 |
122 private ulong theta0(ulong x) { | 134 private ulong theta0(ulong x) |
135 { | |
123 return Bitwise.rotateRight(x,1)^Bitwise.rotateRight(x,8)^(x >> 7); | 136 return Bitwise.rotateRight(x,1)^Bitwise.rotateRight(x,8)^(x >> 7); |
124 } | 137 } |
125 | 138 |
126 private ulong theta1(ulong x) { | 139 private ulong theta1(ulong x) |
140 { | |
127 return Bitwise.rotateRight(x,19)^Bitwise.rotateRight(x,61)^(x >> 6); | 141 return Bitwise.rotateRight(x,19)^Bitwise.rotateRight(x,61)^(x >> 6); |
128 } | 142 } |
129 | 143 |
130 ubyte[] digest() { | 144 ubyte[] digest() |
145 { | |
131 padMessage(MODE_SHA); | 146 padMessage(MODE_SHA); |
132 ubyte[] result = new ubyte[digestSize]; | 147 ubyte[] result = new ubyte[digestSize]; |
133 | 148 |
134 result[0..8] = ByteConverter.BigEndian.from!(ulong)(h0); | 149 result[0..8] = ByteConverter.BigEndian.from!(ulong)(h0); |
135 result[8..16] = ByteConverter.BigEndian.from!(ulong)(h1); | 150 result[8..16] = ByteConverter.BigEndian.from!(ulong)(h1); |
142 | 157 |
143 reset(); | 158 reset(); |
144 return result; | 159 return result; |
145 } | 160 } |
146 | 161 |
147 void reset() { | 162 void reset() |
163 { | |
148 super.reset(); | 164 super.reset(); |
149 h0 = 0x6a09e667f3bcc908u; | 165 h0 = 0x6a09e667f3bcc908u; |
150 h1 = 0xbb67ae8584caa73bu; | 166 h1 = 0xbb67ae8584caa73bu; |
151 h2 = 0x3c6ef372fe94f82bu; | 167 h2 = 0x3c6ef372fe94f82bu; |
152 h3 = 0xa54ff53a5f1d36f1u; | 168 h3 = 0xa54ff53a5f1d36f1u; |
154 h5 = 0x9b05688c2b3e6c1fu; | 170 h5 = 0x9b05688c2b3e6c1fu; |
155 h6 = 0x1f83d9abfb41bd6bu; | 171 h6 = 0x1f83d9abfb41bd6bu; |
156 h7 = 0x5be0cd19137e2179u; | 172 h7 = 0x5be0cd19137e2179u; |
157 } | 173 } |
158 | 174 |
159 SHA512 copy() { | 175 SHA512 copy() |
176 { | |
160 SHA512 h = new SHA512(buffer[0..index]); | 177 SHA512 h = new SHA512(buffer[0..index]); |
161 h.bytes = bytes; | 178 h.bytes = bytes; |
162 h.h0 = h0; | 179 h.h0 = h0; |
163 h.h1 = h1; | 180 h.h1 = h1; |
164 h.h2 = h2; | 181 h.h2 = h2; |
168 h.h6 = h6; | 185 h.h6 = h6; |
169 h.h7 = h7; | 186 h.h7 = h7; |
170 return h; | 187 return h; |
171 } | 188 } |
172 | 189 |
173 debug (UnitTest) { | 190 debug (UnitTest) |
174 unittest { | 191 { |
192 unittest | |
193 { | |
175 static const char[][] test_inputs = [ | 194 static const char[][] test_inputs = [ |
176 "", | 195 "", |
177 "abc", | 196 "abc", |
178 "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn"~ | 197 "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn"~ |
179 "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", | 198 "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", |
197 "e718483d0ce769644e2e42c7bc15b4638e1f98b13b2044285632a803afa973eb"~ | 216 "e718483d0ce769644e2e42c7bc15b4638e1f98b13b2044285632a803afa973eb"~ |
198 "de0ff244877ea60a4cb0432ce577c31beb009c5c2c49aa2e4eadb217ad8cc09b" | 217 "de0ff244877ea60a4cb0432ce577c31beb009c5c2c49aa2e4eadb217ad8cc09b" |
199 ]; | 218 ]; |
200 | 219 |
201 SHA512 h = new SHA512(); | 220 SHA512 h = new SHA512(); |
202 foreach (uint i, char[] input; test_inputs) { | 221 foreach (uint i, char[] input; test_inputs) |
222 { | |
203 for (int j = 0; j < test_repeat[i]; j++) | 223 for (int j = 0; j < test_repeat[i]; j++) |
204 h.update(input); | 224 h.update(input); |
205 char[] digest = h.hexDigest(); | 225 char[] digest = h.hexDigest(); |
206 assert(digest == test_results[i], | 226 assert(digest == test_results[i], |
207 h.name~": ("~digest~") != ("~test_results[i]~")"); | 227 h.name~": ("~digest~") != ("~test_results[i]~")"); |