4
// James Willcox <snorp@snorp.net>
6
// Copyright (C) 2005 James Willcox <snorp@snorp.net>
8
// This library is free software; you can redistribute it and/or
9
// modify it under the terms of the GNU Lesser General Public
10
// License as published by the Free Software Foundation; either
11
// version 2.1 of the License, or (at your option) any later version.
13
// This library is distributed in the hope that it will be useful,
14
// but WITHOUT ANY WARRANTY; without even the implied warranty of
15
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16
// Lesser General Public License for more details.
18
// You should have received a copy of the GNU Lesser General Public
19
// License along with this library; if not, write to the Free Software
20
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23
// BrokenMD5 Class implementation
26
// Matthew S. Ford (Matthew.S.Ford@Rose-Hulman.Edu)
27
// Sebastien Pouliot (sebastien@ximian.com)
28
// Jon Lech Johansen (jon@nanocrew.net)
30
// Copyright 2001 by Matthew S. Ford.
31
// Copyright (C) 2004-2005 Novell, Inc (http://www.novell.com)
33
// Permission is hereby granted, free of charge, to any person obtaining
34
// a copy of this software and associated documentation files (the
35
// "Software"), to deal in the Software without restriction, including
36
// without limitation the rights to use, copy, modify, merge, publish,
37
// distribute, sublicense, and/or sell copies of the Software, and to
38
// permit persons to whom the Software is furnished to do so, subject to
39
// the following conditions:
41
// The above copyright notice and this permission notice shall be
42
// included in all copies or substantial portions of the Software.
44
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
45
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
46
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
47
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
48
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
49
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
50
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
54
using System.Runtime.InteropServices;
55
using System.Security.Cryptography;
59
internal class BrokenMD5 : MD5 {
60
private const int BLOCK_SIZE_BYTES = 64;
61
private const int HASH_SIZE_BYTES = 16;
65
private byte [] _ProcessingBuffer; // Used to start data when passed less than a block worth.
66
private int _ProcessingBufferCount; // Counts how much data we have stored that still needs processed.
69
public BrokenMD5 ( int version )
73
_ProcessingBuffer = new byte [BLOCK_SIZE_BYTES];
84
protected override void Dispose (bool disposing)
86
if (_ProcessingBuffer != null) {
87
Array.Clear (_ProcessingBuffer, 0, _ProcessingBuffer.Length);
88
_ProcessingBuffer = null;
91
Array.Clear (_H, 0, _H.Length);
95
Array.Clear (buff, 0, buff.Length);
100
protected override void HashCore (byte [] rgb, int start, int size)
105
if (_ProcessingBufferCount != 0) {
106
if (size < (BLOCK_SIZE_BYTES - _ProcessingBufferCount)) {
107
System.Buffer.BlockCopy (rgb, start, _ProcessingBuffer, _ProcessingBufferCount, size);
108
_ProcessingBufferCount += size;
112
i = (BLOCK_SIZE_BYTES - _ProcessingBufferCount);
113
System.Buffer.BlockCopy (rgb, start, _ProcessingBuffer, _ProcessingBufferCount, i);
114
ProcessBlock (_ProcessingBuffer, 0);
115
_ProcessingBufferCount = 0;
121
for (i=0; i<size-size%BLOCK_SIZE_BYTES; i += BLOCK_SIZE_BYTES) {
122
ProcessBlock (rgb, start+i);
125
if (size%BLOCK_SIZE_BYTES != 0) {
126
System.Buffer.BlockCopy (rgb, size-size%BLOCK_SIZE_BYTES+start, _ProcessingBuffer, 0, size%BLOCK_SIZE_BYTES);
127
_ProcessingBufferCount = size%BLOCK_SIZE_BYTES;
131
protected override byte [] HashFinal ()
133
byte [] hash = new byte [16];
136
ProcessFinalBlock (_ProcessingBuffer, 0, _ProcessingBufferCount);
138
for (i=0; i<4; i++) {
139
for (j=0; j<4; j++) {
140
hash [i*4+j] = (byte) (_H [i] >> j*8);
147
public override void Initialize ()
150
_ProcessingBufferCount = 0;
158
private void ProcessBlock (byte [] inputBuffer, int inputOffset)
163
count += BLOCK_SIZE_BYTES;
165
for (i=0; i<16; i++) {
166
buff [i] = (uint) (inputBuffer [inputOffset+4*i])
167
| ( ( (uint) (inputBuffer [inputOffset+4*i+1])) << 8)
168
| ( ( (uint) (inputBuffer [inputOffset+4*i+2])) << 16)
169
| ( ( (uint) (inputBuffer [inputOffset+4*i+3])) << 24);
177
// This function was unrolled because it seems to be doubling our performance with current compiler/VM.
178
// Possibly roll up if this changes.
180
// ---- Round 1 --------
182
a += ( ( (c ^ d) & b) ^ d) + (uint) K [0] + buff [0];
183
a = (a << 7) | (a >> 25);
186
d += ( ( (b ^ c) & a) ^ c) + (uint) K [1] + buff [1];
187
d = (d << 12) | (d >> 20);
190
c += ( ( (a ^ b) & d) ^ b) + (uint) K [2] + buff [2];
191
c = (c << 17) | (c >> 15);
194
b += ( ( (d ^ a) & c) ^ a) + (uint) K [3] + buff [3];
195
b = (b << 22) | (b >> 10);
198
a += ( ( (c ^ d) & b) ^ d) + (uint) K [4] + buff [4];
199
a = (a << 7) | (a >> 25);
202
d += ( ( (b ^ c) & a) ^ c) + (uint) K [5] + buff [5];
203
d = (d << 12) | (d >> 20);
206
c += ( ( (a ^ b) & d) ^ b) + (uint) K [6] + buff [6];
207
c = (c << 17) | (c >> 15);
210
b += ( ( (d ^ a) & c) ^ a) + (uint) K [7] + buff [7];
211
b = (b << 22) | (b >> 10);
214
a += ( ( (c ^ d) & b) ^ d) + (uint) K [8] + buff [8];
215
a = (a << 7) | (a >> 25);
218
d += ( ( (b ^ c) & a) ^ c) + (uint) K [9] + buff [9];
219
d = (d << 12) | (d >> 20);
222
c += ( ( (a ^ b) & d) ^ b) + (uint) K [10] + buff [10];
223
c = (c << 17) | (c >> 15);
226
b += ( ( (d ^ a) & c) ^ a) + (uint) K [11] + buff [11];
227
b = (b << 22) | (b >> 10);
230
a += ( ( (c ^ d) & b) ^ d) + (uint) K [12] + buff [12];
231
a = (a << 7) | (a >> 25);
234
d += ( ( (b ^ c) & a) ^ c) + (uint) K [13] + buff [13];
235
d = (d << 12) | (d >> 20);
238
c += ( ( (a ^ b) & d) ^ b) + (uint) K [14] + buff [14];
239
c = (c << 17) | (c >> 15);
242
b += ( ( (d ^ a) & c) ^ a) + (uint) K [15] + buff [15];
243
b = (b << 22) | (b >> 10);
247
// ---- Round 2 --------
249
a += ( ( (b ^ c) & d) ^ c) + (uint) K [16] + buff [1];
250
a = (a << 5) | (a >> 27);
253
d += ( ( (a ^ b) & c) ^ b) + (uint) K [17] + buff [6];
254
d = (d << 9) | (d >> 23);
257
c += ( ( (d ^ a) & b) ^ a) + (uint) K [18] + buff [11];
258
c = (c << 14) | (c >> 18);
261
b += ( ( (c ^ d) & a) ^ d) + (uint) K [19] + buff [0];
262
b = (b << 20) | (b >> 12);
265
a += ( ( (b ^ c) & d) ^ c) + (uint) K [20] + buff [5];
266
a = (a << 5) | (a >> 27);
269
d += ( ( (a ^ b) & c) ^ b) + (uint) K [21] + buff [10];
270
d = (d << 9) | (d >> 23);
273
c += ( ( (d ^ a) & b) ^ a) + (uint) K [22] + buff [15];
274
c = (c << 14) | (c >> 18);
277
b += ( ( (c ^ d) & a) ^ d) + (uint) K [23] + buff [4];
278
b = (b << 20) | (b >> 12);
281
a += ( ( (b ^ c) & d) ^ c) + (uint) K [24] + buff [9];
282
a = (a << 5) | (a >> 27);
285
d += ( ( (a ^ b) & c) ^ b) + (uint) K [25] + buff [14];
286
d = (d << 9) | (d >> 23);
289
c += ( ( (d ^ a) & b) ^ a) + (uint) K [26] + buff [3];
290
c = (c << 14) | (c >> 18);
295
b += ( ( (c ^ d) & a) ^ d) + (uint) 0x445a14ed + buff [8];
296
b = (b << 20) | (b >> 12);
301
b += ( ( (c ^ d) & a) ^ d) + (uint) K [27] + buff [8];
302
b = (b << 20) | (b >> 12);
306
a += ( ( (b ^ c) & d) ^ c) + (uint) K [28] + buff [13];
307
a = (a << 5) | (a >> 27);
310
d += ( ( (a ^ b) & c) ^ b) + (uint) K [29] + buff [2];
311
d = (d << 9) | (d >> 23);
314
c += ( ( (d ^ a) & b) ^ a) + (uint) K [30] + buff [7];
315
c = (c << 14) | (c >> 18);
318
b += ( ( (c ^ d) & a) ^ d) + (uint) K [31] + buff [12];
319
b = (b << 20) | (b >> 12);
323
// ---- Round 3 --------
325
a += (b ^ c ^ d) + (uint) K [32] + buff [5];
326
a = (a << 4) | (a >> 28);
329
d += (a ^ b ^ c) + (uint) K [33] + buff [8];
330
d = (d << 11) | (d >> 21);
333
c += (d ^ a ^ b) + (uint) K [34] + buff [11];
334
c = (c << 16) | (c >> 16);
337
b += (c ^ d ^ a) + (uint) K [35] + buff [14];
338
b = (b << 23) | (b >> 9);
341
a += (b ^ c ^ d) + (uint) K [36] + buff [1];
342
a = (a << 4) | (a >> 28);
345
d += (a ^ b ^ c) + (uint) K [37] + buff [4];
346
d = (d << 11) | (d >> 21);
349
c += (d ^ a ^ b) + (uint) K [38] + buff [7];
350
c = (c << 16) | (c >> 16);
353
b += (c ^ d ^ a) + (uint) K [39] + buff [10];
354
b = (b << 23) | (b >> 9);
357
a += (b ^ c ^ d) + (uint) K [40] + buff [13];
358
a = (a << 4) | (a >> 28);
361
d += (a ^ b ^ c) + (uint) K [41] + buff [0];
362
d = (d << 11) | (d >> 21);
365
c += (d ^ a ^ b) + (uint) K [42] + buff [3];
366
c = (c << 16) | (c >> 16);
369
b += (c ^ d ^ a) + (uint) K [43] + buff [6];
370
b = (b << 23) | (b >> 9);
373
a += (b ^ c ^ d) + (uint) K [44] + buff [9];
374
a = (a << 4) | (a >> 28);
377
d += (a ^ b ^ c) + (uint) K [45] + buff [12];
378
d = (d << 11) | (d >> 21);
381
c += (d ^ a ^ b) + (uint) K [46] + buff [15];
382
c = (c << 16) | (c >> 16);
385
b += (c ^ d ^ a) + (uint) K [47] + buff [2];
386
b = (b << 23) | (b >> 9);
390
// ---- Round 4 --------
392
a += ( ( (~d) | b) ^ c) + (uint) K [48] + buff [0];
393
a = (a << 6) | (a >> 26);
396
d += ( ( (~c) | a) ^ b) + (uint) K [49] + buff [7];
397
d = (d << 10) | (d >> 22);
400
c += ( ( (~b) | d) ^ a) + (uint) K [50] + buff [14];
401
c = (c << 15) | (c >> 17);
404
b += ( ( (~a) | c) ^ d) + (uint) K [51] + buff [5];
405
b = (b << 21) | (b >> 11);
408
a += ( ( (~d) | b) ^ c) + (uint) K [52] + buff [12];
409
a = (a << 6) | (a >> 26);
412
d += ( ( (~c) | a) ^ b) + (uint) K [53] + buff [3];
413
d = (d << 10) | (d >> 22);
416
c += ( ( (~b) | d) ^ a) + (uint) K [54] + buff [10];
417
c = (c << 15) | (c >> 17);
420
b += ( ( (~a) | c) ^ d) + (uint) K [55] + buff [1];
421
b = (b << 21) | (b >> 11);
424
a += ( ( (~d) | b) ^ c) + (uint) K [56] + buff [8];
425
a = (a << 6) | (a >> 26);
428
d += ( ( (~c) | a) ^ b) + (uint) K [57] + buff [15];
429
d = (d << 10) | (d >> 22);
432
c += ( ( (~b) | d) ^ a) + (uint) K [58] + buff [6];
433
c = (c << 15) | (c >> 17);
436
b += ( ( (~a) | c) ^ d) + (uint) K [59] + buff [13];
437
b = (b << 21) | (b >> 11);
440
a += ( ( (~d) | b) ^ c) + (uint) K [60] + buff [4];
441
a = (a << 6) | (a >> 26);
444
d += ( ( (~c) | a) ^ b) + (uint) K [61] + buff [11];
445
d = (d << 10) | (d >> 22);
448
c += ( ( (~b) | d) ^ a) + (uint) K [62] + buff [2];
449
c = (c << 15) | (c >> 17);
452
b += ( ( (~a) | c) ^ d) + (uint) K [63] + buff [9];
453
b = (b << 21) | (b >> 11);
462
private void ProcessFinalBlock (byte [] inputBuffer, int inputOffset, int inputCount)
464
ulong total = count + (ulong)inputCount;
465
int paddingSize = (int) (56 - total % BLOCK_SIZE_BYTES);
468
paddingSize += BLOCK_SIZE_BYTES;
470
byte [] fooBuffer = new byte [inputCount+paddingSize+8];
472
for (int i=0; i<inputCount; i++) {
473
fooBuffer [i] = inputBuffer [i+inputOffset];
476
fooBuffer [inputCount] = 0x80;
477
for (int i=inputCount+1; i<inputCount+paddingSize; i++) {
478
fooBuffer [i] = 0x00;
481
// I deal in bytes. The algorithm deals in bits.
482
ulong size = total << 3;
483
AddLength (size, fooBuffer, inputCount+paddingSize);
484
ProcessBlock (fooBuffer, 0);
486
if (inputCount+paddingSize+8 == 128) {
487
ProcessBlock (fooBuffer, 64);
491
internal void AddLength (ulong length, byte [] buffer, int position)
493
buffer [position++] = (byte) (length);
494
buffer [position++] = (byte) (length >> 8);
495
buffer [position++] = (byte) (length >> 16);
496
buffer [position++] = (byte) (length >> 24);
497
buffer [position++] = (byte) (length >> 32);
498
buffer [position++] = (byte) (length >> 40);
499
buffer [position++] = (byte) (length >> 48);
500
buffer [position] = (byte) (length >> 56);
503
private readonly static uint [] K = {
504
0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee,
505
0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
506
0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,
507
0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,
508
0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa,
509
0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8,
510
0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed,
511
0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a,
512
0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c,
513
0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
514
0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05,
515
0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,
516
0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039,
517
0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
518
0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
519
0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391