2 // System.Security.Cryptography.SHA256Managed.cs
5 // Matthew S. Ford (Matthew.S.Ford@Rose-Hulman.Edu)
8 // Copyright (C) 2004, 2005 Novell, Inc (http://www.novell.com)
10 // Permission is hereby granted, free of charge, to any person obtaining
11 // a copy of this software and associated documentation files (the
12 // "Software"), to deal in the Software without restriction, including
13 // without limitation the rights to use, copy, modify, merge, publish,
14 // distribute, sublicense, and/or sell copies of the Software, and to
15 // permit persons to whom the Software is furnished to do so, subject to
16 // the following conditions:
18 // The above copyright notice and this permission notice shall be
19 // included in all copies or substantial portions of the Software.
21 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 using System
.Runtime
.InteropServices
;
32 namespace System
.Security
.Cryptography
{
35 public class SHA256Managed
: SHA256
{
37 private const int BLOCK_SIZE_BYTES
= 64;
40 private byte[] _ProcessingBuffer
; // Used to start data when passed less than a block worth.
41 private int _ProcessingBufferCount
; // Counts how much data we have stored that still needs processed.
44 public SHA256Managed ()
47 _ProcessingBuffer
= new byte [BLOCK_SIZE_BYTES
];
52 protected override void HashCore (byte[] rgb
, int ibStart
, int cbSize
)
57 if (_ProcessingBufferCount
!= 0) {
58 if (cbSize
< (BLOCK_SIZE_BYTES
- _ProcessingBufferCount
)) {
59 System
.Buffer
.BlockCopy (rgb
, ibStart
, _ProcessingBuffer
, _ProcessingBufferCount
, cbSize
);
60 _ProcessingBufferCount
+= cbSize
;
64 i
= (BLOCK_SIZE_BYTES
- _ProcessingBufferCount
);
65 System
.Buffer
.BlockCopy (rgb
, ibStart
, _ProcessingBuffer
, _ProcessingBufferCount
, i
);
66 ProcessBlock (_ProcessingBuffer
, 0);
67 _ProcessingBufferCount
= 0;
73 for (i
= 0; i
< cbSize
- cbSize
% BLOCK_SIZE_BYTES
; i
+= BLOCK_SIZE_BYTES
) {
74 ProcessBlock (rgb
, ibStart
+ i
);
77 if (cbSize
% BLOCK_SIZE_BYTES
!= 0) {
78 System
.Buffer
.BlockCopy (rgb
, cbSize
- cbSize
% BLOCK_SIZE_BYTES
+ ibStart
, _ProcessingBuffer
, 0, cbSize
% BLOCK_SIZE_BYTES
);
79 _ProcessingBufferCount
= cbSize
% BLOCK_SIZE_BYTES
;
83 protected override byte[] HashFinal ()
85 byte[] hash
= new byte[32];
88 ProcessFinalBlock (_ProcessingBuffer
, 0, _ProcessingBufferCount
);
92 hash
[i
*4+j
] = (byte)(_H
[i
] >> (24-j
*8));
100 public override void Initialize ()
103 _ProcessingBufferCount
= 0;
115 private void ProcessBlock (byte[] inputBuffer
, int inputOffset
)
117 uint a
, b
, c
, d
, e
, f
, g
, h
;
120 uint[] K1
= SHAConstants
.K1
;
121 uint[] buff
= this.buff
;
123 count
+= BLOCK_SIZE_BYTES
;
125 for (i
=0; i
<16; i
++) {
126 buff
[i
] = (uint)(((inputBuffer
[inputOffset
+ 4 * i
]) << 24)
127 | ((inputBuffer
[inputOffset
+ 4 * i
+ 1]) << 16)
128 | ((inputBuffer
[inputOffset
+ 4 * i
+ 2]) << 8)
129 | ((inputBuffer
[inputOffset
+ 4 * i
+ 3])));
133 for (i
=16; i
<64; i
++) {
135 t1
= (((t1
>> 7) | (t1
<< 25)) ^
((t1
>> 18) | (t1
<< 14)) ^
(t1
>> 3));
138 t2
= (((t2
>> 17) | (t2
<< 15)) ^
((t2
>> 19) | (t2
<< 13)) ^
(t2
>> 10));
139 buff
[i
] = t2
+ buff
[i
- 7] + t1
+ buff
[i
- 16];
151 for (i
=0; i
<64; i
++) {
152 t1
= h
+ (((e
>> 6) | (e
<< 26)) ^
((e
>> 11) | (e
<< 21)) ^
((e
>> 25) | (e
<< 7))) + ((e
& f
) ^
(~e
& g
)) + K1
[i
] + buff
[i
];
154 t2
= (((a
>> 2) | (a
<< 30)) ^
((a
>> 13) | (a
<< 19)) ^
((a
>> 22) | (a
<< 10)));
155 t2
= t2
+ ((a
& b
) ^
(a
& c
) ^
(b
& c
));
176 private void ProcessFinalBlock (byte[] inputBuffer
, int inputOffset
, int inputCount
)
178 ulong total
= count
+ (ulong)inputCount
;
179 int paddingSize
= (56 - (int)(total
% BLOCK_SIZE_BYTES
));
182 paddingSize
+= BLOCK_SIZE_BYTES
;
184 byte[] fooBuffer
= new byte[inputCount
+paddingSize
+8];
186 for (int i
=0; i
<inputCount
; i
++) {
187 fooBuffer
[i
] = inputBuffer
[i
+inputOffset
];
190 fooBuffer
[inputCount
] = 0x80;
191 for (int i
=inputCount
+1; i
<inputCount
+paddingSize
; i
++) {
195 // I deal in bytes. The algorithm deals in bits.
196 ulong size
= total
<< 3;
197 AddLength (size
, fooBuffer
, inputCount
+paddingSize
);
198 ProcessBlock (fooBuffer
, 0);
200 if (inputCount
+paddingSize
+8 == 128) {
201 ProcessBlock(fooBuffer
, 64);
205 internal void AddLength (ulong length
, byte[] buffer
, int position
)
207 buffer
[position
++] = (byte)(length
>> 56);
208 buffer
[position
++] = (byte)(length
>> 48);
209 buffer
[position
++] = (byte)(length
>> 40);
210 buffer
[position
++] = (byte)(length
>> 32);
211 buffer
[position
++] = (byte)(length
>> 24);
212 buffer
[position
++] = (byte)(length
>> 16);
213 buffer
[position
++] = (byte)(length
>> 8);
214 buffer
[position
] = (byte)(length
);