MD5 algorithm Description of C # program MD5 algorithm

Source: Internet
Author: User
Tags define hash int size md5 numeric value string format
program | algorithm when I write a program of MD5 algorithm, I find that there are some inaccuracies in the English language description, some details
It's not clear, or very confusing. Finally have to come up with C language source program to debug, which is very not to understand the algorithm
Lee's. So I summed up some of the points I felt.

1. Origin
MD5 's full name is Message-digest algorithm 5 (Information-Digest algorithm, in the early 90 by MIT Laboratory
For the computer science and RSA Data Security Inc. Ronald L Rivest developed,
Developed by MD2, Md3 and MD4. Http://www.ietf.org/rfc/rfc1321.txt, is a most authoritative document,
Submitted to Ieft by Ronald L. Rivest in August 1992.

2. Use
The role of MD5 is to generate an information digest (message-digest) for a piece of information (message) that has
Uniqueness, which can be signed as a digital signature. Used to verify the validity of the file (whether there are any missing or corrupted data), the user
Encryption of a password that computes the hash value in a hash function.

3. Features
Enter a byte string of any length, generating a 128-bit integer. Due to some irreversible features of the algorithm, in the encryption application
have better security. Also, the use of the MD5 algorithm does not require any copyright fees to be paid.

4. Notes
Uniqueness and irreversibility are not absolute, theoretically analysis is a kind of many-to-many relationship, but two different information produce
The probability of the same summary is very small. Irreversible refers to the input from the output of the required computation and calculation time is too large, the use of poor search words
The code method needs too much storage space.

5. Algorithm description

The algorithm input is a byte string, each byte is 8 bit.
The execution of the algorithm is divided into the following steps:

The first step is to fill the position:
The MD5 algorithm first complements the input data so that the length of the data (in bytes) for 64 is 56.
That is, the data is extended to len=k*64+56 bytes, and K is an integer.
Complement method: Fill a 1, then fill 0 to meet the above requirements. Equivalent to a 0x80 byte, and then the complement value
is a byte of 0. The total number of bytes added in this step is 0~63.

Second step, append data length:
Represents the original length of the data (in bits) with a 64-bit integer, which places the 8 bytes of the number in the front,
The high order is appended to the back of the data after the complement. At this point, the total length of the data being filled is:
LEN = k*64+56+8= (k+1) *64 Bytes.

※ Note that the 64-bit integer is the original length of the input data rather than the length of the padding byte, I fell down here.

The third step is to initialize the MD5 parameter:
There are four 32-bit integer variables (a,b,c,d) used to compute the information digest, each of which is initialized to the following
numeric value in hexadecimal numbers, low byte in front.
Word a:01 23 45 67
Word b:89 AB CD EF
Word c:fe DC BA 98
Word d:76 54 32 10
※ Note that the lower byte in front refers to the arrangement of bytes in memory on the little endian platform,
While writing in a program, write:
a=0x67452301
B=0xefcdab89
C=0x98badcfe
d=0x10325476

The fourth step is to define four MD5 basic bitwise action FUNCTIONS:
X,y,z is a 32-bit integer.
F (x,y,z) = (x and Y) or (not (x) and Z)
G (x,y,z) = (X and z) or (Y and not (z))
H (x,y,z) = X xor Y xor Z
I (x,y,z) = Y xor (X or Not (Z))

Then define four functions that are used for four-wheel transforms respectively.
Set MJ to represent the first J subgroup of the message (0 to), <<<s indicates that the loop left s bit, then the four actions are:
FF (A,b,c,d,mj,s,ti) represents a=b+ ((A + (F (b,c,d) +mj+ti) <<<s)
GG (A,b,c,d,mj,s,ti) is a=b+ ((A + (G (b,c,d) +mj+ti) <<<s)
HH (A,b,c,d,mj,s,ti) represents a=b+ ((A + (b,c,d) +mj+ti) <<<s)
II (A,b,c,d,mj,s,ti) represents a=b+ ((A + (b,c,d) +mj+ti) <<<s)


The fifth step is to transform the input data.
Processing data, n is the total number of bytes, in 64 bytes as a group, each group for a loop, each cycle for four-wheel operation.
The 64 bytes to transform are m[0 with 16 32-bit integer arrays ... 15] says. and the array t[1 ... 64] Represents a set of constants,
T[i] is the 32-bit integer portion of the 4294967296*abs (sin (i)), the unit of I is radians, the value of I is from 1 to 64.
The specific process is as follows:

/* Set the main loop variable * *
For i = 0 to N/16-1 do

/* Each cycle, the original data stored in 16 elements of the array x. */
For j = 0 Todo
Set X[j] to m[i*16+j].
End/ending loop to J

/* Save A as AA, B as BB, C as CC, and D as DD.
*/
AA = A
BB = B
CC = C
DD = D

/* 1th Round * *
/* with [ABCD K S] to represent the following operations
A = B + ((A + F (b,c,d) + x[k] + t[i]) <<< s). */
/* Do the following operations. */
[ABCD 0 7 1] [DABC 1 12 2] [Cdab 2 17 3] [BCDA 3 22 4]
[ABCD 4 7 5] [DABC 5 12 6] [Cdab 6 17 7] [BCDA 7 22 8]
[ABCD 8 7 9] [DABC 9 12 10] [Cdab 10 17 11] [BCDA 11 22 12]
[ABCD 12 7 13] [DABC 13 12 14] [Cdab 14 17 15] [BCDA 15 22 16]


* * * * * 2nd round * * *
/* with [ABCD K S] to represent the following operations
A = B + ((A + G (b,c,d) + x[k] + t[i]) <<< s). */
/* Do the following operations. */
[ABCD 1 5 17] [DABC 6 9 18] [Cdab 11 14 19] [BCDA 0 20 20]
[ABCD 5 5 21] [DABC 10 9 22] [Cdab 15 14 23] [BCDA 4 20 24]
[ABCD 9 5 25] [DABC 14 9 26] [Cdab 3 14 27] [BCDA 8 20 28]
[ABCD 13 5 29] [DABC 2 9 30] [Cdab 7 14 31] [BCDA 12 20 32]

/* 3rd Round * *
/* with [ABCD K S] to represent the following operations
A = B + ((A + H (b,c,d) + x[k] + t[i]) <<< s). */
/* Do the following operations. */
[ABCD 5 4 33] [DABC 8 11 34] [Cdab 11 16 35] [BCDA 14 23 36]
[ABCD 1 4 37] [DABC 4 11 38] [Cdab 7 16 39] [BCDA 10 23 40]
[ABCD 13 4 41] [DABC 0 11 42] [Cdab 3 16 43] [BCDA 6 23 44]
[ABCD 9 4 45] [DABC 12 11 46] [Cdab 15 16 47] [BCDA 2 23 48]


/* 4th round * *
/* with [ABCD K S] to represent the following operations
A = B + ((A + I (b,c,d) + x[k] + t[i]) <<< s). */
/* Do the following operations. */
[ABCD 0 6 49] [DABC 7 10 50] [Cdab 14 15 51] [BCDA 5 21 52]
[ABCD 12 6 53] [DABC 3 10 54] [Cdab 10 15 55] [BCDA 1 21 56]
[ABCD 8 6 57] [DABC 15 10 58] [Cdab 6 15 59] [BCDA 13 21 60]
[ABCD 4 6 61] [DABC 11 10 62] [Cdab 2 15 63] [BCDA 9 21 64]

/* Then do the following: *
A = a + AA
B = B + BB
c = C + CC
D = d + DD

Next I/* end of loop on I * *

The sixth step, the output results.
A,b,c,d continuous storage, a total of 16 bytes, 128 bits. This 16 byte is output in hexadecimal order.


Finally, the program language to implement the algorithm, you can enter the following information for the program to make a simple test,
See if there is a bug in the program.
MD5 ("") = d41d8cd98f00b204e9800998ecf8427e
MD5 ("a") = 0cc175b9c0f1b6a831c399e269772661
MD5 ("abc") = 900150983cd24fb0d6963f7d28e17f72
MD5 ("message digest") = F96b697d7cb7938d525a2f31aaf161d0
MD5 ("abcdefghijklmnopqrstuvwxyz") = c3fcd3d76192e4007dfb496cca67e13b
MD5 ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789") =
d174ab98d277d9f5a5611c2c9f419d9f
MD5 ("123456789012345678901234567890123456789012345678901234567890123456789
01234567890 ") = 57edf4a22be3c955ac49da2e2107b67a


C # Program of MD5 algorithm

MD5 algorithm is more special, most suitable for writing in assembly language, a lot of high-level language is powerless or inefficient.
For example, I first tried to write with Python and euphoria, and found it difficult. In contrast, C # as a C family cluster
In the emerging A. NET language, the function is more comprehensive. It took one night to finally realize the MD5 with C #.
Mainly because of some of the details of the algorithm is not very attention, the result is always wrong output, debugging for a long time.

The following is the program code
Source file: Md5.cs
MD5 Alogrithm
by Rufi 2004.6.20 http://rufi.yculblog.com/
Using System;
Using System.Collections;
Using System.IO;

public class MD5 {
Static state variables
private static UInt32 A;
private static UInt32 B;
private static UInt32 C;
private static UInt32 D;

Number of bits to rotate in tranforming
Private Const int S11 = 7;
Private Const int S12 = 12;
Private Const int S13 = 17;
Private Const int S14 = 22;
Private Const int S21 = 5;
Private Const int S22 = 9;
Private Const int S23 = 14;
Private Const int S24 = 20;
Private Const int S31 = 4;
Private Const int S32 = 11;
Private Const int S33 = 16;
Private Const int S34 = 23;
Private Const int S41 = 6;
Private Const int S42 = 10;
Private Const int S43 = 15;
Private Const int S44 = 21;


/* F, G, H and I are basic MD5 functions.
* Four nonlinear functions:
*
* F (x,y,z) = (x&y) | ((~x) &z)
* G (x,y,z) = (x&z) | (y& (~z))
* H (X,Y,Z) =x^y^z
* I (X,y,z) =y^ (x| ( ~Z))
*
* (& with, | or, ~ non, ^ xor or)
*/
private static UInt32 F (UInt32 x,uint32 y,uint32 z) {
Return (X&y) | ((~x) &z);
}
private static UInt32 G (UInt32 x,uint32 y,uint32 z) {
Return (X&AMP;Z) | (y& (~z));
}
private static UInt32 H (UInt32 x,uint32 y,uint32 z) {
return x^y^z;
}
private static UInt32 I (UInt32 x,uint32 y,uint32 z) {
Return y^ (x| ( ~Z));
}

/* FF, GG, HH, and II transformations for Rounds 1, 2, 3, and 4.
* Rotation is separate from addition to prevent recomputation.
*/
private static void FF (ref UInt32 A,uint32 b,uint32 c,uint32 d,uint32 mj,int s,uint32 ti) {
A = a + F (b,c,d) + MJ + ti;
A = a << s | A >> (32-s);
A + b;
}
private static void GG (ref UInt32 A,uint32 b,uint32 c,uint32 d,uint32 mj,int s,uint32 ti) {
A = a + G (b,c,d) + MJ + ti;
A = a << s | A >> (32-s);
A + b;
}
private static void HH (ref UInt32 A,uint32 b,uint32 c,uint32 d,uint32 mj,int s,uint32 ti) {
A = a + H (b,c,d) + MJ + ti;
A = a << s | A >> (32-s);
A + b;
}
private static void II (ref UInt32 A,uint32 b,uint32 c,uint32 d,uint32 mj,int s,uint32 ti) {
A = a + I (b,c,d) + MJ + ti;
A = a << s | A >> (32-s);
A + b;
}

private static void Md5_init () {
a=0x67452301; In memory, this is 0x01234567
b=0xefcdab89; In memory, this is 0x89abcdef
C=0x98badcfe; In memory, this is 0xfedcba98
d=0x10325476; In memory, this is 0x76543210
}

private static uint32[] Md5_append (byte[] input) {
int zeros=0;
int ones = 1;
int size=0;
int n = input. Length;
int m = n%64;
if (M < 56) {
zeros = 55-m;
size=n-m+64;
}
else if (m==56) {
Zeros = 0;
ones = 0;
Size=n+8;
}
else{
zeros = 63-m+56;
size=n+64-m+64;
}

ArrayList bs = new ArrayList (input);
if (ones==1) {
Bs. Add ((byte) 0x80); 0x80 = $10000000
}
for (int i=0;i<zeros;i++) {
Bs. Add ((byte) 0);
}

UInt64 n = (UInt64) n * 8;
byte h1= (Byte) (N&AMP;0XFF);
byte h2= (Byte) ((n>>8) &0xff);
byte h3= (Byte) ((n>>16) &0xff);
byte h4= (Byte) ((n>>24) &0xff);
byte h5= (Byte) ((n>>32) &0xff);
byte h6= (Byte) ((n>>40) &0xff);
byte h7= (Byte) ((n>>48) &0xff);
byte h8= (Byte) (n>>56);
Bs. ADD (H1);
Bs. ADD (H2);
Bs. ADD (H3);
Bs. ADD (H4);
Bs. Add (h5);
Bs. Add (h6);
Bs. ADD (H7);
Bs. ADD (H8);
Byte[] ts= (byte[]) Bs. ToArray (typeof (Byte));

/* Decodes input (byte[]) into output (uint32[). Assumes Len is
* A multiple of 4.
*/
uint32[] output = new UINT32[SIZE/4];
for (Int64 i=0,j=0;i<size;j++,i+=4) {
Output[j]= (UInt32) (Ts[i] | ts[i+1]<<8 | ts[i+2]<<16 | ts[i+3]<<24);
}
return output;
}
private static uint32[] Md5_trasform (uint32[] x) {

UInt32 a,b,c,d;

for (int k=0;k<x.length;k+=16) {
A=a;
B=b;
C=c;
D=d;

/* Round 1 * *
FF (ref A, B, C, D, x[k+ 0], S11, 0xd76aa478); /* 1 * *
FF (ref d, A, B, C, x[k+ 1], S12, 0xe8c7b756); /* 2 * *
FF (ref c, D, a, B, x[k+ 2], S13, 0x242070db); /* 3 * *
FF (ref B, C, D, A, x[k+ 3], S14, 0xc1bdceee); /* 4 * *
FF (ref A, B, C, D, x[k+ 4], S11, 0XF57C0FAF); /* 5 * *
FF (ref d, A, B, C, x[k+ 5], S12, 0x4787c62a); /* 6 * *
FF (ref c, D, a, B, x[k+ 6], S13, 0xa8304613); /* 7 * *
FF (ref B, C, D, A, x[k+ 7], S14, 0xfd469501); /* 8 * *
FF (ref A, B, C, D, x[k+ 8], S11, 0X698098D8); /* 9 * *
FF (ref d, A, B, C, x[k+ 9], S12, 0X8B44F7AF); /* 10 * *
FF (ref c, D, a, B, x[k+10], S13, 0XFFFF5BB1); /* 11 * *
FF (ref B, C, D, A, x[k+11], S14, 0x895cd7be); /* 12 * *
FF (ref A, B, C, D, x[k+12], S11, 0x6b901122); /* 13 * *
FF (ref d, A, B, C, x[k+13], S12, 0xfd987193); /* 14 * *
FF (ref c, D, a, B, x[k+14], S13, 0xa679438e); /* 15 * *
FF (ref B, C, D, A, x[k+15], S14, 0x49b40821); /* 16 * *

/* Round 2 * *
GG (ref A, B, C, D, x[k+ 1], S21, 0xf61e2562); /* 17 * *
GG (ref d, A, B, C, x[k+ 6], S22, 0xc040b340); /* 18 * *
GG (ref c, D, a, B, x[k+11], S23, 0x265e5a51); /* 19 * *
GG (ref B, C, D, A, x[k+ 0], S24, 0XE9B6C7AA); /* 20 * *
GG (ref A, B, C, D, x[k+ 5], S21, 0xd62f105d); /* 21 * *
GG (ref d, A, B, C, x[k+10], S22, 0x2441453); /* 22 * *
GG (ref c, D, a, B, x[k+15], S23, 0xd8a1e681); /* 23 * *
GG (ref B, C, D, A, x[k+ 4], S24, 0XE7D3FBC8); /* 24 * *
GG (ref A, B, C, D, x[k+ 9], S21, 0x21e1cde6); /* 25 * *
GG (ref d, A, B, C, x[k+14], S22, 0XC33707D6); /* 26 * *
GG (ref c, D, a, B, x[k+ 3], S23, 0xf4d50d87); /* 27 * *
GG (ref B, C, D, A, x[k+ 8], S24, 0x455a14ed); /* 28 * *
GG (ref A, B, C, D, X[k+13], S21, 0xa9e3e905); /* 29 * *
GG (ref d, A, B, C, x[k+ 2], S22, 0XFCEFA3F8); /* 30 * *
GG (ref c, D, a, B, x[k+ 7], S23, 0X676F02D9); /* 31 * *
GG (ref B, C, D, A, x[k+12], S24, 0x8d2a4c8a); /* 32 * *

/* Round 3 * *
HH (ref A, B, C, D, x[k+ 5], S31, 0xfffa3942); /* 33 * *
HH (ref d, A, B, C, x[k+ 8], S32, 0x8771f681); /* 34 * *
HH (ref c, D, a, B, x[k+11], S33, 0x6d9d6122); /* 35 * *
HH (ref B, C, D, A, x[k+14], S34, 0xfde5380c); /* 36 * *
HH (ref A, B, C, D, x[k+ 1], S31, 0xa4beea44); /* 37 * *
HH (ref d, A, B, C, x[k+ 4], S32, 0x4bdecfa9); /* 38 * *
HH (ref c, D, a, B, x[k+ 7], S33, 0xf6bb4b60); /* 39 * *
HH (ref B, C, D, A, x[k+10], S34, 0XBEBFBC70); /* 40 * *
HH (ref A, B, C, D, X[k+13], S31, 0X289B7EC6); /* 41 * *
HH (ref d, A, B, C, x[k+ 0], S32, 0XEAA127FA); /* 42 * *
HH (ref c, D, a, B, x[k+ 3], S33, 0xd4ef3085); /* 43 * *
HH (ref B, C, D, A, x[k+ 6], S34, 0X4881D05); /* 44 * *
HH (ref A, B, C, D, x[k+ 9], S31, 0xd9d4d039); /* 45 * *
HH (ref d, A, B, C, x[k+12], S32, 0xe6db99e5); /* 46 * *
HH (ref c, D, a, B, x[k+15], S33, 0X1FA27CF8); /* 47 * *
HH (ref B, C, D, A, x[k+ 2], S34, 0xc4ac5665); /* 48 * *

/* Round 4 * *
II (ref A, B, C, D, x[k+ 0], S41, 0xf4292244); /* 49 * *
II (ref d, A, B, C, x[k+ 7], S42, 0X432AFF97); /* 50 * *
II (ref c, D, a, B, x[k+14], S43, 0XAB9423A7); /* 51 * *
II (ref B, C, D, A, x[k+ 5], S44, 0xfc93a039); /* 52 * *
II (ref A, B, C, D, x[k+12], S41, 0X655B59C3); /* 53 * *
II (ref d, A, B, C, x[k+ 3], S42, 0x8f0ccc92); /* 54 * *
II (ref c, D, a, B, x[k+10], S43, 0xffeff47d); /* 55 * *
II (ref B, C, D, A, x[k+ 1], S44, 0X85845DD1); /* 56 * *
II (ref A, B, C, D, x[k+ 8], S41, 0x6fa87e4f); /* 57 * *
II (ref d, A, B, C, x[k+15], S42, 0XFE2CE6E0); /* 58 * *
II (ref c, D, a, B, x[k+ 6], S43, 0xa3014314); /* 59 * *
II (ref B, C, D, A, x[k+13], S44, 0X4E0811A1); /* 60 * *
II (ref A, B, C, D, x[k+ 4], S41, 0xf7537e82); /* 61 * *
II (ref d, A, B, C, x[k+11], S42, 0xbd3af235); /* 62 * *
II (ref c, D, a, B, x[k+ 2], S43, 0X2AD7D2BB); /* 63 * *
II (ref B, C, D, A, x[k+ 9], S44, 0xeb86d391); /* 64 * *

A+=a;
B+=b;
C+=c;
D+=d;
}
return new Uint32[]{a,b,c,d};
}
public static byte[] Md5array (byte[] input) {
Md5_init ();
uint32[] block = md5_append (input);
Uint32[] bits = md5_trasform (block);

/* encodes bits (uint32[] into output (byte[)). Assumes Len is
* A multiple of 4.
*/
Byte[] Output=new byte[bits. LENGTH*4];
for (int i=0,j=0;i<bits. length;i++,j+=4) {
OUTPUT[J] = (byte) (Bits[i] & 0xff);
Output[j+1] = (byte) ((Bits[i] >> 8) & 0xff);
OUTPUT[J+2] = (byte) ((Bits[i] >>) & 0xff);
OUTPUT[J+3] = (byte) ((Bits[i] >>) & 0xff);
}
return output;
}

public static string arraytohexstring (byte[] Array,bool uppercase) {
String Hexstring= "";
String format= "X2";
if (uppercase) {
format= "X2";
}
foreach (byte b in array) {
HexString + + b.tostring (format);
}
return hexstring;
}

public static string mdstring (String message) {
Char[] C = message. ToCharArray ();
Byte[] B = new Byte[c.length];
for (int i=0;i<c.length;i++) {
B[i]= (Byte) c[i];
}
Byte[] Digest = Md5array (b);
Return arraytohexstring (Digest,false);
}
public static string Mdfile (String fileName) {
FileStream Fs=file.open (Filename,filemode.open,fileaccess.read);
Byte[] Array=new Byte[fs. Length];
Fs. Read (array,0, (int) fs. Length);
Byte[] Digest = Md5array (array);
Fs. Close ();
Return arraytohexstring (Digest,false);
}

public static string Test (String message) {
Return "RnMD5 (" "+message+" ") =" + MD5. mdstring (message);
}
public static string TestSuite () {
string s = "";
S+=test ("");
S+=test ("a");
S+=test ("abc");
S+=test ("Message digest");
S+=test ("abcdefghijklmnopqrstuvwxyz");
S+=test ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789");
S+=test ("12345678901234567890123456789012345678901234567890123456789012345678901234567890");
return s;
}
}




Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.