The MD4 Class. (C #)

zhaozj2021-02-17  51

/ *

CopyRight 2002 Blood (Eaststarbuy@sina.com)

This Code is Ported from Norbert Hranitzky's

(Norbert.hranitzky@mchp.siemens.de)

Java Version.

* /

// Reference Namespace

Using system;

Using system.text;

Namespace blood.com.security

{

///

/// Implements the MD4 Message Digest Algorithm in C #

///

Public Class MD4

{

// MD4 Specific Object Variables

/ / -------------------------------------------------------------------------------------------- -----------------------

///

//// The size in bytes of the input block to the transformation algorithm

///

Private const Int block_length = 64; // = 512/8

///

/// 4 32-Bit Words (Interim Result)

///

Private uint [] context = new uint [4];

///

/// Number of Bytes Proced So Far Mod. 2 Power Of 64.

///

PRIVATE long count;

///

/// 512-bit infut buffer = 16 x 32-Bit Words Holds Until It Reaches 512 BITS

///

Private Byte [] buffer = new byte [block_length];

///

/// 512-bit work buffer = 16 x 32-Bit Words

///

Private uint [] x = new uint [16];

// conntructors

/ / -------------------------------------------------------------------------------------------- ---------------------------------------------------------------------------------------------------------------------------------------

Public MD4 ()

{

Engineeren ();

}

///

/// this constructor is here to mailment theclonability of this class

///

///

Private MD4 (MD4 MD): this ()

{

// this ();

CONTEXT = (uint []) md.context.clone ();

Buffer = (Byte []) md.buffer.clone ();

Count = md.count;

}

// Clonable Method Implementation

/ / -------------------------------------------------------------------------------------------- ------------------------- Public Object Clone ()

{

Return New MD4 (this);

}

// jce methods

/ / -------------------------------------------------------------------------------------------- -------------------------

///

/// Resets this Object Disregarding Any Temporary Data Present At The

/// Time of the Invocation of this Call.

///

Private void Engineeset ()

{

// Initial Values ​​of MD4 I.E. A, B, C, D

// AS Per RFC-1320; They Are Low-Order Byte First

CONTEXT [0] = 0x67452301;

Context [1] = 0xefcdab89;

Context [2] = 0x98badcfe;

CONTEXT [3] = 0x10325476;

Count = 0L;

For (int i = 0; i

{

Buffer [i] = 0;

}

}

///

/// Continues an MD4 Message Digest Using The Input Byte

///

/// byte to input

Private void EngineUpdate (byte b)

{

// compute number of bytes still unhased; ie. present in buffer

INT i = (int) (count% block_length);

Count ; // Update Number of Bytes

Buffer [i] = B;

IF (i == block_length - 1)

Transform (REF Buffer, 0);

}

///

/// md4 block update operation

///

///

/// Continues an MD4 Message Digest Operation by Filling The Buffer,

/// transform (ion) Data in 512-bit Message Block (s), Updating The Variables

/// context and count, and leaving (buffering) THE Remaining bytes in buffer

/// for the next update or finish.

///

/// Input block

/// Start of meaningful bytes in input

/// count of bytes in input blocok to consider private void EngineUpdate (byte [] Input, int offset, int LEN)

{

// Make Sure We don't Exceed Input's Allocated Size / Length

IF (Offset <0 || Len <0 || (long) Offset Len> Input.length)

{

Throw new argumentOutofrangeException ();

}

// compute number of bytes still unhased; ie. present in buffer

Int bufferndx = (int); COUNT% block_length

Count = le; // update number of bytes

INT Partlen = block_length - bufferndx;

INT i = 0;

IF (len> = partlen)

{

Array.copy (Input, Offset I, Buffer, Bufferndx, Partle);

Transform (REF Buffer, 0);

For (i = partlen; i block_length - 1

{

Transform (Ref INPUT, OFFSET I);

}

Bufferndx = 0;

}

// Buffer Remaining Input

IF (i

{

Array.copy (Input, Offset i, Buffer, Bufferndx, Len - i);

}

}

///

/// Completes the Hash Computation by Performing Final Operations Such

/// AS Padding. at the return of this engineDigest, The MD Engine IS

/// reset.

///

/// The array of bytes for the resulting hash value.

Private byte [] Enginedigest ()

{

// Pad Output to 56 MOD 64; AS RFC1320 PUTS IT: CONGRUENT TO 448 MOD 512

Int bufferndx = (int); COUNT% block_length

INT Padlen = (Bufferndx <56)? (56 - Bufferndx): (120 - Bufferndx);

//Padding is always binary 1 FOLLOWED by binary 0's

Byte [] tail = new byte [padlen 8];

Tail [0] = (Byte) 0x80;

// Append Length Before Final Transform

// Save Number of Bits, Casting the long to an array of 8 bytes

// Save low-order byte first.for (int i = 0; i <8; i )

{

TAIL [Padlen I] = (Byte) ((count * 8) >> (8 * i));

}

EngineUpdate (tail, 0, tail.length);

Byte [] result = new byte [16];

// Cast this MD4's Context (Array of 4 UINTS) Into an Array of 16 Bytes.

For (int i = 0; i <4; i )

{

For (int J = 0; j <4; j )

{

Result [i * 4 j] = (byte) (Context [i] >> (8 * j));

}

}

// reset the engine

Engineeren ();

Return Result;

}

///

/// Returns a byte hash from a string

///

/// String to Hash

/// Byte-array what contacts the hash

Public Byte [] getBytehashfromstring (String s)

{

Byte [] b = encoding.utf8.getbytes (s);

MD4 MD4 = New MD4 ();

Md4.EngineUpdate (B, 0, B.Length);

Return md4.enginedigest ();

}

///

/// Returns a binary hash from an input byte array

///

/// byte-array to hash

/// binary hash of infut

Public Byte [] getBytehashfrombytes (byte [] b)

{

MD4 MD4 = New MD4 ();

Md4.EngineUpdate (B, 0, B.Length);

Return md4.enginedigest ();

}

///

/// Returns a string That Contains the Hexadecimal Hash

///

/// byte-array to input

/// String That Contains The Hex of The Hash

Public string getHexhashfrombytes (byte [] b)

{

Byte [] E = getBytehashfrombytes (b);

Return Bytestohex (E, E.LENGTH);

}

///

/// Returns a byte hash from the input byte

///

/// byte to hash /// binary hash of the input byte

Public Byte [] getBytehashfrombyte (byte b)

{

MD4 MD4 = New MD4 ();

Md4.EngineUpdate (b);

Return md4.enginedigest ();

}

///

/// Returns a string That Contains the Hexadecimal Hash

///

/// byte to hash

/// String That Contains The Hex of The Hash

Public String GetHexhashfrombyte (Byte B)

{

Byte [] E = getBytehashfrombyte (b);

Return Bytestohex (E, E.LENGTH);

}

///

/// Returns a string That Contains the Hexadecimal Hash

///

/// String to Hash

/// String That Contains The Hex of The Hash

Public String GetHexHashfromstring (String S)

{

Byte [] b = getBytehashfromstring (s);

Return Bytestohex (B, B.Length);

}

Private static string bytestohex (byte [] a, int LEN)

{

String Temp = bitconverter.tostring (a);

// We need to remove the dashes That come from the bitconverter

Stringbuilder SB = New StringBuilder ((LEN - 2) / 2); // this sale be the final size

For (int i = 0; i

{

IF (Temp [I]! = '-')

{

Sb.append (Temp [i]);

}

}

Return sb.toString ();

}

// OWN Methods

/ / -------------------------------------------------------------------------------------------- -----------------------------------

///

/// md4 Basic Transformation

///

///

/// Transforms Context Based on 512 Bits from Input Block Starting

/// from the offset'th byte.

///

/// input sub-array /// Starting position of sub-array

Private Void Transform (Ref Byte [] block, int offset

{

// Decodes 64 bytes from Input Block Into An Array Of 16 32-bit

// Entities. Use a as a temp var.

For (int i = 0; i <16; i )

{

X [i] = ((uint) block [offset ] & 0xff) |

((uint) Block [Offset ] & 0xFF) << 8) |

((uint) Block [Offset ] & 0xFF) << 16) |

((uint) block [offset ] & 0xff) << 24);

}

Uint a = context [0];

uint b = context [1];

uint c = context [2];

Uint D = context [3];

A = ff (A, B, C, D, X [0], 3);

D = ff (D, A, B, C, X [1], 7);

C = ff (C, D, A, B, X [2], 11);

B = ff (B, C, D, A, X [3], 19);

A = ff (A, B, C, D, X [4], 3);

D = ff (D, A, B, C, X [5], 7);

C = ff (C, D, A, B, X [6], 11);

B = ff (B, C, D, A, X [7], 19);

A = ff (A, B, C, D, X [8], 3);

D = ff (D, A, B, C, X [9], 7);

C = ff (C, D, A, B, X [10], 11);

B = ff (B, C, D, A, X [11], 19);

A = ff (A, B, C, D, X [12], 3);

D = ff (D, A, B, C, X [13], 7);

C = ff (C, D, A, B, X [14], 11);

B = FF (B, C, D, A, X [15], 19);

A = GG (A, B, C, D, X [0], 3);

D = GG (D, A, B, C, X [4], 5);

C = GG (C, D, A, B, X [8], 9);

B = GG (B, C, D, A, X [12], 13);

A = GG (A, B, C, D, X [1], 3);

D = GG (D, A, B, C, X [5], 5);

C = GG (C, D, A, B, X [9], 9);

B = GG (B, C, D, A, X [13], 13);

A = GG (A, B, C, D, X [2], 3);

D = GG (D, A, B, C, X [6], 5);

C = GG (C, D, A, B, X [10], 9);

B = GG (B, C, D, A, X [14], 13);

A = GG (A, B, C, D, X [3], 3); D = GG (D, A, B, C, X [7], 5);

C = GG (C, D, A, B, X [11], 9);

B = GG (B, C, D, A, X [15], 13);

A = HH (A, B, C, D, X [0], 3);

D = HH (D, A, B, C, X [8], 9);

C = HH (C, D, A, B, X [4], 11);

B = HH (B, C, D, A, X [12], 15);

A = HH (A, B, C, D, X [2], 3);

D = HH (D, A, B, C, X [10], 9);

C = HH (C, D, A, B, X [6], 11);

B = HH (B, C, D, A, X [14], 15);

A = HH (A, B, C, D, X [1], 3);

D = HH (D, A, B, C, X [9], 9);

C = HH (C, D, A, B, X [5], 11);

B = HH (B, C, D, A, X [13], 15);

A = HH (A, B, C, D, X [3], 3);

D = HH (D, A, B, C, X [11], 9);

C = HH (C, D, A, B, X [7], 11);

B = HH (B, C, D, A, X [15], 15);

Context [0] = a;

Context [1] = B;

Context [2] = C;

Context [3] = D;

}

// The Basic MD4 Atomic Functions.

Private uint ff (uint a, uint B, uint C, uint D, uint x, int S)

{

UINT T = a ((B & C) | (~ B & D)) x;

Return T << S | T >> (32 - s);

}

Private uint GG (Uint A, Uint B, Uint C, Uint D, UINT X, INT S)

{

UINT T = a ((B & (C | D)) | (C & D)) x 0x5a827999;

Return T << S | T >> (32 - s);

}

Private uint HH (uint a, uint B, uint C, uint D, uint x, int S)

{

UINT T = A (B ^ c ^ D) x 0x6ed9eba1;

Return T << S | T >> (32 - s);

}

} // Class MD4

} // namespace blood.com.security

转载请注明原文地址:https://www.9cbs.com/read-29545.html

New Post(0)