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 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;
39 private const int HASH_SIZE_BYTES
= 32;
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
)
215 paddingSize
= (int)(56 - (inputCount
+ count
) % BLOCK_SIZE_BYTES
);
218 paddingSize
+= BLOCK_SIZE_BYTES
;
220 fooBuffer
= new byte[inputCount
+paddingSize
+8];
222 for (i
=0; i
<inputCount
; i
++) {
223 fooBuffer
[i
] = inputBuffer
[i
+inputOffset
];
226 fooBuffer
[inputCount
] = 0x80;
227 for (i
=inputCount
+1; i
<inputCount
+paddingSize
; i
++) {
231 size
= (uint)(count
+inputCount
);
234 fooBuffer
[inputCount
+paddingSize
] = 0x00;
235 fooBuffer
[inputCount
+paddingSize
+1] = 0x00;
236 fooBuffer
[inputCount
+paddingSize
+2] = 0x00;
237 fooBuffer
[inputCount
+paddingSize
+3] = 0x00;
239 fooBuffer
[inputCount
+paddingSize
+4] = (byte)((size
) >> 24);
240 fooBuffer
[inputCount
+paddingSize
+5] = (byte)((size
) >> 16);
241 fooBuffer
[inputCount
+paddingSize
+6] = (byte)((size
) >> 8);
242 fooBuffer
[inputCount
+paddingSize
+7] = (byte)((size
) >> 0);
244 ProcessBlock(fooBuffer
, 0);
246 if (inputCount
+paddingSize
+8 == 128) {
247 ProcessBlock(fooBuffer
, 64);