md5sum.cpp

来自「从FFMPEG转换而来的H264解码程序,VC下编译..」· C++ 代码 · 共 434 行 · 第 1/2 页

CPP
434
字号
/* ========================================================================== **
 *
 *                                    MD5.c
 *
 * Copyright:
 *  Copyright (C) 2003, 2004 by Christopher R. Hertel
 *
 * Email: crh@ubiqx.mn.org
 *
 * Modified for use with MPlayer, detailed CVS changelog at
 * http://www.mplayerhq.hu/cgi-bin/cvsweb.cgi/main/
 *
 * -------------------------------------------------------------------------- **
 *
 * Description:
 *  Implements the MD5 hash algorithm, as described in RFC 1321.
 *
 * -------------------------------------------------------------------------- **
 *
 * License:
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License as published by the Free Software Foundation; either
 *  version 2.1 of the License, or (at your option) any later version.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * -------------------------------------------------------------------------- **
 *
 * Notes:
 *
 *  None of this will make any sense unless you're studying RFC 1321 as you
 *  read the code.
 *
 *  MD5 is described in RFC 1321.
 *  The MD*4* algorithm is described in RFC 1320 (that's 1321 - 1).
 *  MD5 is very similar to MD4, but not quite similar enough to justify
 *  putting the two into a single module.  Besides, I wanted to add a few
 *  extra functions to this one to expand its usability.
 *
 *  There are three primary motivations for this particular implementation.
 *  1) Programmer's pride.  I wanted to be able to say I'd done it, and I
 *     wanted to learn from the experience.
 *  2) Portability.  I wanted an implementation that I knew to be portable
 *     to a reasonable number platforms.  In particular, the algorithm is
 *     designed with little-endian platforms in mind, but I wanted an
 *     endian-agnostic implementation.
 *  3) Compactness.  While not an overriding goal, I thought it worth-while
 *     to see if I could reduce the overall size of the result.  This is in
 *     keeping with my hopes that this library will be suitable for use in
 *     some embedded environments.
 *  Beyond that, cleanliness and clarity are always worth pursuing.
 *
 *  As mentioned above, the code really only makes sense if you are familiar
 *  with the MD5 algorithm or are using RFC 1321 as a guide.  This code is
 *  quirky, however, so you'll want to be reading carefully.
 *
 *  Yeah...most of the comments are cut-and-paste from my MD4 implementation.
 *
 * -------------------------------------------------------------------------- **
 *
 * References:
 *  IETF RFC 1321: The MD5 Message-Digest Algorithm
 *       Ron Rivest. IETF, April, 1992
 *
 * ========================================================================== **
 */

#include "stdafx.h"
#include "md5sum.h"   /* Added this line */

/* -------------------------------------------------------------------------- **
 * Static Constants:
 *
 *  K[][] - In round one, the values of k (which are used to index
 *          particular four-byte sequences in the input) are simply
 *          sequential.  In later rounds, however, they are a bit more
 *          varied.  Rather than calculate the values of k (which may
 *          or may not be possible--I haven't though about it) the
 *          values are stored in this array.
 *
 *  S[][] - In each round there is a left rotate operation performed as
 *          part of the 16 permutations.  The number of bits varies in
 *          a repeating patter.  This array keeps track of the patterns
 *          used in each round.
 *
 *  T[][] - There are four rounds of 16 permutations for a total of 64.
 *          In each of these 64 permutation operations, a different
 *          constant value is added to the mix.  The constants are
 *          based on the sine function...read RFC 1321 for more detail.
 *          In any case, the correct constants are stored in the T[][]
 *          array.  They're divided up into four groups of 16.
 */



/* -------------------------------------------------------------------------- **
 * Macros:
 *  md5F(), md5G(), md5H(), and md5I() are described in RFC 1321.
 *  All of these operations are bitwise, and so not impacted by endian-ness.
 *
 *  GetLongByte()
 *    Extract one byte from a (32-bit) longword.  A value of 0 for <idx>
 *    indicates the lowest order byte, while 3 indicates the highest order
 *    byte.
 *
 */

/* -------------------------------------------------------------------------- **
 * Static Functions:
 */

void Tmd5::Permute(uint32_t ABCD[4], const uint8_t block[64])
  /* ------------------------------------------------------------------------ **
   * Permute the ABCD "registers" using the 64-byte <block> as a driver.
   *
   *  Input:  ABCD  - Pointer to an array of four unsigned longwords.
   *          block - An array of bytes, 64 bytes in size.
   *
   *  Output: none.
   *
   *  Notes:  The MD5 algorithm operates on a set of four longwords stored
   *          (conceptually) in four "registers".  It is easy to imagine a
   *          simple MD4/5 chip that would operate this way.  In any case,
   *          the mangling of the contents of those registers is driven by
   *          the input message.  The message is chopped and finally padded
   *          into 64-byte chunks and each chunk is used to manipulate the
   *          contents of the registers.
   *
   *          The MD5 Algorithm calls for padding the input to ensure that
   *          it is a multiple of 64 bytes in length.  The last 16 bytes
   *          of the padding space are used to store the message length
   *          (the length of the original message, before padding, expressed
   *          in terms of bits).  If there is not enough room for 16 bytes
   *          worth of bitcount (eg., if the original message was 122 bytes
   *          long) then the block is padded to the end with zeros and
   *          passed to this function.  Then *another* block is filled with
   *          zeros except for the last 16 bytes which contain the length.
   *
   *          Oh... and the algorithm requires that there be at least one
   *          padding byte.  The first padding byte has a value of 0x80,
   *          and any others are 0x00.
   *
   * ------------------------------------------------------------------------ **
   */
  {
static const uint8_t K[3][16] =
  {
    /* Round 1: skipped (since it is simply sequential). */
    {  1,  6, 11,  0,  5, 10, 15,  4,  9, 14,  3,  8, 13,  2,  7, 12 }, /* R2 */
    {  5,  8, 11, 14,  1,  4,  7, 10, 13,  0,  3,  6,  9, 12, 15,  2 }, /* R3 */
    {  0,  7, 14,  5, 12,  3, 10,  1,  8, 15,  6, 13,  4, 11,  2,  9 }  /* R4 */
  };
static const uint8_t S[4][4] =
  {
    { 7, 12, 17, 22 },  /* Round 1 */
    { 5,  9, 14, 20 },  /* Round 2 */
    { 4, 11, 16, 23 },  /* Round 3 */
    { 6, 10, 15, 21 }   /* Round 4 */
  };
static const uint32_t T[4][16] =
  {
    { 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee,   /* Round 1 */
      0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
      0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,
      0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821 },

    { 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa,   /* Round 2 */
      0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8,
      0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed,
      0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a },

    { 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c,   /* Round 3 */
      0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
      0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05,
      0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665 },

    { 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039,   /* Round 4 */
      0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
      0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
      0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391 },
  };

  int      round;
  int      i, j;
  uint8_t  s;
  uint32_t a, b, c, d;
  uint32_t KeepABCD[4];
  uint32_t X[16];

  /* Store the current ABCD values for later re-use.
   */
  for( i = 0; i < 4; i++ )
    KeepABCD[i] = ABCD[i];

  /* Convert the input block into an array of unsigned longs, taking care
   * to read the block in Little Endian order (the algorithm assumes this).
   * The uint32_t values are then handled in host order.
   */
  for( i = 0, j = 0; i < 16; i++ )
    {
    X[i]  =  (uint32_t)block[j++];
    X[i] |= ((uint32_t)block[j++] << 8);
    X[i] |= ((uint32_t)block[j++] << 16);
    X[i] |= ((uint32_t)block[j++] << 24);
    }

  /* This loop performs the four rounds of permutations.
   * The rounds are each very similar.  The differences are in three areas:

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?