2 // System.Security.Cryptography SHA256Managed Class implementation
5 // Matthew S. Ford (Matthew.S.Ford@Rose-Hulman.Edu)
8 // (C) 2004 Novell (http://www.novell.com)
12 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
14 // Permission is hereby granted, free of charge, to any person obtaining
15 // a copy of this software and associated documentation files (the
16 // "Software"), to deal in the Software without restriction, including
17 // without limitation the rights to use, copy, modify, merge, publish,
18 // distribute, sublicense, and/or sell copies of the Software, and to
19 // permit persons to whom the Software is furnished to do so, subject to
20 // the following conditions:
22 // The above copyright notice and this permission notice shall be
23 // included in all copies or substantial portions of the Software.
25 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
29 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
30 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
31 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
34 namespace System
.Security
.Cryptography
{
36 public class SHA256Managed
: SHA256
{
38 private const int BLOCK_SIZE_BYTES
= 64;
39 private const int HASH_SIZE_BYTES
= 32;
43 private byte[] _ProcessingBuffer
; // Used to start data when passed less than a block worth.
44 private int _ProcessingBufferCount
; // Counts how much data we have stored that still needs processed.
46 public SHA256Managed ()
49 _ProcessingBuffer
= new byte [BLOCK_SIZE_BYTES
];
53 private uint Ch (uint u
, uint v
, uint w
)
55 return (u
&v
) ^
(~u
&w
);
58 private uint Maj (uint u
, uint v
, uint w
)
60 return (u
&v
) ^
(u
&w
) ^
(v
&w
);
63 private uint Ro0 (uint x
)
65 return ((x
>> 7) | (x
<< 25))
66 ^
((x
>> 18) | (x
<< 14))
70 private uint Ro1 (uint x
)
72 return ((x
>> 17) | (x
<< 15))
73 ^
((x
>> 19) | (x
<< 13))
77 private uint Sig0 (uint x
)
79 return ((x
>> 2) | (x
<< 30))
80 ^
((x
>> 13) | (x
<< 19))
81 ^
((x
>> 22) | (x
<< 10));
84 private uint Sig1 (uint x
)
86 return ((x
>> 6) | (x
<< 26))
87 ^
((x
>> 11) | (x
<< 21))
88 ^
((x
>> 25) | (x
<< 7));
91 protected override void HashCore (byte[] rgb
, int start
, int size
)
96 if (_ProcessingBufferCount
!= 0) {
97 if (size
< (BLOCK_SIZE_BYTES
- _ProcessingBufferCount
)) {
98 System
.Buffer
.BlockCopy (rgb
, start
, _ProcessingBuffer
, _ProcessingBufferCount
, size
);
99 _ProcessingBufferCount
+= size
;
103 i
= (BLOCK_SIZE_BYTES
- _ProcessingBufferCount
);
104 System
.Buffer
.BlockCopy (rgb
, start
, _ProcessingBuffer
, _ProcessingBufferCount
, i
);
105 ProcessBlock (_ProcessingBuffer
, 0);
106 _ProcessingBufferCount
= 0;
112 for (i
=0; i
<size
-size
%BLOCK_SIZE_BYTES
; i
+= BLOCK_SIZE_BYTES
) {
113 ProcessBlock (rgb
, start
+i
);
116 if (size
%BLOCK_SIZE_BYTES
!= 0) {
117 System
.Buffer
.BlockCopy (rgb
, size
-size
%BLOCK_SIZE_BYTES
+start
, _ProcessingBuffer
, 0, size
%BLOCK_SIZE_BYTES
);
118 _ProcessingBufferCount
= size
%BLOCK_SIZE_BYTES
;
122 protected override byte[] HashFinal ()
124 byte[] hash
= new byte[32];
127 ProcessFinalBlock (_ProcessingBuffer
, 0, _ProcessingBufferCount
);
129 for (i
=0; i
<8; i
++) {
130 for (j
=0; j
<4; j
++) {
131 hash
[i
*4+j
] = (byte)(_H
[i
] >> (24-j
*8));
139 public override void Initialize ()
142 _ProcessingBufferCount
= 0;
154 private void ProcessBlock (byte[] inputBuffer
, int inputOffset
)
156 uint a
, b
, c
, d
, e
, f
, g
, h
;
161 count
+= BLOCK_SIZE_BYTES
;
165 for (i
=0; i
<16; i
++) {
166 buff
[i
] = ((uint)(inputBuffer
[inputOffset
+4*i
]) << 24)
167 | ((uint)(inputBuffer
[inputOffset
+4*i
+1]) << 16)
168 | ((uint)(inputBuffer
[inputOffset
+4*i
+2]) << 8)
169 | ((uint)(inputBuffer
[inputOffset
+4*i
+3]));
173 for (i
=16; i
<64; i
++) {
174 buff
[i
] = Ro1(buff
[i
-2]) + buff
[i
-7] + Ro0(buff
[i
-15]) + buff
[i
-16];
186 for (i
=0; i
<64; i
++) {
187 t1
= h
+ Sig1(e
) + Ch(e
,f
,g
) + SHAConstants
.K1
[i
] + buff
[i
];
188 t2
= Sig0(a
) + Maj(a
,b
,c
);
209 private void ProcessFinalBlock (byte[] inputBuffer
, int inputOffset
, int inputCount
)
216 paddingSize
= (int)(56 - (inputCount
+ count
) % BLOCK_SIZE_BYTES
);
219 paddingSize
+= BLOCK_SIZE_BYTES
;
221 fooBuffer
= new byte[inputCount
+paddingSize
+8];
223 for (i
=0; i
<inputCount
; i
++) {
224 fooBuffer
[i
] = inputBuffer
[i
+inputOffset
];
227 fooBuffer
[inputCount
] = 0x80;
228 for (i
=inputCount
+1; i
<inputCount
+paddingSize
; i
++) {
232 size
= (uint)(count
+inputCount
);
235 fooBuffer
[inputCount
+paddingSize
] = 0x00;
236 fooBuffer
[inputCount
+paddingSize
+1] = 0x00;
237 fooBuffer
[inputCount
+paddingSize
+2] = 0x00;
238 fooBuffer
[inputCount
+paddingSize
+3] = 0x00;
240 fooBuffer
[inputCount
+paddingSize
+4] = (byte)((size
) >> 24);
241 fooBuffer
[inputCount
+paddingSize
+5] = (byte)((size
) >> 16);
242 fooBuffer
[inputCount
+paddingSize
+6] = (byte)((size
) >> 8);
243 fooBuffer
[inputCount
+paddingSize
+7] = (byte)((size
) >> 0);
245 ProcessBlock(fooBuffer
, 0);
247 if (inputCount
+paddingSize
+8 == 128) {
248 ProcessBlock(fooBuffer
, 64);