2010-04-07 Jb Evain <jbevain@novell.com>
[mcs.git] / class / corlib / System.Security.Cryptography / SHA256Managed.cs
blob9f4c2b85ad8dfd1d9c3557ce1e95bda4fb1abc8c
1 //
2 // System.Security.Cryptography.SHA256Managed.cs
3 //
4 // Author:
5 // Matthew S. Ford (Matthew.S.Ford@Rose-Hulman.Edu)
6 //
7 // (C) 2001
8 // Copyright (C) 2004, 2005 Novell, Inc (http://www.novell.com)
9 //
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:
17 //
18 // The above copyright notice and this permission notice shall be
19 // included in all copies or substantial portions of the Software.
20 //
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 {
34 [ComVisible (true)]
35 public class SHA256Managed : SHA256 {
37 private const int BLOCK_SIZE_BYTES = 64;
38 private uint[] _H;
39 private ulong count;
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.
42 private uint[] buff;
44 public SHA256Managed ()
46 _H = new uint [8];
47 _ProcessingBuffer = new byte [BLOCK_SIZE_BYTES];
48 buff = new uint[64];
49 Initialize ();
52 protected override void HashCore (byte[] rgb, int ibStart, int cbSize)
54 int i;
55 State = 1;
57 if (_ProcessingBufferCount != 0) {
58 if (cbSize < (BLOCK_SIZE_BYTES - _ProcessingBufferCount)) {
59 System.Buffer.BlockCopy (rgb, ibStart, _ProcessingBuffer, _ProcessingBufferCount, cbSize);
60 _ProcessingBufferCount += cbSize;
61 return;
63 else {
64 i = (BLOCK_SIZE_BYTES - _ProcessingBufferCount);
65 System.Buffer.BlockCopy (rgb, ibStart, _ProcessingBuffer, _ProcessingBufferCount, i);
66 ProcessBlock (_ProcessingBuffer, 0);
67 _ProcessingBufferCount = 0;
68 ibStart += i;
69 cbSize -= i;
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];
86 int i, j;
88 ProcessFinalBlock (_ProcessingBuffer, 0, _ProcessingBufferCount);
90 for (i=0; i<8; i++) {
91 for (j=0; j<4; j++) {
92 hash[i*4+j] = (byte)(_H[i] >> (24-j*8));
96 State = 0;
97 return hash;
100 public override void Initialize ()
102 count = 0;
103 _ProcessingBufferCount = 0;
105 _H[0] = 0x6A09E667;
106 _H[1] = 0xBB67AE85;
107 _H[2] = 0x3C6EF372;
108 _H[3] = 0xA54FF53A;
109 _H[4] = 0x510E527F;
110 _H[5] = 0x9B05688C;
111 _H[6] = 0x1F83D9AB;
112 _H[7] = 0x5BE0CD19;
115 private void ProcessBlock (byte[] inputBuffer, int inputOffset)
117 uint a, b, c, d, e, f, g, h;
118 uint t1, t2;
119 int i;
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++) {
134 t1 = buff[i - 15];
135 t1 = (((t1 >> 7) | (t1 << 25)) ^ ((t1 >> 18) | (t1 << 14)) ^ (t1 >> 3));
137 t2 = buff[i - 2];
138 t2 = (((t2 >> 17) | (t2 << 15)) ^ ((t2 >> 19) | (t2 << 13)) ^ (t2 >> 10));
139 buff[i] = t2 + buff[i - 7] + t1 + buff[i - 16];
142 a = _H[0];
143 b = _H[1];
144 c = _H[2];
145 d = _H[3];
146 e = _H[4];
147 f = _H[5];
148 g = _H[6];
149 h = _H[7];
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));
156 h = g;
157 g = f;
158 f = e;
159 e = d + t1;
160 d = c;
161 c = b;
162 b = a;
163 a = t1 + t2;
166 _H[0] += a;
167 _H[1] += b;
168 _H[2] += c;
169 _H[3] += d;
170 _H[4] += e;
171 _H[5] += f;
172 _H[6] += g;
173 _H[7] += h;
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));
181 if (paddingSize < 1)
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++) {
192 fooBuffer[i] = 0x00;
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);