MD5 algorithm research
The full name of MD5 is a Message-Digest Algorithm 5 (information-summary algorithm), which is developed by Mit Laboratory for Computer Science and RSA Data Security Inc, which is developed by MD2, MD3 and MD4 in the 1990s. Its role is to make large capacity information to be "compressed" into a confidential format before signing private privacy with digital signature software (that is, transforms an arbitrary length of byte string into a certain length). Whether it is MD2, MD4 or MD5, they all need to obtain a random length of information and generate a 128-bit information summary. Although the structure of these algorithms is more similar, the design of MD2 is completely different from MD4 and MD5, because MD2 is designed for 8-bit machines, while MD4 and MD5 are 32-bit computers. The descriptions of these three algorithms have a detailed description in Internet RFCS 1321 (http://www.ietf.org/rfc/rfc1321.txt), this is the most authoritative document, by Ronald L Rivest submitted to IEFT in August 1992.
Rivest developed an MD2 algorithm in 1989. In this algorithm, the information is first supplied to the information, so that the byte length of the information is a multiple of 16. Then, at a 16-bit test and append to the end of the information. And calculate the hash value based on this new information. Later, Rogier and Chauvaud found that if the test and the MD2 conflict will be generated. The result of the encryption of the MD2 algorithm is unique - neither repeat.
In order to enhance the safety of the algorithm, RiveSt has developed an MD4 algorithm in 1990. The MD4 algorithm also needs to fill the information to ensure that the byte length of the information plus 448 can be divided by 512 (information byte length MOD 512 = 448). Then, one of the initial lengths of information indicated by 64-bit binary is added. The information is processed into blocks of 512-bit DAMG? RD / Merkle iterative structure, and each block is to be processed by three different steps. Den Boer and Bosselaers and others quickly discovered the first step and third steps in the MD4 version. Dobbertin demonstrates how to use a regular personal computer to find a conflict in the full version of the MD4 in a few minutes (this conflict is actually a vulnerability, which will result in encryption of different content but may get the same encryption. result). There is no doubt that MD4 is eliminated.
Although the MD4 algorithm has such a large vulnerability in the security, it has a guiding role in the presence of several information security encryption algorithms that have been developed thereon. In addition to MD5, there are also SHA-1, RIPE-MD, and HAVAL, etc.
One year later, that is, in 1991, Rivest developed technology more approached MD5 algorithm. It adds the concept of "safe-band" (safty-beelts) based on MD4. Although MD5 is slightly slower than MD4, it is safer. This algorithm is obvious by four and MD4 designs with a little different steps. In the MD5 algorithm, the size of the information - summary and the necessary conditions of the filler are identical to the MD4. Den Boer and Bosselaers have discovered pseudo-collisions in the MD5 algorithm, but there is no other resulting result.
Van Orschot and Wiener have considered a function of violent search conflicts in hash, and they guess a machine that is designed to search for MD5 conflicts (this machine is approximately manufactured in 1994 It is a million US dollars) to find a conflict every 24 days. However, from 1991 to 2001, there is no new algorithm for MD6 or other names that have alternative MD5 algorithms, and we can see that this flaw does not have much impact on MD5 security. All of these is not enough to become MD5 problems in practical applications. Also, since the use of the MD5 algorithm does not need to pay any copyright costs, in general (non-top secret applications. But even if the application is in the top secret field, MD5 is not a very good intermediate technology), MD5 It should be considered very safe. Application of algorithm
The typical application of MD5 is a message-digest to prevent tampering. For example, there are many softwares in UNIX to have a file name in the download, and the file extension is the file named .md5, in this file, there is usually only one line of text, which is approximately structured.
MD5 (tanajiya.tar.gz) = 0ca175b9c0f726a831d895e269332461
This is a digital signature of tanajiya.tar.gz file. MD5 uses the entire file as a large text message, producing this unique MD5 information summary through its irreversible string conversion algorithm. If in the process of transmitting this file later, regardless of any form changes in the content of the file (including the transmission error caused by the line instability during the download process), as long as you recall the MD5, you will find it. The summary of the information is different, thereby determining that you get just an incorrect file. If there is another third party certification body, use MD5 to prevent "reliability" of the author, this is the so-called digital signature application.
MD5 is also widely used in encryption and decryption technology. For example, the user's password in the UNIX system is stored in the file system after the MD5 (or other similar algorithm) is encrypted. When the user logs in, the system calculates the password entered into the MD5 value, then goes and saved the MD5 value in the file system to compare, and then determine if the input password is correct. By this step, the system can determine the legality of the user login system without knowing the coding of the user's password. This not only avoids the user's password known by the user of the system administrator privilege, but also adds the difficulty of password being crack to some extent.
It is precisely because of this reason, the method of hacked the most deciphering password is a method called "running". There are two ways to get a dictionary, one is a character string table for daily collections, the other is to generate the MD5 value of these dictionaries with the MD5 program, and then use the target The MD5 value is retrieved in this dictionary. We assume that the maximum length of the password is 8-bit bytes (8 bytes), and the password can only be a letter and a number, a total of 26 26 10 = 62 characters, and the number of items that are arranged in the group is P (62, 1) p (62, 2) .... P (62, 8), it is already a very an astronomical number, storing this dictionary requires a TB-level disk array, and this method has a premise, It is possible to get the password MD5 value of the target account. This encryption technology is widely used in UNIX systems, which is why the UNIX system is more robust than a general operating system.
Algorithm Description
A brief description of the MD5 algorithm may be: MD5 is grouped with 512-bit grouping to process the input information, and each group is divided into 16 32-bit sub-packets. After a series of processes, the output of the algorithm is from four 32 bits. The packet consists, and the four 32-bit grouping level will generate a 128-bit scatter value. In the MD5 algorithm, the information is first to be filled, so that the result of the byte length to 512 is equal to 448. Therefore, the byte length of the information will be extended to N * 512 448, namely N * 64 56 bytes, n is a positive integer. The filling method is as follows, and one 1 and countless 0 are filled in the rear of the information until 0 to the information of the information is stopped using 0. Then, the length of the pre-filling before this result is additionally indicated by 64-bit binary. After these two steps, the current information byte length = N * 512 448 64 = (n 1) * 512, that is, the length is exactly the integer multiple of 512. The reason for this is to meet the requirements of the information length in the back processing.
The MD5 has four 32-bit integer parameters of chaining variable, which are: a = 0x01234567, b = 0x89abcdef, c = 0xfedcba98, d = 0x76543210.
When these four link variables are set, the four-wheel loop calculation of the algorithm is started. The number of cycles is the number of 512-bit information packets in the information.
Copy the above four link variables to the other four variables: A to A, B to B, C to C, D to D.
The main circulation has four rounds (MD4 only three rounds), each round of cycles are similar. The first round of 16 operations. Each of the A, B, C, and D is operated for a nonlinear function calculation, and then the resulting result is added to the fourth variable, a sub-packet and a constant of the text. The resulting result is then moved to the right ring and plus one of A, B, C or D. Finally, the results are used to replace one of A, B, C or D.
Take it is the four nonlinear functions used in each operation (one per wheel).
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))
(& Yes, | Yes, ~ is right, ^ is different or)
Description of these four functions: If the corresponding position of X, Y and Z is independent and uniform, each bit of the result should also be independent and uniform.
F is a function of bitmaping. That is, if x, then y, otherwise z. The function h is a bitmap parity.
Assume that MJ represents the jth packet of the message (from 0 to 15),
<< ff (A, B, C, D, MJ, S, Ti) represents A = B ((A (F (B, C, D) MJ Ti)
<< GG (A, B, C, D, MJ, S, Ti) represents A = B ((A (G (B, C, D) MJ Ti)
<< HH (A, B, C, D, MJ, S, Ti) represents A = B ((A (H (B, C, D) MJ Ti)
<< II (A, B, C, D, MJ, S, Ti) represents A = B ((A (i (B, C, D) MJ Ti)
<< These four rounds (64 steps) are:
First round FF (A, B, C, D, M0, 7, 0xD76AA478)
FF (D, A, B, C, M1, 12, 0XE8C7B756)
FF (C, D, A, B, M2, 17, 0X242070DB)
FF (B, C, D, A, M3, 22, 0XC1BDCEEE)
FF (A, B, C, D, M4, 7, 0xF57c0FAF)
FF (D, A, B, C, M5, 12, 0X4787C62A)
FF (C, D, B, M6, 17, 0XA8304613)
FF (B, C, D, A, M7, 22, 0xFD469501)
FF (A, B, C, D, M8, 7, 0x698098d8)
FF (D, A, B, C, M9, 12, 0X8B44F7AF)
FF (C, D, A, B, M10, 17, 0xFFFF5BB1)
FF (B, C, D, A, M11, 22, 0X895CD7BE)
FF (A, B, C, D, M12, 7, 0x6b901122)
FF (D, A, B, C, M13, 12, 0xFD987193)
FF (C, D, A, B, M14, 17, 0XA679438E)
FF (B, C, D, A, M15, 22, 0X49B40821)
second round
GG (A, B, C, D, M1, 5, 0xF61e2562)
GG (D, A, B, C, M6, 9, 0xc040b340)
GG (C, D, A, B, M11, 14, 0X265E5A51)
GG (B, C, D, A, M0, 20, 0XE9B6C7AA)
GG (A, B, C, D, M5, 5, 0xD62F105D)
GG (D, A, B, C, M10, 9, 0x02441453)
GG (C, D, B, M15, 14, 0XD8A1E681)
GG (B, C, D, A, M4, 20, 0XE7D3FBC8)
GG (A, B, C, D, M9, 5, 0X21E1CDE6)
GG (D, A, B, C, M14, 9, 0XC33707D6)
GG (C, D, A, B, M3, 14, 0xf4d50d87)
GG (B, C, D, A, M8, 20, 0X455A14ED)
GG (A, B, C, D, M13, 5, 0XA9E3E905)
GG (D, A, B, C, M2, 9, 0xfcefa3f8)
GG (C, D, A, B, M7, 14, 0X676F02D9)
GG (B, C, D, A, M12, 20, 0X8D2A4C8A)
Third round
HH (A, B, C, D, M5, 4, 0xFFFA3942)
HH (D, A, B, C, M8, 11, 0X8771F681)
HH (C, D, A, B, M11, 16, 0X6D9D6122)
HH (B, C, D, A, M14, 23, 0XFDE5380C)
HH (A, B, C, D, M1, 4, 0XA4BEEA44)
HH (D, A, B, C, M4, 11, 0X4BDECFA9)
HH (C, D, A, B, M7, 16, 0XF6BB4B60)
HH (B, C, D, A, M10, 23, 0XBEBFBC70)
HH (A, B, C, D, M13, 4, 0X289B7EC6)
HH (D, A, B, C, M0, 11, 0XEAA127FA)
HH (C, D, A, B, M3, 16, 0xD4ef3085)
HH (B, C, D, A, M6, 23, 0X04881D05)
HH (A, B, C, D, M9, 4, 0xD9D4D039)
HH (D, A, B, C, M12, 11, 0XE6DB99E5)
HH (C, D, A, B, M15, 16, 0X1FA27CF8)
HH (B, C, D, A, M2, 23, 0XC4AC5665)
Fourth round
II (A, B, C, D, M0, 6, 0xF4292244)
II (D, A, B, C, M7, 10, 0X432AFF97)
II (C, D, B, M14, 15, 0XAB9423A7)
II (B, C, D, A, M5, 21, 0xFC93A039)
II (A, B, C, D, M12, 6, 0x65559c3)
II (D, A, B, C, M3, 10, 0X8F0CCC92)
II (C, D, A, B, M10, 15, 0xffeff47d)
II (B, C, D, A, M1, 21, 0X85845DD1)
II (A, B, C, D, M8, 6, 0x6fa87e4f)
II (D, A, B, C, M15, 10, 0XFE2CE6E0) II (C, D, A, B, M6, 15, 0XA3014314)
II (B, C, D, A, M13, 21, 0X4E0811A1)
Ii (A, B, C, D, M4, 6, 0xf7537e82)
II (D, A, B, C, M11, 10, 0XBD3AF235)
II (C, D, A, B, M2, 15, 0X2AD7D2BB)
II (B, C, D, A, M9, 21, 0XEB86D391)
The constant TI can choose from:
In the first step, Ti is 4294967296 * ABS (SiN (i)) integer part, and the unit of I is an arc. (4294967296 equal to 2) 32 times)
After all of these completed, A, B, C, and D were added to A, B, C, D, respectively. Then use the next packet data to continue the algorithm, and the last output is cascaded of A, B, C, and D.
When you implement the MD5 algorithm according to the method I mentioned above, you can use the following information to make a simple test you made, see if there is any error.
MD5 ("") = D41D8CD98F00B204E9800998ECF8427E
MD5 ("a") = 0cc175b9c0f1b6a831c399e269772661
MD5 ("ABC") = 900150983cd24fb0d6963f7d28e17f72
MD5 ("Message Digest") = F96B697D7CB7938D525A2F31AAF161D0
MD5 ("AbcdefghijklmnopqrStuvwxyz") = C3FCD3D76192E4007DFB496CCA67E13B
MD5 ("AbcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrStuvwxyz0123456789) =
D174AB98D277D9F5A5611C2C9F419D9F
MD5 ("123456789012345678901234567890123456789012345678901234567890123456789
01234567890 ") = 57EDF4A22BE3C955AC49DA2E2107B67A
If you use the information on the above information to test the MD5 algorithm instance, finally, the conclusions and standard answers are exactly the same, then I will have a congratulations here. To know, my program is not derived from the same result when the first compilation is successful.
MD5 security
Improvements made by MD5 relative to MD4:
1. Added the fourth round;
2. Each step has a unique addition constant;
3. To reduce the symmetry of function G in the second round from (X & Y) | (Y & Z) to (Y & Z) | (Y & (~ Z));
4. The first step plus the result of the previous step, which will cause faster avalanche effects;
5. Change the order of accessing the message sub-packet in the second round and third rounds, making it more different;
6. Approximately optimize the loop left shift transmissions in each round to achieve a faster avalanche effect. The displacement amount of each wheel is different.
The MD2 Message-Digest Algorithm Status of this Memo This memo provides information for the Internet community. It does not specify an Internet standard. Distribution of this memo is unlimited. Acknowlegements The description of MD2 is based on material prepared by John Linn and Ron Rivest . Their permission to incorporate that material is greatly appreciated Table of Contents 1. Executive Summary 1 2. Terminology and Notation 2 3. MD2 Algorithm Description 2 4. Summary 4 References 5 APPENDIX A -. Reference Implementation 5 Security Considerations 17 Author's Address 17 1 EXECU tive Summary This document describes the MD2 message-digest algorithm. The algorithm takes as input a message of arbitrary length and produces as output a 128-bit "fingerprint" or "message digest" of the input. It is conjectured that it is computationally infeasible to produce two messages having the same message digest, or to produce any message having a given prespecified target message digest. The MD2 algorithm is intended for digital signature applications, where a large file must be "compressed"
in a secure manner before being signed with a private (secret) key under a public-key cryptosystem such as RSA. License to use MD2 is granted for non-commerical Internet Privacy- Enhanced Mail [1-3]. This document is an update to the August 1989 RFC 1115 [3], which also gives a reference implementation of MD2. The main differences are that a textual description of MD2 is included, and that the reference implementation of MD2 is more portable. For OSI-based applications, MD2's object identifier is md2 OBJECT iDENTIFIER :: = iso (1) member-body (2) US (840) rsadsi (113549) digestAlgorithm (2) 2} In the X.509 type AlgorithmIdentifier [4], the parameters for MD2 should have TYPE NULL. 2. Terminology and notation in this document, a "byte" is an electric-bit quantity. let x_i denote "x sub i". if Subscript is an expression, WE Surround IT IN BRACES, AS IN X_ {i 1}. Similarly, we use ^ for superscripts (exponentiation), so that x ^ i Denote Sx to the i-th power. let x xor y denote the bit-wise xor of x and y.3. Md2 Algorithm Description We Begin by Supposing That We Have A B-byte Message As INPUT, AND THAT WISH TO FIND ITS message digest Here b is an arbitrary nonnegative integer; b may be zero, and it may be arbitrarily large We imagine the bytes of the message written down as follows:.. m_0 m_1 ... m_ {b-1} The following five steps Are Performed to Compute The Message Digest of The Message. 3.1 Step 1. Append Padding Bytes The Message IS "Padded"
(Extended) so that its length (in bytes) is congruent to 0, modulo 16. That is, the message is extended so that it is a multiple of 16 bytes long. Padding is always performed, even if the length of the message is already congruent to 0, modulo 16. Padding is performed as follows: "i" bytes of value "i" are appended to the message so that the length in bytes of the padded message becomes congruent to 0, modulo 16. At least one byte And at Most 16 16 BYTES Are Appended. AtTer Point The Resulting Message (After Padding with Bytes) HAS a Length That Is An Exact Multiple of 16 Bytes. Let M [0 ... N-1] DENOTE The BYTES of THE RESULTING message, where N is a multiple of 16. 3.2 Step 2. Append Checksum A 16-byte checksum of the message is appended to the result of the previous step. This step uses a 256-byte "random" permutation constructed from the digits of Pi. Let S [i] Denote The I-TH Element of this table. The Table is Given in the append IX. do the following: / * clear checksum. * / for i = 0 to 15 do: set C [i] to 0. end / * of loop on i * / set l to 0. / * Process Each 16-Word Block. * / for i = 0 to n / 16-1 do / * checksum block i. * / for j = 0 to 15 do set c to m [i * 16 j]. set c [j] to s [ C xor l]. set L to C [J]. End / * of loop on j * / end / * of loop on i * / the 16-byte checksum c [0 ... 15] is appended to the message. Let M [0 with checksum), where n '= n
16. 3.3 Step 3. Initialize MD Buffer A 48-byte buffer X is used to compute the message digest. The buffer is initialized to zero. 3.4 Step 4. Process Message in 16-Byte Blocks This step uses the same 256-byte permutation S as step 2 does. Do the folload: / * process Each 16-word block. * / For i = 0 to n '/ 16-1 do / * Copy Block I Into x. * / for j = 0 to 15 do SET X [16 J] to M [i * 16 j]. Set x [32 j] to (x [16 j] xor x [j]). End / * of loop on j * / set t TO 0. / * do 18 rounds. * / for j = 0 to 17 do / * round j. * / fork = 0 to 47 do set t and x [k] to (x [k] xor s [t] ). End / * of loop on k * / set t to (t j) modulo 256. End / * of loop on j * / end / * of loop on i * / 3.5 step 5. Output the message Digest Productued AS Output IS X [0 ... 15]. That is, we begin with x [0], and end with x [15]. this completion Es The Description of Md2. A Reference Implementation In C Is Given in The Appendix. 4. Summary THE MD2 Message-Digest Algorithm is Simple to Implement, And Provides a "Fingerprint"
or message digest of a message of arbitrary length. It is conjectured that the difficulty of coming up with two messages having the same message digest is on the order of 2 ^ 64 operations, and that the difficulty of coming up with any message having a given message digest is on the order of 2 ^ 128 operations. The MD2 algorithm has been carefully scrutinized for weaknesses. It is, however, a relatively new algorithm and further security analysis is of course justified, as is the case with any new proposal of this Sort. References [1] Linn, J., "Privacy Enhancement for Internet Electronic Mail: Part I - Message Encipherment and Authentication Procedures", RFC 1113, DEC, IAB Privacy Task Force, August 1989. [2] Kent, S. , And J. Linn, "Privacy Enhancement for Internet Electronic Mail: Part II - Certificate-Based Key Management", RFC 1114, BBNCC, DEC, IAB Privacy Task Force, August 1989. [3] Linn, J., "Privacy Enhancement for i nternet Electronic Mail: Part III - Algorithms, Modes, and Identifiers ", RFC 1115 DEC, IAB Privacy Task Force, August 1989. [4] CCITT Recommendation X.509 (1988)," The Directory - Authentication Framework "APPENDIX A. - Reference Implementation This appendix contains the following files taken from RSAREF: A Cryptographic Toolkit for Privacy-Enhanced Mail: global.h - global header file md2.h - header file for MD2 md2c.c - source code for MD2 for more Information on rsaref, send email to
. The appendix also includes the following file: mddriver.c - test driver for MD2, MD4 and MD5 The driver compiles for MD5 by default but can compile for MD2 or MD4 if the symbol MD is defined on the C compiler command line as 2 or 4. A.1 global.h / * GLOBAL.H -. RSAREF types and constants * / / * PROTOTYPES should be set to one if and only if the compiler supports function argument prototyping The following makes PROTOTYPES default to 0 if it has not already been defined with C compiler flags * / #ifndef PROTOTYPES #define PROTOTYPES 0 #endif / * pOINTER defines a generic pointer type * / typedef unsigned char * pOINTER;. / * UINT2 defines a two byte word * / typedef unsigned short int UINT2; / * UINT4 defines a four byte word * / typedef unsigned long int UINT4;.. / * PROTO_LIST is defined depending on how PROTOTYPES is defined above If using PROTOTYPES, then PROTO_LIST returns the list, otherwise it returns an empty list * / #if protoypes #define proto_list (list) list #else #define proto_list (list) () #ENDIF A.2 md2.h / * md2.h - Header file for md2c.c * / / * CopyRight (C) 1990-2, RSA Data Security, Inc. Created 1990. All rights reserved. License to copy and use this software is granted for non-commercial Internet Privacy-Enhanced Mail provided that it is identified as the "RSA Data Security, Inc. MD2 Message Digest Algorithm" in all material mentioning or referencing this software or this function. RSA Data Security, Inc. makes no representations concerning either the merchantability of this software or the suitability of this software for any particular purpose. It is provided "as is"
. Without express or implied warranty of any kind These notices must be retained in any copies of any part of this documentation and / or software * / typedef struct {unsigned char state [16];. / * State * / unsigned char checksum [16 ]; / * checksum * / unsigned int count; / * number of bytes, modulo 16 * / unsigned char buffer [16]; / * input buffer * /} MD2_CTX; void MD2Init PROTO_LIST ((MD2_CTX *)); void MD2Update PROTO_LIST ((MD2_CTX *, Unsigned Int); Void Md2Final Proto_List ((unsigned char [16), md2_ctx *)); A.3 MD2C.C / * MD2C.C - RSA Data Security, Inc., MD2 message-digest algorithm * / / * Copyright (C) 1990-2, RSA Data Security, Inc. Created 1990. All rights reserved. License to copy and use this software is granted for non-commercial Internet Privacy-Enhanced Mail provided that it Is Identified As The "RSA Data Security, Inc. MD2 Message Dige st Algorithm "in all material mentioning or referencing this software or this function. RSA Data Security, Inc. makes no representations concerning either the merchantability of this software or the suitability of this software for any particular purpose. It is provided" as is "without express or implied warranty of any kind. These notices must be retained in any copies of any part of this documentation and / or software. * / #include "global.h" #include "md2.h" static void MD2Transform PROTO_LIST ((unsigned Char [16], unsigned char [16], unsigned char [16])); static void md2_memcpy proto_list (Pointer, Pointer, Unsigned Int);
static void MD2_memset PROTO_LIST ((POINTER, int, unsigned int)); / * Permutation of 0..255 constructed from the digits of pi It gives a "random" nonlinear byte substitution operation * / static unsigned char PI_SUBST [256].. = {41, 46, 67, 201, 162, 216, 124, 1, 61, 54, 84, 161, 236, 240, 6, 19, 98, 167, 5, 243, 192, 199, 115, 140, 152, 147, 43, 217, 188, 76, 130, 202, 30, 155, 87, 60, 253, 212, 224, 22, 103, 66, 111, 24, 138, 23, 229, 18, 190, 78, 196, 214, 218, 158, 222, 73, 160, 251, 245, 142, 187, 47, 238, 122, 169, 104, 121, 145, 21, 178, 7, 63, 148, 194, 16, 137, 11, 34, 95, 33, 128, 127, 93, 154, 90, 144, 50, 39, 53, 62, 204, 231, 191, 247, 151, 3, 255, 25, 48, 179, 72, 165, 181, 209, 215, 94, 146, 42, 172, 86, 170, 198, 79, 184, 56, 210, 150, 164, 125, 182, 118, 252, 107, 226, 156, 116, 4, 241, 69, 157, 112, 89, 100, 113, 135, 32, 134, 91, 207, 101, 230, 45, 168, 2, 27, 96, 37, 173, 174, 176, 185, 246, 28, 70, 97, 105, 52, 64, 126, 15, 85, 71, 163, 3 5, 221, 81, 175, 58, 195, 92, 249, 206, 186, 197, 234, 38, 44, 83, 13, 110, 133, 40, 132, 9, 211, 223, 205, 244, 65, 129, 77, 82, 106, 220, 55, 200, 108, 193, 171, 250, 36, 225, 123, 8, 12, 189, 177, 74, 120, 136, 149, 139, 227, 99, 232, 109, 233, 203, 213, 254, 59, 0, 29, 57, 242, 239, 183, 14, 102, 88, 208, 228, 166, 119, 114, 248, 235, 117, 75, 10, 49, 68, 80, 180, 143, 237, 31, 26, 219, 153, 141, 51, 159, 17, 131, 20}; static unsigned char * Padding [] = {(unsigned char * ) "", (Unsigned char *) "/ 002/002", (unsigned char *) "/ 003/003/003", (Unsigned char *) "/ 004/004 / 004/004 ", (unsigned char *)" / 005/005/005/005/005 "
(Unsigned char *) "/ 006/006", (unsigned char *) "/ 007/007/007", (unsigned char *) "/ 010/010/010/010 "(unsigned char *)" / 011/011/011/011 "/ 011/011/011/011", (unsigned char *) "/ 012/012/012/012/012/012 "(unsigned char *)" / 013/013/013/013/013/013/013 " (Unsigned char *) "/ 014/014/014/014/014", (unsigned char *) "/ 015/015/015/015/015 / 015/015/015 ", (unsigned char *)" / 016/016/016/016/016/016/016/016/016/016/016/016/016 / 016, (unsigned char *) "/ 017/017/017/017/017/017/017 / 017", (unsigned char *) "/ 020 / 020/020/020/020/020/020/020/020/020/020/020/020 "}; / * md2 Initialization. Begins an md2 Operation, Writing a new context. * / Void Md2init (Context) MD2_CTX * Context; / * context * / {context-> count = 0; MD2_MEMSET ((Pointer) Context-> State, 0, SIZ eof (context-> state)); MD2_memset ((POINTER) context-> checksum, 0, sizeof (context-> checksum));} / * MD2 block update operation Continues an MD2 message-digest operation, processing another message block. , and updating the context * / void MD2Update (context, input, inputLen) MD2_CTX * context;. / * context * / unsigned char * input; / * input block * / unsigned int inputLen; / * length of input block * / { Unsigned int I, index, partlen; / * update number of bytes mod 16 * / index = context-> count; context-> count =
(Index Inputlen) & 0xF; Partlen = 16 - Index; / * Transform As Many Times as Possible. * / if (Inputlen> = Partle) {MD2_Memcpy ((Pointer) & Context-> Buffer [Index], (Pointer) Input , Partle); MD2Transform (Context-> State, Context-> Buffsum, Context-> buffer); for (i = partlen; i 15
/ * Form Encryption Block from State, Block, State ^ Block. * / Md2_memcpy ((Pointer) X, (Pointer) State, 16); MD2_MEMCPY ((Pointer) x 16, (Pointer) Block, 16); For i = 0; i <16; i ) x [i 32] = state [i] ^ block [i]; / * encrypt block (18 rounds). * / t = 0; for (i = 0; i < 18; i ) {for (j = 0; j <48; j ) T = x [j] ^ = pi_subst [t]; t = (t i) & 0xff;} / * save new state * / md2_memcpy (Pointer) X, 16); / * update checksum. * / T = checksum [15]; for (i = 0; i <16; i ) T = checksum [i] ^ = pi_subst [block [i] ^ T]; / * ZEROIZE SENSITIVE INFORMATION. * / MD2_MEMSET ((Pointer) x, 0, sizeof (x));} / * Note: Replace "for loop" with standard memcpy if Possible. * / static void MD2_MEMCPY (OUTPUT, INPUT, LEN) Pointer Output; Pointer Input; unsigned int LEN; {Unsigned Int i; for (i = 0; i without express or implied warranty of any kind. These notices must be retained in any copies of any part of this documentation and / or software. * / / * The following makes MD default to MD5 if it has not already been defined with C compiler flags . * / #ifndef md #ndif #include S ') MDString (argv [i] 2); Else IF (strcmp (argv [i], "-t") == 0) MDTIMETRIAL (); Else IF (Strcmp [i], "-x" ) == 0) mdtestsuite (); else mdfile (argv [i]); else mdfilter (); return (0);} / * Digests a string andprints the result. * / Static void mdstring (string) char * string {MD_CTX Context; Unsigned CHAR Digest [16]; Unsigned Int Len = Strlen (String); MDINIT (& Context); MdUpdate (& Context, String, Len); Mdfinal (Digest, & Context); Printf ("MD% D (/ "% s /") = ", md, string); mdprint (DiGest); Printf (" / n ");} / * MeasureS the time to digest test_block_count test_block_len-byte blocks. * / static void mdtime () {md_ctx context; time_t endTime, startTime; unsigned char block [TEST_BLOCK_LEN], digest [16]; unsigned int i; printf ( ". MD% d time trial Digesting% d% d-byte blocks ...", MD, TEST_BLOCK_LEN, TEST_BLOCK_COUNT ); / * Initialize block * / for (i = 0; i } / * Digests a reference suite of strings and prints the results. * / Static void mdtestsuite () {printf ("MD% D test suite: / n", md); mdstring (""); mdstring ("a") ; MDString ( "abc"); MDString ( "message digest"); MDString ( "abcdefghijklmnopqrstuvwxyz"); MDString ( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"); MDString ( "1234567890123456789012345678901234567890/1234567890123456789012345678901234567890");} / * Digests a file and prints the result. * / static void mdfile (filename) Char * filename; {file * file; md_ctx context; int Len; unsigned char buffer [1024], digest [16]; if (File = FOPEN (FileName, "RB")) = = NULL) PRINTF ("% s can't be opened / n", filename); else {mdinit (& context); while (len = fread (buffer, 1, 1024, file) MDUPDATE (& Context, Buffer, Len) Mdfinal (Digest, & Context); fclose (file); Printf ("MD% D (% s) =", MD, FileName); mdprint (Digest); Printf ("/ n");}} / * Digest S THE STANDARD INPUT AND Print; * / static void mdfilter () {md_ctx context; int Len; unsigned char buffer [16], Digest [16]; mdinit (& context); while (len = fread (buffer, 1, 16, stdin) MDUPDATE (& Context, Buffer, Len); Mdfinal (Digest, & Context); mdprint (Digest); Printf ("/ n");} / * Prints a message digest in Hexadecimal. * / Static void mdprint Digest) unsigned char digest [16]; {UNSIGNED INT i; for (i = 0; i <16; i ) Printf ("% 02x", Digest [i]);} A.5 Test Suite the MD2 Test Suite Driver option "-x" ) Should print the following results: MD2 test suite: MD2 ( "") = 8350e5a3e24c153df2275c9f80692773 MD2 ( "a") = 32ec01ec4a6dac72c0ab96fb34c0b5d1 MD2 ( "abc") = da853b0d3f88d99b30283a69e6ded6bb MD2 ( "message digest") = ab4f496bfb2a530b219ff33031fe06b0 MD2 ( "abcdefghijklmnopqrstuvwxyz") = 4e8ddff3650292ab5a4108c3aa47940b MD2 ( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789") = da33def2a42df13975352846c30338cd MD2 ( "123456789012345678901234567890123456789012345678901234567890123456 78901234567890") = d5976f79d83d3a0dc9806c3c66f3efd8 Security Considerations The level of security discussed in this memo is considered to be sufficient for implementing very high security hybrid digital signature schemes based on MD2 and a public-key cryptosystem Author's Address Burton S. Kaliski Jr. RSA Laboratories (a division of RSA Data Security, Inc.) 10 Twin Dolphin Drive Redwood City, CA 94065 Phone:. (415) 595-8782 FAX: (415) 595-4126 EMail: Burt @ rsa.com The MD4 Message-Digest Algorithm Status of thie Memo This memo provides information for the Internet community. It does not specify an Internet standard. Distribution of this memo is unlimited. Acknowlegements We would like to thank Don Coppersmith, Burt Kaliski, Ralph Merkle, and Noam Nisan for numerous helpful comments and suggestions Table of Contents 1. Executive Summary 1 2. Terminology and Notation 2 3. MD4 Algorithm Description 2 4. Summary 6 References 6 APPENDIX A -. Reference Implementation 6 Security Considerations 20 Author's Address 20 1. Executive Summary This document describes the MD4 message-digest algorithm [1]. The algorithm takes as input a message of arbitrary length and produces as output a 128-bit "fingerprint" or "message digest" of the input. It is conjectured that it is computationally infeasible to produce two messages having the same message digest, or to produce any message having a given prespecified target message digest. The MD4 algorithm is intended for digital signature applications, where a large file must be "compressed" in a secure manner before being encrypted with a private (secret) key under a public-key cryptosystem such as RSA. The MD4 algorithm is designed to be quite fast on 32-bit machines. In addition, the MD4 algorithm does not require any large substitution tables;. the algorithm can be coded quite compactly The MD4 algorithm is being placed in the public domain for review and possible adoption as a standard This document replaces the October 1990 RFC 1186 [2] The main difference is that the reference implementation.. Of MD4 in the appendix is more portable. for osi-based application In the X.509 Type Algorithmidentifier [3], The Parameters for MD4 SHOULD HAVE TYPE NULL. 2. Terminology and notation in this document a "Word" IS A 32-bit Quantity and A "Byte" is an ele ht-bit quantity. A sequence of bits can be becom interpreted in a natural manner as a sequence of bytes, where each consecutive group of eight bits is interpreted as a byte with the high-order (most significant) bit of each byte listed first. Similarly, a sequence of bytes can be interpreted as a sequence of 32-bit words, where each consecutive group of four bytes is interpreted as a word with the low-order (least significant) byte given first. Let x_i denote "x sub i". If the subscript is an expression, we surround IT IN BRACES, AS IN X_ {i 1}. Similarly, We Use ^ for SuperScripts (Exponentiation), SO That X ^ i Denotes x to the I-th Power. Let the symbol " " Denote Addition of Words (IE, MODULO-2 ^ 32 Addition). Let x <<< S Denote the 32-bit value obtained by circularly shifting (rotating) x left by s bit positions. let not (x) denote the bit- Wise complement of x, and let x v y Denote the bit-wise or of x and y. let x xor y denote the bit-wise xor of x and y, and let xy denote the bit-wise and of x and y. 3. MD4 Algorithm Description We begin by supposing that we have a b-bit message as input, and that we wish to find its message digest Here b is an arbitrary nonnegative integer;. b may be zero, it need not be a multiple of eight, and it may be arbitrarily large We imagine the bits of the message written down as follows:. m_0 m_1 ... m_ {b-1} The following five steps are performed to compute the message digest of the message 3.1 Step 1. , Append Padding Bits The Message IS "Padded" (Extended) SO That ITS Length (in Bits) IS CONGRUENT to 448, Modulo 512. That IS, The Message IS E xtended so that it is just 64 bits shy of being a multiple of 512 bits long Padding is always performed, even if the length of the message is already congruent to 448, modulo 512. Padding is performed as follows:. a single "1" Bit is appended to the message, and then "0" bits are appended so that the length in bits of the padded message becomes congruent to 448, modulo 512. In all, at least one bit and at most 512 bits are appended. 3.2 Step 2. Append Length A 64-bit representation of b ( the length of the message before the padding bits were added) is appended to the result of the previous step. In the unlikely event that b is greater than 2 ^ 64, then only the low-order 64 bits of b are used. (These bits are appended as two 32-bit words and appended low-order word first in accordance with the previous conventions.) At this point the resulting message (after padding with bits and with b) has a length that is an exact multiple of 512 bits Equivalently, this Message Has a Length That IS An Exact Multiple Of 16 (32-Bit) Words. Let M [0 ... N-1] Denote The Words of The Resulting Message, WHERE N IS A MULTIPLE OF 16.3.3 Step 3. Initialize MD Buffer A Four-Word Buffer (A, B, C, D) IS Used to Compute The Message Dige ST. Here Each of A, B, C, D IS A 32-Bit Register. these Registers Are Initialized to the Following Values in Hexadecimal, Low-Order Bytes First): Word A: 01 23 45 67 WORD B: 89 AB CD ef word C: fe dc ba 98 word D: 76 54 32 10 3.4 Step 4. Process Message in 16-Word Blocks We first define three auxiliary functions that each take as input three 32-bit words and produce as output one 32-bit Word. f (x, y, z) = xy v not (x) z g (x, y, z) = xy v xz v yz h (x, y, z) = x xor y xor z in Each bit position F ACTS AS A CONDITIONAL: IF X THEN Y ELSE Z. The Function F Could Have Been Defined Using INSTEAD OF V SINCE XY AND NOT (X) Z Will Never Have "1" Bits in The Same Bit Position. 0 "Bit. It is INTERESTING to Note That IF The Bits of X, Y, And Z Are Independent and UNBiad, The Each Bit of F (X, Y, Z) Will Be Independent and Unbiased, And Similarly Each Bit of G ( X, Y, Z) WILL BEDEPENDENT AND UNBISED. The function h is the bit-wise xor or parity "function" IT HAS Properties Similar to Those of f and g. do the following: Process Each 16-Word block. * / For i = 0 to n / 16-1 do / * Copy Block I Into x. * / for j = 0 to 15 do set x [j] to m [i * 16 j]. End / * of loop on j * / / * Save A AA, B AS BB, C AS CC, And D As Dd. * / AA = A BB = B CC = C DD = D / * ROUND 1. * / / * let [ABCD KS] Denote the Operation A = (A F (B, C, D) x [K]) <<< S. * / / / * do the f Ollowing 16 Operations. * / [Abcd 0 3] [CDAB 2 11] [BCDA 3 19] [ABCD 4 3] [DABC 5 7] [CDAB 6 11] [BCDA 7 19] [ABCD 8 3 ] [DABC 9 7] [CDAB 10 11] [BCDA 11 19] [ABCD 12 3] [DABC 13 7] [CDAB 14 11] [BCDA 15 19] / * Round 2. * / / * let [ABCD KS] DENOTE THE OPERATION A = (A G (B, C, D) X [K] 5A827999 <<< S. * / / * do the folload 16 Operations. * / [Abcd 0 3] [DABC 4 5] [CDAB 8 9] [BCDA 12 13] [ABCD 1 3] [DABC 5 5] [CDAB 9 9] [ BCDA 13 13] [DABC 6 5] [CDAB 10 9] [BCDA 14 13] [ABCD 3 3] [DABC 7 5] [CDAB 11 9] [BCDA 15 13] / * Round 3. * / / * Let [abcd ks] denote the Operation A = (A H (B, C, D) X [K] 6ed9eba1) <<< S. * / / * Do the folload 16 Operations. * / [ ABCD 0 3] [DABC 8 9] [CDAB 4 11] [ABCD 2 3] [DABC 10 9] [CDAB 6 11] [BCDA 14 15] [ABCD 1 3] [DABC 9 9] [ CDAB 5 11] [ABCD 3 3] [DABC 11 9] [CDAB 7 11] [BCDA 15 15] / * Then Perform The Following Additions. (That IS, INCREMENT EACH OF THE FOUR registers by the value IT HAD BEFORE this block was started.) * / a = a aa b = b bb c = C CC D = D DD end / * of loop on i * / note. The value 5a..99 is a hexadecimal 32-bit constant, Written with the high-order digit first. This constant represents The Square root of 2. The Octal Value of this constant is 013240474631. The value 6E..A1 is a hexadecimal 32-bit constant, written with the high-order digit first. This constant represents the square root of 3. The octal value of this constant is 015666365641. See Knuth, The Art of Programming, Volume 2 (SEMINUMERICAL Algorithms), Second Edition (1981), Addison-Wesley. Table 2, Page 660. 3.5 Step 5. Output The Message Digest Produced As Output IS A, B, C, D. That IS, WE Begin with the low-order byte of A, and end with the high-order byte of D. This completes the description of MD4. A reference implementation in C is given in the appendix. 4. Summary The MD4 message-digest algorithm is simple to Implement, and provides a "fingerprint" Or Message Digest of a Message of Arbitrar y length. It is conjectured that the difficulty of coming up with two messages having the same message digest is on the order of 2 ^ 64 operations, and that the difficulty of coming up with any message having a given message digest is on the order of 2 ^ 128 operations. The MD4 algorithm has been carefully scrutinized for weaknesses. It is, however, a relatively new algorithm and further security analysis is of course justified, as is the case with any new proposal of this sort. References [1] Rivest , R., "THE MD4 Message Digest Algorithm", In Aj Menezes and Sa Vanstone, Editors, Advances in Cryptology - Crypto ' 90 Proceedings, Pages 303-311, Springer-Verlag, 1991. [2] Rivest, R., "The MD4 Message Digest Algorithm", RFC 1186, MIT, October 1990. [3] CCITT Recommendation X.509 (1988), . "The Directory - Authentication Framework" [4] Rivest, R., "The MD5 Message-Digest Algorithm", RFC 1321, MIT and RSA Data Security, Inc, April 1992. APPENDIX A - Reference Implementation This appendix contains the following files : Global.h - Global HEADER FILE MD4.H - Header File for MD4 MD4C.C - Source Code for MD4 MDDriver.c - Test Driver for MD2, MD4 and MD5 The Driver Compiles for MD5 by Default But Can Compile for MD2 or MD4 if the symbol MD is defined on the C compiler command line as 2 or 4. The implementation is portable and should work on many different plaforms. However, it is not difficult to optimize the implementation on particular platforms, an exercise left To the reader. for example, on "Little- endian "platforms where the lowest-addressed byte in a 32- bit word is the least significant and there are no alignment restrictions, the call to Decode in MD4Transform can be replaced with a typecast. A.1 global.h / * GLOBAL.H -. RSAREF types and constants * / / * PROTOTYPES should be set to one if and only if the compiler supports function argument prototyping The following makes PROTOTYPES default to 0 if it has not already been defined with C compiler flags * / #ifndef PROTOTYPES. #define prototypes 0 #ENDIF / * POINTER Defines a generic pointer type * / typef unsigned char * Pointer; / * uint2 defines a two byte word * / typef unsigned short int uint2; / * UINT4 defines a four byte word * / typedef unsigned long int UINT4; / * PROTO_LIST is defined depending on how PROTOTYPES is defined above If using PROTOTYPES, then PROTO_LIST returns the list, otherwise it returns an empty list * / #if.. Prototype #define proto_list (list) list #else #define proto_list () #ENDIF A.2 MD4.H / * md4.h - Header File for MD4C * / / * CopyRight (c) 1991-2, RSA Data Security, Inc. Created 1991. All rights reserved. License to copy and use this software is granted provided that it is identified as the "RSA Data Security, Inc. MD4 Message-Digest Algorithm" in all material mentioning or referencing this software or this function. License is also granted to make and use derivative works provided that such works are identified as "derived from the RSA Data Security, Inc. MD4 Message-Digest Algorithm" in all material mentioning or referencing the derived work. RSA Data Security , Inc. Makes no representations conce rning either the merchantability of this software or the suitability of this software for any particular purpose. It is provided "as is" without express or implied warranty of any kind. These notices must be retained in any copies of any part of this documentation and / OR software. * / / * md4 context. * / typef struct {uint4 state [4]; / * state (abcd) * / uint4 count [2]; / * Number of Bits, MODULO 2 ^ 64 (LSB first) * / Unsigned char buffer [64]; / * input buffer * /} MD4_CTX; Void MD4init proto_list ((MD4_CTX *)); Void MD4UPDATE PROTO_LIST ((MD4_CTX *, unsigned char *, unsigned int)); Void Md4Final Proto_List ((unsigned char [16), md4_ctx *)); A.3 MD4C.C / * MD4C.C - RSA Data Security, Inc., MD4 Message-Digest Algorithm * / / * Copyright (C) 1990- 2, RSA Data Security, Inc. All rights reserved. License to copy and use this software is granted provided that it is identified as the "RSA Data Security, Inc. MD4 Message-Digest Algorithm" in all material mentioning or referencing this software or this function. License is also granted to make and use derivative works provided that such works are identified as "derived from the RSA Data Security, MD4 Message-Digest Algorithm Inc." in all material mentioning or referencing the derived work. RSA Data Security, Inc. makes no representations concerning either the merchantability of this software or the suitability of this software for any particular purpose. It is provided "as is" without express or implied warranty of any kind. These notices must be retained in any copies of any part Of this documentation and / or software. * / #include "global.h" #include "md4.h" / * constants for md4transform routine. * / #define s11 3 #define s12 7 #define s13 11 #define s14 19 # Define s22 5 #define s22 5 #define s23 9 #define s24 13 #define s31 3 #define s32 9 #define s33 11 #define s34 15 static void md4transform proto_list ((uint4 [4), unsigned char [64])); static void Encode PROTO_LIST ((unsigned char *, UINT4 *, unsigned int)); static void Decode PROTO_LIST ((UINT4 *, unsigned char *, unsigned int)); static void MD4_memcpy PROTO_LIST ((POINTER, POINTER, unsigned int)) static void MD4_MEMSET Proto_List (Pointer, INT, Unsigned Int); static unsigned char Padding [64] = {0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 , 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 , 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; / * f, g and h are basic md4 functions. * / #Define f (x, Y, Z) | ((x) & (y))) #define g (x, y, z) ((x) & (y) | (x ) & (z)) | ((Y) & (z))) #define h (x, y, z) ((x) ^ (y) ^ (z)) / * rotate_left rotates x left n bits. * / #define rotate_left (x, n) ((x) << (n)) | ((x) >> (32- (n)))) / * ff, gg and hh area, GG and HH Are Transformations for rounds 1, 2 And 3 * / / * rotation is ass, from addition to prevent recomputation * / #define FF (A, B, C, D, X, S) {/ (a) = f ((b), (c), d)) (x); / (a) = rotate_left ((a)); /} #define gg (A, B, C, D, X, S) {/ (a) = g ((b), (c), (d)) (x) (uint4) 0x5a827999; / (a) = rotate_left ((a), (s)); /} #define hh (a, b, c , D, X, S) {/ (a) = h ((b), (c), (d)) (x) (uint4) 0x6ed9eba1; / (a) = rotate_left ((a), s)); /} / * MD4 Initialization. Begins AN MD4 Operation, Writing a new context. * / Void MD4init (context) MD4_CTX * Context; / * context * / {context-> count [0] = context-> count [1] = 0; / * Load Magic Initialization Constants. * / Context-> State [0] = 0x67452301; Context-> State [1] = 0xEfcdab89; context-> state [2] = 0x98badcfe; context-> state [3] = 0x10325476; / * MD4 Block Update Operation. Continues AN MD4 Message-Digest Operation, Processing Another Message Block, and Updating the Context. * / Void Md4Update (Context, Input, Inputlen) MD4_CTX * Context; / * Context * / unsigned char * input; / * input block * / unsigned int inputLen; / * length of input block * / {unsigned int i, index, partLen; / * Compute number of bytes mod 64 * / index = ( Unsigned int ((Context-> Count [0] >> 3) & 0x3f); / * update number of bits * / if ((Context-> count [0] = ((uint4) Inputlen << 3)))) <(Uint4) Inputlen << 3)) Context-> Count [1] ; context-> count [1] = ((uint4) Inputlen >> 29); Partlen = 64 - Index; / * Transform AS MD4_MEMCPY ((POINTER) & context-> buffer [indext-> buffer "; md4transform (context-> state, context-> buffer); for (i = Partlen; i 63 56)? (56 - index): (120 - index); MD4UPDATE (CONTEXT, PADDING, PADLEN); / * append length (before padding) * / MD4Update (Context, Bits, 8); / * Store State In Digest * / Encode (Digest, Context-> State, 16); / * Zeroize Sensitive Information. * / MD4_MEMSET ((Pointer) Context, 0, SizeOf (* Context));} / * MD4 Basic Transformation. Transforms State Based on Block. * / static void MD4Transform (State, Block) uint4 state [4]; unsigned char block [64]; {uint4 a = state [0], b = state [1], c = state [2], d = state [ 3], x [16]; decode (x, block, 64); / * ROUND 1 * / ff (A, B, C, D, X [0], S11); / * 1 * / ff (D, A, B, C, X [1], S12); / * 2 * / ff (C, D, A, B, X [2], S13); / * 3 * / ff (B, C, D, A, X [3], S14; / * 4 * / ff (A, B, C, D, X [4], S11); / * 5 * / ff (D, A, B, C, X [ 5], S12); / * 6 * / ff (C, D, A, B, X [6], S13); / * 7 * / ff (B, C, D, A, X [7], S14 ); / * 8 * / ff (A, B, C, D, X [8], S11); / * 9 * / ff (D, A, B, C, X [9], S12); / * 10 * / ff (C, D, A, B, X [10], S13 ); / * 11 * / ff (B, C, D, A, X [11], S14); / * 12 * / ff (A, B, C, D, X [12], S11); / * 13 * / ff (D, A, B, C, X [13], S12); / * 14 * / ff (C, D, A, B, X [14], S13); / * 15 * / ff (B, C, D, A, X [15], S14); / * 16 * / / * ROUND 2 * / GG (A, B, C, D, X [0], S21); / * 17 * / GG (D, A, B, C, X [4], S22); / * 18 * / gg (C, D, A, B, X [8], S23); / * 19 * / gg (B , C, D, A, X [12], S24); / * 20 * / gg (A, B, C, D, X [1], S21); / * 21 * / gg (D, A, B , C, X [5], S22); / * 22 * / gg (C, D, A, B, X [9], S23); / * 23 * / GG (B, C, D, A, X [13], S24); / * 24 * / gg (A, B, C, D, X [2], S21); / * 25 * / gg (D, A, B, C, X [6], S22); / * 26 * / gg (C, D, A, B, X [10], S23); / * 27 * / gg (B, C, D, A, X [14], S24); / * 28 * / gg (A, B, C, D, X [3], S21); / * 29 * / gg (D, A, B, C, X [7], S22); / * 30 * / GG (C, D, A, B, X [11], S23); / * 31 * / gg (B, C, D, A, X [15], S24); / * 32 * / / * Round 3 * / hh (A, B, C, D, X [0], S31); / * 33 * / HH (D, A, B, C, X [8], S32); / * 34 * / HH (C, D, A, B, X [4], S33); / * 35 * / HH (B, C, D, A, X [12], S34); / * 36 * / HH (A, B , C, D, X [2], S31); / * 37 * / HH (D, A, B, C, X [10], S32); / * 38 * / HH (C, D, A, B , X [6], S33); / * 39 * / HH (B, C, D, A, X [14], S34); / * 40 * / HH (A, B, C, D, X [1 ], S31); / * 41 * / HH (D, A, B, C, X [9], S32); / * 42 * / HH (C, D, A, B, X [5], S33) ; / * 43 * / hh (B, C, D, A, X [13], S34); / * 44 * / HH (A, B, C, D, X [3], S31); / * 45 * / HH (D, A, B, C, X [11], S32); / * 46 * / HH (C, D, A, B, X [7], S33); / * 47 * / HH ( B, C, D, A, X [15], S34); / * 48 * / state [0] = a; state [1] = b; state [2] = C; State [3] = D; / * ZEROIZE SENSITIVE INFORMATION. * / MD4_MEMSET ((Pointer) x, 0, sizeof (x));} / * encodes input (UINT4) INTO OUTPUT (UNSIGNED Char). Assumes Len Is A Multiple of 4. * / Static Void Encode (Output, Input, LEN) Unsigned Char * Output; UINT4 * INPUT; UNSIGNED INT LEN; {UNSIGNED INT I, J; For (i = 0, j = 0; j Unsigned char * input; unsigned int LEN; {Unsigned INT i, J; for (i = 0, j = 0; j md5.h "#endif / * Length of test block, number of test blocks * / #define TEST_BLOCK_LEN 1000 #define TEST_BLOCK_COUNT 1000 static void MDString PROTO_LIST ((char *));. static void MDTimeTrial PROTO_LIST ((void)); static Void mdtestsuite proto_list (void)); static void mdfile proto_list ((char *)); static void mdfilter proto_list (void)); static void mdprint proto_list ((unsigned char [16)); #IF MD == 2 #define MD_CTX MD2_CTX #define MDInit MD2Init #define MDUpdate MD2Update #define MDFinal MD2Final #endif #if MD == 4 #define MD_CTX MD4_CTX #define MDInit MD4Init #define MDUpdate MD4Update #define MDFinal MD4Final #endif #if MD == 5 #define MD_CTX MD5_CTX #define MDInit MD5Init #define MDUpdate MD5Update #define MDFinal MD5Final #endif / * Main driver Arguments (may be any combination): -sstring - digests string -t - runs time trial -x - runs test script filename - digests file. (NONE) - DIGESTS Standard Input * / Int Main (Argc, Argv) INT Argc; char * argv []; {INT i; if (argc> 1) for (i = 1; i Mdfinal (Digest, & Context); Printf ("MD% D (/"% s / ") =", md, string); mdprint (Digest); Printf ("/ n");} / * MeasureS The Time to Digest . TEST_BLOCK_COUNT TEST_BLOCK_LEN-byte blocks * / static void MDTimeTrial () {MD_CTX context; time_t endTime, startTime; unsigned char block [TEST_BLOCK_LEN], digest [16]; unsigned int i;. printf ( "MD% d time trial Digesting% d % D-BYTE BLOCKS ... ", MD, Test_block_len, test_block_count); / * Initialize block * / for (i = 0; i } / * Digate. * / Static void mdfile (filename) char * filename; {file * file; md_ctx context; int Len; unsigned char buffer [1024], digest [16]; if ((File) = FOPEN (FileName, "RB"))) == NULL) Printf ("% s can't be opened / n", filename); else {mdinit (& context); while (len = fread (buffer, 1, 1024, File)) MDUPDATE (& Context, Buffer, Len); Mdfinal (Digest, & Context); fclose (file); Printf ("MD% D (% s) =", MD, FileName); MDPrint (Digest); Printf (" / N ");}} / * Digests the standard. * / static void mdfilter () {md_ctx context; int Len; unsigned char buffer [16], Digest [16]; mdinit (& context); while (Len = FREAD (Buffer, 1, 16, Stdin) MDUPDATE (& Context, Buffer, Len); Mdfinal (Digest, & Context); Mdprint (Digest); Printf ("/ n");} / * Prints a Message Digest In Hexadecimal. * / static void mdprint (Digest) unsigned char digest [16]; {UNSIGNED INT i; for (i = 0; i <16; i ) Printf ("% 02x", Digest [i]);} A.5 Test Suite the MD4 Test Suite (Driver option "-x") Should Print The Following Results: MD4 Test Suite: MD4 ( "") = 31d6cfe0d16ae931b73c59d7e0c089c0 MD4 ( "a") = bde52cb31de33e46245e05fbdbd6fb24 MD4 ( "abc") = a448017aaf21d8525fc10ae87aa6729d MD4 ( "message digest") = d9130a8164549fe818874806e1c7014b MD4 ( "abcdefghijklmnopqrstuvwxyz") = d79e1c308aa5bbcdeea8ed63df412da9 MD4 ( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789") = 043f8582f241db351ce627e153e7f0e4 MD4 ( " 123456789012345678901234567890123456789012345678901234567890123456 78901234567890 ") = e33b4ddc9c38f2199c3e7b164fcc0536 Security Considerations The level of security discussed in this memo is considered to be sufficient for implementing moderate security hybrid digital- signature schemes based on MD4 and a public-key cryptosystem. We do not know of any reason that MD4 would not be sufficient for implementing very high security digital-signature schemes, but because MD4 was designed to be exceptionally fast, it is "at the edge" in terms of risking successful cryptanalytic attack. After further critical review, it may be appropriate to consider MD4 for very high security applications. for very high security applications before the completion of that review, the MD5 algorithm [4] is recommended. Author's Address Ronald L. Rivest Massachusetts Institute of Technology Laboratory for Computer Science NE43-324 545 Technology Square Cambrid GE, MA 02139-1986 Phone: (617) 253-5880 Email: Rivest @ theory.lcs.mit.edu Network Working Group R. Rivest Request for Comments: 1321 MIT Laboratory for Computer Science and RSA Data Security, Inc. April 1992 The MD5 Message-Digest Algorithm Status of this Memo This memo provides information for the Internet community . It does not specify an Internet standard. Distribution of this memo is unlimited. Acknowlegements We would like to thank Don Coppersmith, Burt Kaliski, Ralph Merkle, David Chaum, and Noam Nisan for numerous helpful comments and suggestions. Table of Contents 1. Executive Summary 1 2. Terminology and notation 2 3. MD5 Algorithm Description 3 4. Summary 6 5. Differences Between MD4 and MD5 6 References 7 APPENDIX A -. Reference Implementation 7 Security Considerations 21 Author's Address 21 1. Executive Summary This document describes the MD5 message-digest algorithm The algorithm takes as input a message of arbitrary length and produces as Output a 128-bit "fingerprint" or "message digest" of the input. It is conjectured that it is computationally infeasible to produce two messages having the same message digest, or to produce any message having a given prespecified target message digest. The MD5 algorithm is intended for digital signature applications, where a large file must be "compressed" in a secure manner before being encrypted with a private (secret) key under a public-key cryptosystem such as RSA. The MD5 algorithm is designed to be quite fast on 32-bit machines. in addition, the MD5 algorithm does not require any large substitution tables;. the algorithm can be coded quite compactly The MD5 algorithm is an extension of the MD4 message-digest algorithm 1,2] MD5 is slightly slower than MD4, but is more "conservative" in design MD5.. Was Designed Because It Was Felt That MD4 WAS Perhaps Being Adopted for Use More Quickly Than Justified by The Existing Critical Review; Because MD4 WASDESIGNED TO BE Exceptionally Fast, it is "at the edge" in terms of risking successful cryptanalytic attack. MD5 backs off a bit, giving up a little in speed for a much greater likelihood of ultimate security. It incorporates some suggestions made by various reviewers, and contains additional optimizations. The MD5 algorithm is being placed in the public domain for review and possible adoption as a standard. for OSI-based applications, MD5's object identifier is md5 OBJECT iDENTIFIER :: = iso (1) member-body (2) US (840) rsadsi (113549) Digestalgorithm (2) 5} in the X.509 Type Algorithmidentifier [3], The Parameters for MD5 SHOULD HAVE TYPE NULL. 2. Terminology and notation in this document a "Word" is a 32-bit quantity and a "byte" is an eight-bit quantity. A sequence of bits can be interpreted in a natural manner as a sequence of bytes, where each consecutive group of eight bits is interpreted as a byte with the high -order (most significant) bit of each byte listed first. Similarly, a sequence of bytes can be interpreted as a sequence of 32-bit words, where each consecutive group of four bytes is interpreted as a word with the low-order (least Significant) Byte Given First. Let X_i Denote "X Sub I". If The Subscript IS An Expression, WE Surround IT IN BRACES, AS IN X_ {i 1}. Similarly, We Use ^ for SuperScripts (Exponentiation), SO That X ^ I Denotes x to the I-th Power. Let the symbol " " Denote Addition of Words (IE, MODULO-2 ^ 32 Addition). Let x <<< S Denote the 32-bit value obtained by circularly shifting Rotating) x left by s bit positions. let not (x) denote the bit-wise complement of x, and let x v y denote the bit-wise or of x AND Y. let x xor y denote the bit-wise xor of x and y, and let xy denote the bit-wise and of off x and y.3. MD5 Algorithm Description We Begin by Supposing That We Have A B-bit Message AS input, and that we wish to find its message digest Here b is an arbitrary nonnegative integer;. b may be zero, it need not be a multiple of eight, and it may be arbitrarily large We imagine the bits of the message written down. As Follows: M_0 m_1 ... m_ {b-1} the folline fin confnes.......................................................... (Extended) so that its length (in bits) is congruent to 448, modulo 512. That is, the message is extended so that it is just 64 bits shy of being a multiple of 512 bits long. Padding is always performed, even if The Length of the Message IS Already Congruent To 448, Modulo 512. Padding Is Performed As Follows: a Single "1" Bit is appended to the message, and then "0" bits are appended so that the length in bits of the padded message becomes congruent to 448, modulo 512. In all, at least one bit and at most 512 bits are appended. 3.2 Step 2. Append Length A 64-bit representation of b ( the length of the message before the padding bits were added) is appended to the result of the previous step. In the unlikely event that b is greater than 2 ^ 64, then only the low-order 64 bits of b are used. (These bits are appended as two 32-bit words and appended low-order word first in accordance with the previous conventions.) At this point the resulting message (after padding with bits and with b) has a length that is an exact multiple of 512 bits Equivalently, this Message Has a Length That IS An Exact Multiple Of 16 (32-Bit) Words. Let M [0 ... N-1] Denote The Words of The Resulting Message, WHERE N IS A MULTIPLE OF 16.3.3 Step 3. Initialize MD Buffer A Four-Word Buffer (A, B, C, D) IS Used to Compute The Message Dige ST. Here Each of A, B, C, D IS A 32-Bit Register. these Registers Are Initialized to the Following Values in Hexadecimal, Low-Order Bytes First): Word A: 01 23 45 67 WORD B: 89 AB CD Ef Word C: Fe DC Ba 98 Word D: 76 54 32 10 3.4 Step 4. Process Message In 16-Word Blocks We First Define Four Auxiliary Functions That Each Take AS Input Three 32-Bit Words and Product As ONE 32-BIT Word. f (x, y, z) = xy v not (x) z g (x, y, z) = xz v y NOT (Z) h (x, y, z) = x xor y xor z i ( X, y, z) = y xor (x v not (z)) in Each Bit Position f ACTS AS A CONDITIONAL: IF X THEN Y ELSE Z. The Function F Could Have Been Defined Using INSTEAD OF NEVER HAVE 1'S INDEPESTINT AND UNETER THE INDEPENT AND UNISTED, THE INDEPEN , Y, Z) Will be independent and unbiad. The functions g, h, and i are similar to the function f, in That the Act in "Bitwise Parallel" To Produce Their Output from the Bits of X, Y, And Z, In Such A Manner That IF The Corresponding Bits of X, Y, And Z Are Independent and UNBiad, THEN Each Bit of G (X, Y, Z), H (X, Y, Z), AND i (x, y, Z) Will be independent and unbiad. Note That the function h is the bit-wise "xor" Parity "Function of ITS INPUTS. THIS STEP Uses A 64-Element Table T [1 ... 64] Constructed from the sine Function. Let T [I] Denote The I-TH ELEMENT OF THE TABLE, WHICH IS Equal to the INTEGER Part of 4294967296 Times ABS (SIN (I)), WHERE I is in radians. The elements of the table area Appendix. Do The Following: / * Process Each 16-word block. * / For i = 0 to n / 16-1 do / * Copy Block I Into x. * / for j = 0 to 15 DO SET X [J] To M [i * 16 j]. END / * OF LOOP ON J * / / * SAVE A AA, B AS BB, C AS CC, AND D AS Dd. * / AA = A BB = B CC = C DD = D / * ROUND 1. * / / * Let [abcd ksi] DENOTE The OPERATION A = B ((A F (B, C, D) X [K] T [I]) <<< s). * / / * do the folload 16 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] [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] / * Round 2. * / / * let [ABCD KSI] DENOTE THE OPERATION A = B ((A G (B, C, D) X [K] T [I]) <<< s). * / / * Do the folload 16 Operations. * / [Abcd 1 5 17] [DABC 6 9 18] [CDAB 11 14 19] [BCDA 0 20 20] [ABCD 5 5 21] [CDAB 15 14 23] [ABCD 9 5 25] [DABC 14 9 26] [CDAB 3 14 27] [BCDA 8 20 28] [ABCD 13 5 29 ] [DABC 2 9 30] [BCDA 12 20 32] / * ROUND 3. * / / * let [ABCD KST] DENOTE The Operation A = B ((A H (B, C, D) X [K] T [I]) <<< s). * / / * do the folload 16 Operations. * / [Abcd 5 4 33] [DABC 8 11 34 [CDAB 11 16 35] [ABCD 1 4 37] [CDAB 7 16 39] [BCDA 10 23 40] [ABCD 13 4 41] [DABC 0 11 42] [ CDAB 3 16 44] [ABCD 9 4 45] [DABC 12 11 46] [CDAB 15 16 47] [BCDA 2 23 48] / * ROUND 4. * / / * let [ABCD KST] DENOTE The Operation A = B ((A I (B, C, D) X [K] T [I]) <<< s). * / / * do the folload 16 Operations. * / [Abcd 0 6 49] [CDAB 14 15 51] [BCDA 5 21 52] [ABCD 12 6 53] [DABC 3 10 54 [CDAB 10 15 55] [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] / * Then Perform The Following Additions. (That INCREMENT EACH OF THE FOUR Registers by The Value It Had Before This Block Was Started.) * / A = A AA B = B BB C = C CC D = D DD END / * OF LOOP ON I * / 3.5 Step 5. Output The Message Digest Produced As Output IS A, B, C, D. That IS, WE Begin with the low low order byte of A, and end with the high-order byte of D. This completes the description of MD5. A reference implementation in C is given in the appendix. 4. Summary The MD5 message-digest algorithm is simple to implement, and provides a "fingerprint" or message digest of a message of arbitrary length. It is conjectured that the difficulty of coming up with two messages having the same message digest is on the order of 2 ^ 64 operations, and that the difficulty of coming up with any message having a given message digest is on the order of 2 ^ 128 operations. The MD5 algorithm has been carefully scrutinized for weaknesses. It is, however, a relatively new algorithm and further security analysis is of course justified, as is the case with any new proposal of this . sort 5. Differences Between MD4 and MD5 The following are the differences between MD4 and MD5: 1. A fourth round has been added 2. Each step now has a unique additive constant 3. The function g in round 2 was changed from.. (XZ V xz v yz) TO (XZ V y NOT (Z)) to make g less symmetric. 4. Each Step Now add. This Promotes A Faster "Avalanche Effect". 5. TH e order in which input words are accessed in rounds 2 and 3 is changed, to make these patterns less like each other. 6. The shift amounts in each round have been approximately optimized, to yield a faster "avalanche effect." The shifts in DiffERENT ROUNDS Are Distinct. References [1] Rivest, R., "The MD4 Message Digest Algorithm", RFC 1320, Mit and RSA Data Security, Inc., April 1992. [2] Rivest, R., "THE MD4 Message Digest Algorithm ", In Aj Menezes and Sa Vanstone, Editors, Advances in cryptology - crypto '90 proceedings, pages 303-311, springer-verlag, 1991. [3] ccitt recommendation X.509 (1988)," The Directory - Authentication Framework "APPENDIX A - Reference Implementation This appendix contains the following files taken from RSAREF:. A Cryptographic Toolkit for Privacy-Enhanced Mail: global.h - global header file md5.h - header file for MD5 md5c. C - Source Code for MD5 for more information on rsaref, send email to / * PROTO_LIST is defined depending on how PROTOTYPES is defined above. If using PROTOTYPES, then PROTO_LIST returns the list, otherwise it returns an empty list. * / #If PROTOTYPES #define PROTO_LIST (list) list #else #define PROTO_LIST (list) () #ENDIF A.2 MD5.H / * MD5.H - Header File for MD5c.c * / / * Copyright (c) 1991-2, RSA Data Security, Inc. Created 1991. All Rights Reserved. license to copy and use this software is granted provided that it is identified as the "RSA Data Security, Inc. MD5 Message-Digest Algorithm" in all material mentioning or referencing this software or this function. License is also granted to make and use derivative works provided that such works are identified as "derived from the RSA Data Security, Inc. MD5 Message-Digest Algorithm" in all material mentioning or referencing the derived work. RSA Data Security, Inc. makes no representations concerning either the merchantability of this software or the suitability Of this software for any particular pur pose. It is provided "as is" without express or implied warranty of any kind. These notices must be retained in any copies of any part of this documentation and / or software. * / / * MD5 context. * / typedef struct {UINT4 State [4]; / * State (abcd) * / uint4 count [2]; / * Number of Bits, MODULO 2 ^ 64 (LSB first) * / unsigned char buffer [64]; / * input buffer * /} MD5_CTX void md5init proto_list ((MD5_CTX *)); Void Md5Update Proto_List ((MD5_CTX *, Unsigned Char *, unsigned int)); Void MD5Final Proto_List (UNSIGNED CHAR [16], MD5_CTX *)); A.3 MD5C.C / * MD5C.C - RSA Data Security, Inc., MD5 Message-Digest Algorithm * / / / * Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All Rights Reserved. License to copy and use this software is granted provided that it is identified as the "RSA Data Security, Inc. MD5 Message-Digest Algorithm" in all material mentioning or referencing this software or this function. License is also granted to make and use derivative works provided that such works are identified as "derived from the RSA Data Security, Inc. MD5 Message-Digest Algorithm" in all material mentioning or referencing the derived work. RSA Data Security, Inc. makes no representations concerning either the merchantability of this software or the suitability of this software for any particular purpose. It is provided "as is" without express or implied warranty of any kind. These notices must be retained in any copies of any part of this documentation and / or software. * / #include " Global.h "#include" md5.h "/ * c OnStants for MD5Transform Routine. * / #define S11 7 #define S12 12 #define S13 17 #define S14 22 #define S21 5 #define S22 9 #define S23 14 #define S24 20 #define S31 4 #define S32 11 #define S33 16 #define s34 23 #define s41 6 #define s42 10 #define s43 15 #define s44 21 static void md5transform proto_list ((uint4 [4), unsigned char [64])); static void encode proto_list ((unsigned char *, UINT4 *, unsigned int)); static void Decode PROTO_LIST ((UINT4 *, unsigned char *, unsigned int)); static void MD5_memcpy PROTO_LIST ((POINTER, POINTER, unsigned int)); static void MD5_memset PROTO_LIST ((POINTER, int , unsigned int); static unsigned charphadding [64] = {0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 , 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 , 0, 0, 0, 0, 0, 0, 0, 0, 0};, / * f, g, h and i are basic md5 functions. * / #Define f X, Y, Z) ((x) & (Y)) | ((~ x) & (z))) #define g (x, y, z) ((x) & (z)) | (Y) & (~ z))) #define h (x, y, z) ((x) ^ (y) ^ (z)) #define i (x, y, z) ((y) ^ (((y) ^ x) | (~ z))) / * rotate_left rotates x left n bits. * / #define rotate_left (x, n) (((x) << (n)) | ((x) >> (32-) N)))))))) / * ff, gg, hh, and II transformations for rots 1, 2, 3, and 4. rotation is ass, * / #define FF (A, B, C, D, X, S, AC) {/ (a) = f ((b), (c)) (x) (uint4) (AC); / (a) = rotate_left ((a), (s)); / (a) = (b); /} #define gg (A, B, C, D, X, S, AC) {/ (a) = g ((b), (c ), (d)) (x) (UINT4) (AC); / (a) = rotate_left ((a), (s)); / (a) = (b); /} #define hh A, B, C, D, X, S, AC) {/ (a) = h ((b), (c), (d)) (x) (U INT4) (AC); / (a) = rotate_LEFT ((a), (s)); / (a) = (b); /} #define II (A, B, C, D, X, S, AC) {/ (a) = I ((b), (c), (d)) (x) (UINT4) (AC); / (a) = rotate_left ((a), (s)) ; / (a) = (b); /} / * md5 initialization. Begins an md5 Operation, Writing a new context. * / void md5init (context) md5_ctx * context; / * context * / {context-> count [ 0] = context-> count [1] = 0; / * load magic initialization constants. * / Context-> state [0] = 0x67452301; context-> state [1] = 0xefcdab89; context-> state [2] = 0x98badcfe; context-> state [3] = 0x10325476;} / * MD5 block update operation Continues an MD5 message-digest operation, processing another message block, and updating the context * / void MD5Update (context, input, inputLen) MD5_CTX * context;.. / * context * / unsigned char * input; / * input block * / unsigned int inputLen; / * length of input block * / {unsigned int i, index, partLen; / * Compute number of bytes mod 64 * / index = (unsigned int ((Context-> Count [0] >> 3) & 0x3f); / * update number of bits * / if ((Context-> count [0] = (uint4) Inputlen << 3)) <( (UINT4) INPUTLEN << 3)))) Context-> Count [1] ; context-> count [1] = ((uint4) Inputlen >> 29); Partlen = 64 - Index; / * Transform As Many Times AS POSSIBLE. * / IF (Inputlen> = Partle) {MD5_MEMCPY ((Pointer) & context-> buffer [index], (pointer) INPUT, PARTLEN; MD5TRANSFORM (Context-> State, Context-> Buffer); for (i = Partlen; i 63 / * Save Number of Bits * / Encode (Bits, Context-> Count, 8); / * Pad out to 56 mod 64. * / index = (unsigned int) ((context-> count [0) >> 3) & 0x3f); Padlen = (INDEX <56)? (56 - index): (120 - index); Md5Update (Context, Padding, Padlen); / * append length (before padding) * / md5Update (Context, Bits, 8 ); / * Store State in Digest * / Encode (Digest, Context-> State, 16); / * ZEROIZE SENSITIVE INFORMATION. * / MD5_MEMSET ((Pointer) Context, 0, SizeOf (* Context));} / * md5 Basic Transformation. Transforms State Based on Block. * / Static Void Md5Transform (State, Block) uint4 state [4]; unsigned char block [64]; {uint4 a = state [0], b = state [1], c = State [2], D = State [3], x [16]; decode (x, block, 64); / * Round 1 * / ff (A, B, C, D, X [0], S11, 0XD76AA478 ); / * 1 * / ff (D, A, B, C, X [1], S12, 0xE8C7B756); / * 2 * / ff (C, D, A, B, X [2], S13, 0X242070DB ); / * 3 * / ff (B, C, D, A, X [3], S14, 0XC1BDCEEE); / * 4 * / ff (A, B, C, D, X [4], S11, 0XF57C0FAF ); / * 5 * / ff (D, A, B, C, X [5], S12, 0x4787C62A); / * 6 * / ff (C, D, A, B, X [6], S13, 0XA8304613); / * 7 * / ff (B, C, D, A, X [7], S14, 0XFD469501); / * 8 * / ff (A, B, C, D, X [8], S11, 0X698098D8); / * 9 * / ff (D, A, B, C, X [9], S12, 0x8B44F7AF); / * 10 * / ff (C, D, A, B, X [10], S13, 0xFFFFF5BB1); / * 11 * / ff (B, C, D, A, X [11], S14, 0X895CD7BE); / * 12 * / ff (A, B, C, D, X [12], S11, 0x6b901122); / * 13 * / ff (D, A, B, C, X [13], S12, 0xFD987193); / * 14 * / ff (C, D, A, B, X [14], S13, 0xA679438E); / * 15 * / ff (B, C, D, A, X [15], S14, 0X49B40821); / * 16 * / / * ROUND 2 * / GG (A, B, C, D, X [1], S21 0xF61e2562); / * 17 * / gg (D, A, B, C, X [6], S22, 0XC040B340); / * 18 * / gg (C, D, A, B, X [11], S23, 0X265E5A51); / * 19 * / gg (B, C, D, A, X [0], S24, 0XE9B6C7AA); / * 20 * / gg (A, B, C, D, X [5], S21, 0XD62F105D); / * 21 * / gg (D, A, B, C, X [10], S22, 0x2441453); / * 22 * / gg (C, D, A, B, X [15], S23, 0XD8A1E681); / * 23 * / gg (B, C, D, A, X [4], S24, 0XE7D3FBC8); / * 24 * / gg (A, B, C, D, X [9], S21, 0x21E1CDE6); / * 25 * / gg (D, A, B, C, X [14], S22, 0XC33707D6); / * 26 * / gg (C, D, A, B, X [3], S23, 0XF4D50D87); / * 27 * / gg (B, C, D, A, X [8], S24, 0X455A14ED); / * 28 * / gg (A, B, C, D, X [13], S21, 0XA9E3E905); / * 29 * / gg (D, A, B, C, X [2], S22, 0XFCEFA3F8); / * 30 * / gg (C, D, A, B, X [7], S23, 0x676F02D9); / * 31 * / gg (B, C, D, A, X [12], S24, 0X8D2A4C8A); / * 32 * / / * ROUND 3 * / HH (A, B, C, D, X [5], S31, 0xFFFA3942); / * 33 * / HH (D, A, B, C, X [8] , S32, 0x8771F681); / * 34 * / HH (C, D, A, B, X [11], S33, 0x6D9D6122); / * 35 * / HH (B, C, D, A, X [14] , S34, 0xFDE5380C); / * 36 * / HH (A, B, C, D, X [1], S31, 0XA4BEE A44); / * 37 * / hh (D, A, B, C, X [4], S32, 0x4BDECFA9); / * 38 * / HH (C, D, A, B, X [7], S33, 0xF6bb4b60); / * 39 * / hh (B, C, D, A, X [10], S34, 0XBEBFBC70); / * 40 * / HH (A, B, C, D, X [13], S31, 0x289B7EC6); / * 41 * / hh (d, a, b, c, x [0], s32, 0xeaa127fa); / * 42 * / hh (C, D, A, B, X [3], S33, 0xD4ef3085); / * 43 * / hh (B, C, D, A, X [6], S34, 0X4881D05); / * 44 * / hh (A, B, C, D, X [9], S31, 0xD9D4D039); / * 45 * / hh (D, A, B, C, X [12], S32, 0xE6DB99E5); / * 46 * / HH (C, D, A, B, X [15], S33, 0x1fa27cf8); / * 47 * / hh (B, C, D, A, X [2], S34, 0XC4AC5665); / * 48 * / / * ROUND 4 * / II (A, B, C, D, X [0], S41, 0XF4292244); / * 49 * / II (D, A, B, C, X [7], S42, 0x432AFF97); / * 50 * / II (C, D, A, B, X [14], S43, 0XAB9423A7); / * 51 * / ii (B, C, D, A, X [5], S44, 0XFC93A039); / * 52 * / II (A, B, C, D, X [12], S41, 0X65559C3); / * 53 * / ii (D, A, B, C, X [3], S42, 0x8F0CC92); / * 54 * / ii (C, D, A, B, X [10], S43, 0xffeff47d); / * 55 * / ii (B, C, D, A, X [1], S44, 0x85845DD1); / * 56 * / ii (A, B, C, D, X [8], S41, 0X6FA87E4F); / * 57 * / II (D, A, B, C, X [15], S42, 0XFE2CE6E0); / * 58 * / II (C, D, A, B, X [6], S43, 0XA3014314); / * 59 * / ii (B, C, D, A, X [13], S44, 0X4E0811A1); / * 60 * / ii (A, B, C, D, X [4], S41, 0XF7537E82); / * 61 * / ii (D, A, B, C, X [11], S42, 0XBD3AF235); / * 62 * / II (C, D, A, B, X [2], S43, 0X2AD7D2BB); / * 63 * / ii (B, C, D, A, X [9], S44, 0XEB86D391); / * 64 * / state [0] = a; state [1] = b; state [2] = C; State [3] = D; / * ZEROIZE SENSITIVE INFORMATION. * / MD5_MEMSET ((Pointer) X, 0, SIZEOF (X));} / * Encodes INPUT (UINT4) INTO OUTPUT (Unsigned Char). Assumes Len Is A Multiple of 4. * / static void Encode (Output, Input, LEN) unsigned char * OUTPUT; UINT4 * infut; unsigned int Len; {unsigned int 1, j; for (i = 0, j = 0; j ((Uint4) INPUT [(UINT4) INPUT [J 1]) << 8) | ((uint4) INPUT [J 2]) << 16) | (((UINT4) INPUT [J 3]) << 24);} / * Note: Replace "for loop" with standard memcpy if Possible. * / static void md5_memcpy (output, input, len) Pointer Output; Pointer INPUT; Unsigned int I; for (i = 0; i static void MDTimeTrial PROTO_LIST ((void)); static void MDTestSuite PROTO_LIST ((void)); static void MDFile PROTO_LIST ((char *)); static void MDFilter PROTO_LIST ((void)); static void MDPrint PROTO_LIST ((unsigned char [ 16])); #if MD == 2 #define MD_CTX MD2_CTX #define MDInit MD2Init #define MDUpdate MD2Update #define MDFinal MD2Final #endif #if MD == 4 #define MD_CTX MD4_CTX #define MDInit MD4Init #define MDUpdate MD4Update #define MDFinal MD4Final #endif #if MD == 5 #define MD_CTX MD5_CTX #define MDInit MD5Init #define MDUpdate MD5Update #define MDFinal MD5Final #endif / * Main driver Arguments (may be any combination):. -sstring - digests string -t - runs time Trial-x - Runs Test Script FileName - Digests File (None) - Digests Standard Input * / Int Main (Argc, Argv) Int Argc; Char * Argv []; {INT I; IF (Argc> 1) for (i = 1; I .} / * Measures the time to digest TEST_BLOCK_COUNT TEST_BLOCK_LEN-byte blocks * / static void MDTimeTrial () {MD_CTX context; time_t endTime, startTime; unsigned char block [TEST_BLOCK_LEN], digest [16]; unsigned int i; printf ( "MD % D Time Trial. DiGesting% D% D-Byte Blocks ... ", MD, Test_block_len, Test_block_count); / * Initialize Block * / for (i = 0; i FOPEN (FileName, "RB")) == NULL) Printf ("% s can't be opened / n", filename); else {mdinit (& context); while (len = fread (buffer, 1, 1024, file )) MDUPDATE (& Context, Buffer, Len); Mdfinal (Digest, & Context); fclose (file); Printf ("MD% D (% s) =", MD, FileName); MDPrint (Digest); Printf ("/ N ");}} / * Digests the standard input and prints the result. * / static void mdfilter () {md_ctx context; int Len; unsigned char buffer [16], Digest [16]; mdinit (& context); while (WHILE) Len = FREAD (Buffer, 1, 16, Stdin) MDUPDATE (& Context, Buffer, Len); Mdfinal (Digest, & Context); Mdprint (Digest); Printf ("/ n");} / * Prints a Message Digest in Hexadecimal. * / static void mdprint (Digest) unsigned char digest [16]; {UNSIGNED INT i; for (i = 0; i <16; i ) Printf ("% 02x", Digest [i]);} A. 5 Test Suite The MD5 Test Suite (Driver Option "-x") Should Print The Following Results: MD5 Test Suite: MD5 (") = D41D8CD98F00B204E9800998ECF8427E MD5 (" a ") = 0cc175b9c0f1b6a 831c399e269772661 MD5 ( "abc") = 900150983cd24fb0d6963f7d28e17f72 MD5 ( "message digest") = f96b697d7cb7938d525a2f31aaf161d0 MD5 ( "abcdefghijklmnopqrstuvwxyz") = c3fcd3d76192e4007dfb496cca67e13b MD5 ( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789") = d174ab98d277d9f5a5611c2c9f419d9f MD5 ( "123456789012345678901234567890123456789012345678901234567890123456 78901234567890") =