PixelLightAPI
.
|
00001 /*********************************************************\ 00002 * File: ChecksumMD5.h * 00003 * 00004 * Copyright (C) 2002-2011 The PixelLight Team (http://www.pixellight.org/) 00005 * 00006 * This file is part of PixelLight. 00007 * 00008 * PixelLight is free software: you can redistribute it and/or modify 00009 * it under the terms of the GNU Lesser General Public License as published by 00010 * the Free Software Foundation, either version 3 of the License, or 00011 * (at your option) any later version. 00012 * 00013 * PixelLight is distributed in the hope that it will be useful, 00014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00016 * GNU Lesser General Public License for more details. 00017 * 00018 * You should have received a copy of the GNU Lesser General Public License 00019 * along with PixelLight. If not, see <http://www.gnu.org/licenses/>. 00020 \*********************************************************/ 00021 00022 00023 #ifndef __PLCORE_CHECKSUMMD5_H__ 00024 #define __PLCORE_CHECKSUMMD5_H__ 00025 #pragma once 00026 00027 00028 //[-------------------------------------------------------] 00029 //[ Includes ] 00030 //[-------------------------------------------------------] 00031 #include "PLCore/Tools/Checksum.h" 00032 00033 00034 //[-------------------------------------------------------] 00035 //[ Namespace ] 00036 //[-------------------------------------------------------] 00037 namespace PLCore { 00038 00039 00040 //[-------------------------------------------------------] 00041 //[ Classes ] 00042 //[-------------------------------------------------------] 00043 /** 00044 * @brief 00045 * MD5 message-digest checksum 00046 * 00047 * @remarks 00048 * -------------------------------------------------------------------------- 00049 * Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All 00050 * rights reserved. 00051 * 00052 * License to copy and use this software is granted provided that it 00053 * is identified as the "RSA Data Security, Inc. MD5 Message-Digest 00054 * Algorithm" in all material mentioning or referencing this software 00055 * or this function. 00056 * 00057 * License is also granted to make and use derivative works provided 00058 * that such works are identified as "derived from the RSA Data 00059 * Security, Inc. MD5 Message-Digest Algorithm" in all material 00060 * mentioning or referencing the derived work. 00061 * 00062 * RSA Data Security, Inc. makes no representations concerning either 00063 * the merchantability of this software or the suitability of this 00064 * software for any particular purpose. It is provided "as is" 00065 * without express or implied warranty of any kind. 00066 * 00067 * These notices must be retained in any copies of any part of this 00068 * documentation and/or software. 00069 * -------------------------------------------------------------------------- 00070 * -------------------------------------------------------------------------- 00071 * This implementation of the RSA MD5 Algorithm is basing on the implementation written 00072 * by Langfine Ltd (www.langfine.com). 00073 * The original code was just reorganized so fit's into PixelLight. 00074 * 00075 * Author's Address 00076 * Ronald L. Rivest Massachusetts Institute of Technology 00077 * Laboratory for Computer Science NE43-324 545 Technology Square 00078 * Cambridge, MA 02139-1986 Phone: (617) 253-5880 00079 * EMail: rivest@theory.lcs.mit.edu 00080 * 00081 * Langfine Ltd makes no representations concerning either 00082 * the merchantability of this software or the suitability of this 00083 * software for any particular purpose. It is provided "as is" 00084 * without express or implied warranty of any kind. 00085 * 00086 * In addition to the above, Langfine make no warrant or assurances regarding the 00087 * accuracy of this implementation of the MD5 checksum algorithm nor any assurances 00088 * regarding its suitability for any purposes. 00089 * -------------------------------------------------------------------------- 00090 * Below are extracts from a memo on The MD5 Message-Digest Algorithm by R. Rivest of MIT 00091 * Laboratory for Computer Science and RSA Data Security, Inc., April 1992. 00092 * 00093 * 1. Executive Summary 00094 * This document describes the MD5 message-digest algorithm. The 00095 * algorithm takes as input a message of arbitrary length and produces 00096 * as output a 128-bit "fingerprint" or "message digest" of the input. 00097 * It is conjectured that it is computationally infeasible to produce 00098 * two messages having the same message digest, or to produce any 00099 * message having a given prespecified target message digest. The MD5 00100 * algorithm is intended for digital signature applications, where a 00101 * large file must be "compressed" in a secure manner before being 00102 * encrypted with a private (secret) key under a public-key cryptosystem 00103 * such as RSA. 00104 * 00105 * The MD5 algorithm is designed to be quite fast on 32-bit machines. In 00106 * addition, the MD5 algorithm does not require any large substitution 00107 * tables; the algorithm can be coded quite compactly. 00108 * The MD5 algorithm is an extension of the MD4 message-digest algorithm 00109 * 1,2]. MD5 is slightly slower than MD4, but is more "conservative" in 00110 * design. MD5 was designed because it was felt that MD4 was perhaps 00111 * being adopted for use more quickly than justified by the existing 00112 * critical review; because MD4 was designed to be exceptionally fast, 00113 * it is "at the edge" in terms of risking successful cryptanalytic 00114 * attack. MD5 backs off a bit, giving up a little in speed for a much 00115 * greater likelihood of ultimate security. It incorporates some 00116 * suggestions made by various reviewers, and contains additional 00117 * optimizations. The MD5 algorithm is being placed in the public domain 00118 * for review and possible adoption as a standard. 00119 * 00120 * 00121 * 2. Terminology and Notation 00122 * In this document a "word" is a 32-bit quantity and a "byte" is an 00123 * eight-bit quantity. A sequence of bits can be interpreted in a 00124 * natural manner as a sequence of bytes, where each consecutive group 00125 * of eight bits is interpreted as a byte with the high-order (most 00126 * significant) bit of each byte listed first. Similarly, a sequence of 00127 * bytes can be interpreted as a sequence of 32-bit words, where each 00128 * consecutive group of four bytes is interpreted as a word with the 00129 * low-order (least significant) byte given first. 00130 * Let x_i denote "x sub i". If the subscript is an expression, we 00131 * surround it in braces, as in x_{i+1}. Similarly, we use ^ for 00132 * superscripts (exponentiation), so that x^i denotes x to the i-th power. 00133 * Let the symbol "+" denote addition of words (i.e., modulo-2^32 00134 * addition). Let X <<< s denote the 32-bit value obtained by circularly 00135 * shifting (rotating) X left by s bit positions. Let not(X) denote the 00136 * bit-wise complement of X, and let X v Y denote the bit-wise OR of X 00137 * and Y. Let X xor Y denote the bit-wise XOR of X and Y, and let XY 00138 * denote the bit-wise AND of X and Y. 00139 * 00140 * 00141 * 3. MD5 Algorithm Description 00142 * We begin by supposing that we have a b-bit message as input, and that 00143 * we wish to find its message digest. Here b is an arbitrary 00144 * nonnegative integer; b may be zero, it need not be a multiple of 00145 * eight, and it may be arbitrarily large. We imagine the bits of the 00146 * message written down as follows: m_0 m_1 ... m_{b-1} 00147 * The following five steps are performed to compute the message digest 00148 * of the message. 00149 * 00150 * 3.1 Step 1. Append Padding Bits 00151 * The message is "padded" (extended) so that its length (in bits) is 00152 * congruent to 448, modulo 512. That is, the message is extended so 00153 * that it is just 64 bits shy of being a multiple of 512 bits long. 00154 * Padding is always performed, even if the length of the message is 00155 * already congruent to 448, modulo 512. 00156 * Padding is performed as follows: a single "1" bit is appended to the 00157 * message, and then "0" bits are appended so that the length in bits of 00158 * the padded message becomes congruent to 448, modulo 512. In all, at 00159 * least one bit and at most 512 bits are appended. 00160 * 00161 * 3.2 Step 2. Append Length 00162 * A 64-bit representation of b (the length of the message before the 00163 * padding bits were added) is appended to the result of the previous 00164 * step. In the unlikely event that b is greater than 2^64, then only 00165 * the low-order 64 bits of b are used. (These bits are appended as two 00166 * 32-bit words and appended low-order word first in accordance with the 00167 * previous conventions.) 00168 * At this point the resulting message (after padding with bits and with 00169 * b) has a length that is an exact multiple of 512 bits. Equivalently, 00170 * this message has a length that is an exact multiple of 16 (32-bit) 00171 * words. Let M[0 ... N-1] denote the words of the resulting message, 00172 * where N is a multiple of 16. 00173 * 00174 * 3.3 Step 3. Initialize MD Buffer 00175 * A four-word buffer (A,B,C,D) is used to compute the message digest. 00176 * Here each of A, B, C, D is a 32-bit register. These registers are 00177 * initialized to the following values in hexadecimal, low-order bytes first): 00178 * word A: 01 23 45 67 word B: 89 ab cd ef 00179 * word C: fe dc ba 98 word D: 76 54 32 10 00180 * 00181 * 3.4 Step 4. Process Message in 16-Word Blocks 00182 * We first define four auxiliary functions that each take as input 00183 * three 32-bit words and produce as output one 32-bit word. 00184 * F(X,Y,Z) = XY v not(X) Z G(X,Y,Z) = XZ v Y not(Z) 00185 * H(X,Y,Z) = X xor Y xor Z I(X,Y,Z) = Y xor (X v not(Z)) 00186 * In each bit position F acts as a conditional: if X then Y else Z. 00187 * The function F could have been defined using + instead of v since XY 00188 * and not(X)Z will never have 1's in the same bit position.) It is 00189 * interesting to note that if the bits of X, Y, and Z are independent 00190 * and unbiased, the each bit of F(X,Y,Z) will be independent and unbiased. 00191 * The functions G, H, and I are similar to the function F, in that they 00192 * act in "bitwise parallel" to produce their output from the bits of X, 00193 * Y, and Z, in such a manner that if the corresponding bits of X, Y, 00194 * and Z are independent and unbiased, then each bit of G(X,Y,Z), 00195 * H(X,Y,Z), and I(X,Y,Z) will be independent and unbiased. Note that 00196 * the function H is the bit-wise "xor" or "parity" function of its inputs. 00197 * This step uses a 64-element table T[1 ... 64] constructed from the 00198 * sine function. Let T[i] denote the i-th element of the table, which 00199 * is equal to the integer part of 4294967296 times abs(sin(i)), where i 00200 * is in radians. The elements of the table are given in the appendix. 00201 * Do the following: 00202 * 00203 * // Process each 16-word block. 00204 * For i = 0 to N/16-1 do // Copy block i into X. 00205 * For j = 0 to 15 do 00206 * Set X[j] to M[i*16+j] 00207 * end //of loop on j 00208 * 00209 * // Save A as AA, B as BB, C as CC, and D as DD. 00210 * AA = A BB = B 00211 * CC = C DD = D 00212 * 00213 * // Round 1. 00214 * // Let [abcd k s i] denote the operation 00215 * // a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). 00216 * // Do the following 16 operations. 00217 * [ABCD 0 7 1] [DABC 1 12 2] [CDAB 2 17 3] [BCDA 3 22 4] 00218 * [ABCD 4 7 5] [DABC 5 12 6] [CDAB 6 17 7] [BCDA 7 22 8] 00219 * [ABCD 8 7 9] [DABC 9 12 10] [CDAB 10 17 11] [BCDA 11 22 12] 00220 * [ABCD 12 7 13] [DABC 13 12 14] [CDAB 14 17 15] [BCDA 15 22 16] 00221 * 00222 * // Round 2. 00223 * // Let [abcd k s i] denote the operation 00224 * // a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). 00225 * // Do the following 16 operations. 00226 * [ABCD 1 5 17] [DABC 6 9 18] [CDAB 11 14 19] [BCDA 0 20 20] 00227 * [ABCD 5 5 21] [DABC 10 9 22] [CDAB 15 14 23] [BCDA 4 20 24] 00228 * [ABCD 9 5 25] [DABC 14 9 26] [CDAB 3 14 27] [BCDA 8 20 28] 00229 * [ABCD 13 5 29] [DABC 2 9 30] [CDAB 7 14 31] [BCDA 12 20 32] 00230 * 00231 * // Round 3. 00232 * // Let [abcd k s t] denote the operation 00233 * // a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). 00234 * // Do the following 16 operations. 00235 * [ABCD 5 4 33] [DABC 8 11 34] [CDAB 11 16 35] [BCDA 14 23 36] 00236 * [ABCD 1 4 37] [DABC 4 11 38] [CDAB 7 16 39] [BCDA 10 23 40] 00237 * [ABCD 13 4 41] [DABC 0 11 42] [CDAB 3 16 43] [BCDA 6 23 44] 00238 * [ABCD 9 4 45] [DABC 12 11 46] [CDAB 15 16 47] [BCDA 2 23 48] 00239 * 00240 * // Round 4. 00241 * // Let [abcd k s t] denote the operation 00242 * // a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). 00243 * // Do the following 16 operations. 00244 * [ABCD 0 6 49] [DABC 7 10 50] [CDAB 14 15 51] [BCDA 5 21 52] 00245 * [ABCD 12 6 53] [DABC 3 10 54] [CDAB 10 15 55] [BCDA 1 21 56] 00246 * [ABCD 8 6 57] [DABC 15 10 58] [CDAB 6 15 59] [BCDA 13 21 60] 00247 * [ABCD 4 6 61] [DABC 11 10 62] [CDAB 2 15 63] [BCDA 9 21 64] 00248 * 00249 * // Then perform the following additions. (That is increment each 00250 * // of the four registers by the value it had before this block 00251 * // was started.) 00252 * A = A + AA B = B + BB C = C + CC D = D + DD 00253 * 00254 * end // of loop on i 00255 * 00256 * 3.5 Step 5. Output 00257 * The message digest produced as output is A, B, C, D. That is, we 00258 * begin with the low-order byte of A, and end with the high-order byte of D. 00259 * This completes the description of MD5. 00260 * 00261 * Summary 00262 * The MD5 message-digest algorithm is simple to implement, and provides 00263 * a "fingerprint" or message digest of a message of arbitrary length. 00264 * It is conjectured that the difficulty of coming up with two messages 00265 * having the same message digest is on the order of 2^64 operations, 00266 * and that the difficulty of coming up with any message having a given 00267 * message digest is on the order of 2^128 operations. The MD5 algorithm 00268 * has been carefully scrutinized for weaknesses. It is, however, a 00269 * relatively new algorithm and further security analysis is of course 00270 * justified, as is the case with any new proposal of this sort. 00271 * 00272 * 00273 * 5. Differences Between MD4 and MD5 00274 * The following are the differences between MD4 and MD5: 00275 * 1. A fourth round has been added. 00276 * 2. Each step now has a unique additive constant. 00277 * 3. The function g in round 2 was changed from (XY v XZ v YZ) to 00278 * (XZ v Y not(Z)) to make g less symmetric. 00279 * 4. Each step now adds in the result of the previous step. This 00280 * promotes a faster "avalanche effect". 00281 * 5. The order in which input words are accessed in rounds 2 and 00282 * 3 is changed, to make these patterns less like each other. 00283 * 6. The shift amounts in each round have been approximately 00284 * optimized, to yield a faster "avalanche effect." The shifts in 00285 * different rounds are distinct. 00286 * 00287 * References 00288 * [1] Rivest, R., "The MD4 Message Digest Algorithm", RFC 1320, MIT and 00289 * RSA Data Security, Inc., April 1992. 00290 * [2] Rivest, R., "The MD4 message digest algorithm", in A.J. Menezes 00291 * and S.A. Vanstone, editors, Advances in Cryptology - CRYPTO '90 00292 * Proceedings, pages 303-311, Springer-Verlag, 1991. 00293 * [3] CCITT Recommendation X.509 (1988), "The Directory - 00294 * Authentication Framework."APPENDIX A - Reference Implementation 00295 * 00296 * 00297 * The level of security discussed in this memo is considered to be 00298 * sufficient for implementing very high security hybrid digital- 00299 * signature schemes based on MD5 and a public-key cryptosystem. 00300 * 00301 * @note 00302 * - MD5 produces a 128-bit/16-byte hash 00303 */ 00304 class ChecksumMD5 : public Checksum { 00305 00306 00307 //[-------------------------------------------------------] 00308 //[ Public functions ] 00309 //[-------------------------------------------------------] 00310 public: 00311 /** 00312 * @brief 00313 * Default constructor 00314 */ 00315 PLCORE_API ChecksumMD5(); 00316 00317 /** 00318 * @brief 00319 * Destructor 00320 */ 00321 PLCORE_API virtual ~ChecksumMD5(); 00322 00323 00324 //[-------------------------------------------------------] 00325 //[ Private functions ] 00326 //[-------------------------------------------------------] 00327 private: 00328 /** 00329 * @brief 00330 * Rotates the bits in a 32 bit uint32 left by a specified amount 00331 * 00332 * @param[in] x 00333 * The value to be rotated 00334 * @param[in] n 00335 * The number of bits to rotate by 00336 * 00337 * @return 00338 * The rotated uint32 00339 */ 00340 inline uint32 RotateLeft(uint32 x, int n) const; 00341 00342 /** 00343 * @brief 00344 * Implementation of basic MD5 transformation algorithm 00345 * 00346 * @param[in, out] nA 00347 * Current (partial) checksum 00348 * @param[in] nB 00349 * Current (partial) checksum 00350 * @param[in] nC 00351 * Current (partial) checksum 00352 * @param[in] nD 00353 * Current (partial) checksum 00354 * @param[in] nX 00355 * Input data 00356 * @param[in] nS 00357 * MD5_SXX Transformation constant 00358 * @param[in] nT 00359 * MD5_TXX Transformation constant 00360 */ 00361 inline void FF(uint32 &nA, uint32 nB, uint32 nC, uint32 nD, uint32 nX, uint32 nS, uint32 nT) const; 00362 00363 /** 00364 * @brief 00365 * Implementation of basic MD5 transformation algorithm 00366 * 00367 * @param[in, out] nA 00368 * Current (partial) checksum 00369 * @param[in] nB 00370 * Current (partial) checksum 00371 * @param[in] nC 00372 * Current (partial) checksum 00373 * @param[in] nD 00374 * Current (partial) checksum 00375 * @param[in] nX 00376 * Input data 00377 * @param[in] nS 00378 * MD5_SXX Transformation constant 00379 * @param[in] nT 00380 * MD5_TXX Transformation constant 00381 */ 00382 inline void GG(uint32 &nA, uint32 nB, uint32 nC, uint32 nD, uint32 nX, uint32 nS, uint32 nT) const; 00383 00384 /** 00385 * @brief 00386 * Implementation of basic MD5 transformation algorithm 00387 * 00388 * @param[in, out] nA 00389 * Current (partial) checksum 00390 * @param[in] nB 00391 * Current (partial) checksum 00392 * @param[in] nC 00393 * Current (partial) checksum 00394 * @param[in] nD 00395 * Current (partial) checksum 00396 * @param[in] nX 00397 * Input data 00398 * @param[in] nS 00399 * MD5_SXX Transformation constant 00400 * @param[in] nT 00401 * MD5_TXX Transformation constant 00402 */ 00403 inline void HH(uint32 &nA, uint32 nB, uint32 nC, uint32 nD, uint32 nX, uint32 nS, uint32 nT) const; 00404 00405 /** 00406 * @brief 00407 * Implementation of basic MD5 transformation algorithm 00408 * 00409 * @param[in, out] nA 00410 * Current (partial) checksum 00411 * @param[in] nB 00412 * Current (partial) checksum 00413 * @param[in] nC 00414 * Current (partial) checksum 00415 * @param[in] nD 00416 * Current (partial) checksum 00417 * @param[in] nX 00418 * Input data 00419 * @param[in] nS 00420 * MD5_SXX Transformation constant 00421 * @param[in] nT 00422 * MD5_TXX Transformation constant 00423 */ 00424 inline void II(uint32 &nA, uint32 nB, uint32 nC, uint32 nD, uint32 nX, uint32 nS, uint32 nT) const; 00425 00426 /** 00427 * @brief 00428 * Transfers the data in an 8 bit array to a 32 bit array 00429 * 00430 * @param[out] nOutput 00431 * The 32 bit (uint32) destination array 00432 * @param[in] nInput 00433 * The 8 bit (uint8) source array 00434 * @param[in] nLength 00435 * The number of 8 bit data items in the source array 00436 * 00437 * @remarks 00438 * Four uint8 from the input array are transferred to each uint32 entry of the 00439 * output array. The first uint8 is transferred to the bits (0-7) of the output 00440 * uint32, the second uint8 to bits 8-15 etc. The algorithm assumes that the 00441 * input array is a multiple of 4 bytes long so that there is a perfect fit into 00442 * the array of 32 bit words. 00443 */ 00444 inline void ByteToDWord(uint32 nOutput[], const uint8 nInput[], uint32 nLength) const; 00445 00446 /** 00447 * @brief 00448 * Transfers the data in an 32 bit array to a 8 bit array 00449 * 00450 * @param[out] nOutput 00451 * The 8 bit destination array 00452 * @param[in] nInput 00453 * The 32 bit source array 00454 * @param[in] nLength 00455 * The number of 8 bit data items in the source array 00456 * 00457 * @remarks 00458 * One uint32 from the input array is transferred into four uint8 in the output 00459 * array. The first (0-7) bits of the first uint32 are transferred to the first 00460 * output uint8, bits bits 8-15 are transferred from the second uint8 etc. 00461 * The algorithm assumes that the output array is a multiple of 4 bytes long 00462 * so that there is a perfect fit of 8 bit uint8 into the 32 bit uint32. 00463 */ 00464 inline void DWordToByte(uint8 nOutput[], uint32 nInput[], uint32 nLength) const; 00465 00466 /** 00467 * @brief 00468 * MD5 basic transformation algorithm; transforms 'm_nMD5' 00469 * 00470 * @param[in] nBlock 00471 * Block 00472 * 00473 * @remarks 00474 * An MD5 checksum is calculated by four rounds of 'Transformation'. The 00475 * MD5 checksum currently held in m_nMD5 is merged by the transformation 00476 * process with data passed in 'nBlock'. 00477 */ 00478 void Transform(const uint8 nBlock[64]); 00479 00480 00481 //[-------------------------------------------------------] 00482 //[ Private data ] 00483 //[-------------------------------------------------------] 00484 private: 00485 uint8 m_nBuffer[64]; /**< Input buffer */ 00486 uint32 m_nCount[2]; /**< Number of bits, modulo 2^64 (lsb first) */ 00487 uint32 m_nMD5[4]; /**< MD5 checksum */ 00488 00489 00490 //[-------------------------------------------------------] 00491 //[ Private virtual Checksum functions ] 00492 //[-------------------------------------------------------] 00493 private: 00494 virtual void Update(const uint8 nInput[], uint32 nInputLen) override; 00495 virtual String Final() override; 00496 00497 00498 }; 00499 00500 00501 //[-------------------------------------------------------] 00502 //[ Namespace ] 00503 //[-------------------------------------------------------] 00504 } // PLCore 00505 00506 00507 #endif // __PLCORE_CHECKSUMMD5_H__
|