2 // System.Security.Cryptography.SHA512Managed.cs
5 // Dan Lewis (dihlewis@yahoo.co.uk)
6 // Sebastien Pouliot (sebastien@ximian.com)
9 // Implementation translated from Bouncy Castle JCE (http://www.bouncycastle.org/)
10 // See bouncycastle.txt for license.
11 // (C) 2004 Novell (http://www.novell.com)
15 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
17 // Permission is hereby granted, free of charge, to any person obtaining
18 // a copy of this software and associated documentation files (the
19 // "Software"), to deal in the Software without restriction, including
20 // without limitation the rights to use, copy, modify, merge, publish,
21 // distribute, sublicense, and/or sell copies of the Software, and to
22 // permit persons to whom the Software is furnished to do so, subject to
23 // the following conditions:
25 // The above copyright notice and this permission notice shall be
26 // included in all copies or substantial portions of the Software.
28 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
29 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
30 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
31 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
32 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
33 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
34 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
39 namespace System
.Security
.Cryptography
{
41 public class SHA512Managed
: SHA512
{
46 private ulong byteCount1
;
47 private ulong byteCount2
;
49 private ulong H1
, H2
, H3
, H4
, H5
, H6
, H7
, H8
;
54 public SHA512Managed ()
58 Initialize (false); // limited initialization
61 private void Initialize (bool reuse
)
63 // SHA-512 initial hash value
64 // The first 64 bits of the fractional parts of the square roots
65 // of the first eight prime numbers
66 H1
= 0x6a09e667f3bcc908L
;
67 H2
= 0xbb67ae8584caa73bL
;
68 H3
= 0x3c6ef372fe94f82bL
;
69 H4
= 0xa54ff53a5f1d36f1L
;
70 H5
= 0x510e527fade682d1L
;
71 H6
= 0x9b05688c2b3e6c1fL
;
72 H7
= 0x1f83d9abfb41bd6bL
;
73 H8
= 0x5be0cd19137e2179L
;
80 for (int i
= 0; i
< xBuf
.Length
; i
++)
84 for (int i
= 0; i
!= W
.Length
; i
++)
89 public override void Initialize ()
91 Initialize (true); // reuse instance
96 protected override void HashCore (byte[] rgb
, int start
, int count
)
98 // fill the current word
99 while ((xBufOff
!= 0) && (count
> 0)) {
100 update (rgb
[start
]);
105 // process whole words.
106 while (count
> xBuf
.Length
) {
107 processWord (rgb
, start
);
108 start
+= xBuf
.Length
;
109 count
-= xBuf
.Length
;
110 byteCount1
+= (ulong) xBuf
.Length
;
113 // load in the remainder.
115 update (rgb
[start
]);
121 protected override byte[] HashFinal ()
125 ulong lowBitLength
= byteCount1
<< 3;
126 ulong hiBitLength
= byteCount2
;
128 // add the pad bytes.
133 processLength (lowBitLength
, hiBitLength
);
136 byte[] output
= new byte [64];
137 unpackWord(H1
, output
, 0);
138 unpackWord(H2
, output
, 8);
139 unpackWord(H3
, output
, 16);
140 unpackWord(H4
, output
, 24);
141 unpackWord(H5
, output
, 32);
142 unpackWord(H6
, output
, 40);
143 unpackWord(H7
, output
, 48);
144 unpackWord(H8
, output
, 56);
150 private void update (byte input
)
152 xBuf
[xBufOff
++] = input
;
153 if (xBufOff
== xBuf
.Length
) {
154 processWord(xBuf
, 0);
160 private void processWord (byte[] input
, int inOff
)
162 W
[wOff
++] = ( (ulong) input
[inOff
] << 56)
163 | ( (ulong) input
[inOff
+ 1] << 48)
164 | ( (ulong) input
[inOff
+ 2] << 40)
165 | ( (ulong) input
[inOff
+ 3] << 32)
166 | ( (ulong) input
[inOff
+ 4] << 24)
167 | ( (ulong) input
[inOff
+ 5] << 16)
168 | ( (ulong) input
[inOff
+ 6] << 8)
169 | ( (ulong) input
[inOff
+ 7]);
174 private void unpackWord (ulong word
, byte[] output
, int outOff
)
176 output
[outOff
] = (byte) (word
>> 56);
177 output
[outOff
+ 1] = (byte) (word
>> 48);
178 output
[outOff
+ 2] = (byte) (word
>> 40);
179 output
[outOff
+ 3] = (byte) (word
>> 32);
180 output
[outOff
+ 4] = (byte) (word
>> 24);
181 output
[outOff
+ 5] = (byte) (word
>> 16);
182 output
[outOff
+ 6] = (byte) (word
>> 8);
183 output
[outOff
+ 7] = (byte) word
;
186 // adjust the byte counts so that byteCount2 represents the
187 // upper long (less 3 bits) word of the byte count.
188 private void adjustByteCounts ()
190 if (byteCount1
> 0x1fffffffffffffffL
) {
191 byteCount2
+= (byteCount1
>> 61);
192 byteCount1
&= 0x1fffffffffffffffL
;
196 private void processLength (ulong lowW
, ulong hiW
)
204 private void processBlock ()
207 // expand 16 word block into 80 word blocks.
208 for (int t
= 16; t
<= 79; t
++)
209 W
[t
] = Sigma1 (W
[t
- 2]) + W
[t
- 7] + Sigma0 (W
[t
- 15]) + W
[t
- 16];
211 // set up working variables.
221 for (int t
= 0; t
<= 79; t
++) {
222 ulong T1
= h
+ Sum1 (e
) + Ch (e
, f
, g
) + SHAConstants
.K2
[t
] + W
[t
];
223 ulong T2
= Sum0 (a
) + Maj (a
, b
, c
);
242 // reset the offset and clean out the word buffer.
244 for (int i
= 0; i
!= W
.Length
; i
++)
248 private ulong rotateRight (ulong x
, int n
)
250 return (x
>> n
) | (x
<< (64 - n
));
253 /* SHA-512 and SHA-512 functions (as for SHA-256 but for longs) */
254 private ulong Ch (ulong x
, ulong y
, ulong z
)
256 return ((x
& y
) ^
((~x
) & z
));
259 private ulong Maj (ulong x
, ulong y
, ulong z
)
261 return ((x
& y
) ^
(x
& z
) ^
(y
& z
));
264 private ulong Sum0 (ulong x
)
266 return rotateRight (x
, 28) ^
rotateRight (x
, 34) ^
rotateRight (x
, 39);
269 private ulong Sum1 (ulong x
)
271 return rotateRight (x
, 14) ^
rotateRight (x
, 18) ^
rotateRight (x
, 41);
274 private ulong Sigma0 (ulong x
)
276 return rotateRight (x
, 1) ^
rotateRight(x
, 8) ^
(x
>> 7);
279 private ulong Sigma1 (ulong x
)
281 return rotateRight (x
, 19) ^
rotateRight (x
, 61) ^
(x
>> 6);