2 // Mono.Security.Cryptography SHA224 class implementation
3 // based on SHA256Managed class implementation (mscorlib.dll)
6 // Matthew S. Ford (Matthew.S.Ford@Rose-Hulman.Edu)
7 // Sebastien Pouliot <sebastien@ximian.com>
10 // Copyright (C) 2004-2005 Novell, Inc (http://www.novell.com)
12 // Permission is hereby granted, free of charge, to any person obtaining
13 // a copy of this software and associated documentation files (the
14 // "Software"), to deal in the Software without restriction, including
15 // without limitation the rights to use, copy, modify, merge, publish,
16 // distribute, sublicense, and/or sell copies of the Software, and to
17 // permit persons to whom the Software is furnished to do so, subject to
18 // the following conditions:
20 // The above copyright notice and this permission notice shall be
21 // included in all copies or substantial portions of the Software.
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
27 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
28 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
29 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32 using System
.Security
.Cryptography
;
34 namespace Mono
.Security
.Cryptography
{
36 public class SHA224Managed
: SHA224
{
38 private const int BLOCK_SIZE_BYTES
= 64;
42 private byte[] _ProcessingBuffer
; // Used to start data when passed less than a block worth.
43 private int _ProcessingBufferCount
; // Counts how much data we have stored that still needs processed.
45 public SHA224Managed ()
48 _ProcessingBuffer
= new byte [BLOCK_SIZE_BYTES
];
52 private uint Ch (uint u
, uint v
, uint w
)
54 return (u
&v
) ^
(~u
&w
);
57 private uint Maj (uint u
, uint v
, uint w
)
59 return (u
&v
) ^
(u
&w
) ^
(v
&w
);
62 private uint Ro0 (uint x
)
64 return ((x
>> 7) | (x
<< 25))
65 ^
((x
>> 18) | (x
<< 14))
69 private uint Ro1 (uint x
)
71 return ((x
>> 17) | (x
<< 15))
72 ^
((x
>> 19) | (x
<< 13))
76 private uint Sig0 (uint x
)
78 return ((x
>> 2) | (x
<< 30))
79 ^
((x
>> 13) | (x
<< 19))
80 ^
((x
>> 22) | (x
<< 10));
83 private uint Sig1 (uint x
)
85 return ((x
>> 6) | (x
<< 26))
86 ^
((x
>> 11) | (x
<< 21))
87 ^
((x
>> 25) | (x
<< 7));
90 protected override void HashCore (byte[] rgb
, int start
, int size
)
95 if (_ProcessingBufferCount
!= 0) {
96 if (size
< (BLOCK_SIZE_BYTES
- _ProcessingBufferCount
)) {
97 System
.Buffer
.BlockCopy (rgb
, start
, _ProcessingBuffer
, _ProcessingBufferCount
, size
);
98 _ProcessingBufferCount
+= size
;
102 i
= (BLOCK_SIZE_BYTES
- _ProcessingBufferCount
);
103 System
.Buffer
.BlockCopy (rgb
, start
, _ProcessingBuffer
, _ProcessingBufferCount
, i
);
104 ProcessBlock (_ProcessingBuffer
, 0);
105 _ProcessingBufferCount
= 0;
111 for (i
=0; i
<size
-size
%BLOCK_SIZE_BYTES
; i
+= BLOCK_SIZE_BYTES
) {
112 ProcessBlock (rgb
, start
+i
);
115 if (size
%BLOCK_SIZE_BYTES
!= 0) {
116 System
.Buffer
.BlockCopy (rgb
, size
-size
%BLOCK_SIZE_BYTES
+start
, _ProcessingBuffer
, 0, size
%BLOCK_SIZE_BYTES
);
117 _ProcessingBufferCount
= size
%BLOCK_SIZE_BYTES
;
121 protected override byte[] HashFinal ()
123 byte[] hash
= new byte[28];
126 ProcessFinalBlock (_ProcessingBuffer
, 0, _ProcessingBufferCount
);
128 for (i
=0; i
<7; i
++) {
129 for (j
=0; j
<4; j
++) {
130 hash
[i
*4+j
] = (byte)(_H
[i
] >> (24-j
*8));
138 public override void Initialize ()
141 _ProcessingBufferCount
= 0;
153 private void ProcessBlock (byte[] inputBuffer
, int inputOffset
)
155 uint a
, b
, c
, d
, e
, f
, g
, h
;
160 count
+= BLOCK_SIZE_BYTES
;
164 for (i
=0; i
<16; i
++) {
165 buff
[i
] = ((uint)(inputBuffer
[inputOffset
+4*i
]) << 24)
166 | ((uint)(inputBuffer
[inputOffset
+4*i
+1]) << 16)
167 | ((uint)(inputBuffer
[inputOffset
+4*i
+2]) << 8)
168 | ((uint)(inputBuffer
[inputOffset
+4*i
+3]));
172 for (i
=16; i
<64; i
++) {
173 buff
[i
] = Ro1(buff
[i
-2]) + buff
[i
-7] + Ro0(buff
[i
-15]) + buff
[i
-16];
185 for (i
=0; i
<64; i
++) {
186 t1
= h
+ Sig1(e
) + Ch(e
,f
,g
) + SHAConstants
.K1
[i
] + buff
[i
];
187 t2
= Sig0(a
) + Maj(a
,b
,c
);
208 private void ProcessFinalBlock (byte[] inputBuffer
, int inputOffset
, int inputCount
)
210 ulong total
= count
+ (ulong)inputCount
;
211 int paddingSize
= (56 - (int)(total
% BLOCK_SIZE_BYTES
));
214 paddingSize
+= BLOCK_SIZE_BYTES
;
216 byte[] fooBuffer
= new byte[inputCount
+paddingSize
+8];
218 for (int i
=0; i
<inputCount
; i
++) {
219 fooBuffer
[i
] = inputBuffer
[i
+inputOffset
];
222 fooBuffer
[inputCount
] = 0x80;
223 for (int i
=inputCount
+1; i
<inputCount
+paddingSize
; i
++) {
227 // I deal in bytes. The algorithm deals in bits.
228 ulong size
= total
<< 3;
229 AddLength (size
, fooBuffer
, inputCount
+paddingSize
);
230 ProcessBlock (fooBuffer
, 0);
232 if (inputCount
+paddingSize
+8 == 128) {
233 ProcessBlock(fooBuffer
, 64);
237 internal void AddLength (ulong length
, byte[] buffer
, int position
)
239 buffer
[position
++] = (byte)(length
>> 56);
240 buffer
[position
++] = (byte)(length
>> 48);
241 buffer
[position
++] = (byte)(length
>> 40);
242 buffer
[position
++] = (byte)(length
>> 32);
243 buffer
[position
++] = (byte)(length
>> 24);
244 buffer
[position
++] = (byte)(length
>> 16);
245 buffer
[position
++] = (byte)(length
>> 8);
246 buffer
[position
] = (byte)(length
);