PixelLightAPI  .
ChecksumMD5.h
Go to the documentation of this file.
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__


PixelLight PixelLight 0.9.10-R1
Copyright (C) 2002-2011 by The PixelLight Team
Last modified Fri Dec 23 2011 15:50:51
The content of this PixelLight document is published under the
Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported