md5sum.cpp

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

CPP
434
字号
   *   - The function (F, G, H, or I) used to perform bitwise permutations
   *     on the registers,
   *   - The order in which values from X[] are chosen.
   *   - Changes to the number of bits by which the registers are rotated.
   * This implementation uses a switch statement to deal with some of the
   * differences between rounds.  Other differences are handled by storing
   * values in arrays and using the round number to select the correct set
   * of values.
   *
   * (My implementation appears to be a poor compromise between speed, size,
   * and clarity.  Ugh.  [crh])
   */
  for( round = 0; round < 4; round++ )
    {
    for( i = 0; i < 16; i++ )
      {
      j = (4 - (i % 4)) & 0x3;  /* <j> handles the rotation of ABCD.          */
      s = S[round][i%4];        /* <s> is the bit shift for this iteration.   */

      b = ABCD[(j+1) & 0x3];    /* Copy the b,c,d values per ABCD rotation.   */
      c = ABCD[(j+2) & 0x3];    /* This isn't really necessary, it just looks */
      d = ABCD[(j+3) & 0x3];    /* clean & will hopefully be optimized away.  */

      /* The actual perumation function.
       * This is broken out to minimize the code within the switch().
       */
      switch( round )
        {
        case 0:
          /* round 1 */
          a = md5F( b, c, d ) + X[i];
          break;
        case 1:
          /* round 2 */
          a = md5G( b, c, d ) + X[ K[0][i] ];
          break;
        case 2:
          /* round 3 */
          a = md5H( b, c, d ) + X[ K[1][i] ];
          break;
        default:
          /* round 4 */
          a = md5I( b, c, d ) + X[ K[2][i] ];
          break;
        }
      a = 0xFFFFFFFF & ( ABCD[j] + a + T[round][i] );
      ABCD[j] = b + (0xFFFFFFFF & (( a << s ) | ( a >> (32 - s) )));
      }
    }

  /* Use the stored original A, B, C, D values to perform
   * one last convolution.
   */
  for( i = 0; i < 4; i++ )
    ABCD[i] = 0xFFFFFFFF & ( ABCD[i] + KeepABCD[i] );

  } /* Permute */


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

Tmd5::Tmd5(void)
  /* ------------------------------------------------------------------------ **
   * Initialize an MD5 context.
   *
   *  Input:  ctx - A pointer to the MD5 context structure to be initialized.
   *                Contexts are typically created thusly:
   *                  ctx = (auth_md5Ctx *)malloc( sizeof(auth_md5Ctx) );
   *
   *  Output: A pointer to the initialized context (same as <ctx>).
   *
   *  Notes:  The purpose of the context is to make it possible to generate
   *          an MD5 Message Digest in stages, rather than having to pass a
   *          single large block to a single MD5 function.  The context
   *          structure keeps track of various bits of state information.
   *
   *          Once the context is initialized, the blocks of message data
   *          are passed to the <auth_md5SumCtx()> function.  Once the
   *          final bit of data has been handed to <auth_md5SumCtx()> the
   *          context can be closed out by calling <auth_md5CloseCtx()>,
   *          which also calculates the final MD5 result.
   *
   *          Don't forget to free an allocated context structure when
   *          you've finished using it.
   *
   *  See Also:  <auth_md5SumCtx()>, <auth_md5CloseCtx()>
   *
   * ------------------------------------------------------------------------ **
   */
  {
  len     = 0;
  b_used  = 0;

  ABCD[0] = 0x67452301;    /* The array ABCD[] contains the four 4-byte  */
  ABCD[1] = 0xefcdab89;    /* "registers" that are manipulated to        */
  ABCD[2] = 0x98badcfe;    /* produce the MD5 digest.  The input acts    */
  ABCD[3] = 0x10325476;    /* upon the registers, not the other way      */
                                /* 'round.  The initial values are those      */
                /* given in RFC 1321 (pg. 4).  Note, however, that RFC 1321   */
                /* provides these values as bytes, not as longwords, and the  */
                /* bytes are arranged in little-endian order as if they were  */
                /* the bytes of (little endian) 32-bit ints.  That's          */
                /* confusing as all getout (to me, anyway). The values given  */
                /* here are provided as 32-bit values in C language format,   */
                /* so they are endian-agnostic.  */
  } /* auth_md5InitCtx */


void Tmd5::sum(const uint8_t *src,unsigned int len)
  /* ------------------------------------------------------------------------ **
   * Build an MD5 Message Digest within the given context.
   *
   *  Input:  ctx - Pointer to the context in which the MD5 sum is being
   *                built.
   *          src - A chunk of source data.  This will be used to drive
   *                the MD5 algorithm.
   *          len - The number of bytes in <src>.
   *
   *  Output: A pointer to the updated context (same as <ctx>).
   *
   *  See Also:  <auth_md5InitCtx()>, <auth_md5CloseCtx()>, <auth_md5Sum()>
   *
   * ------------------------------------------------------------------------ **
   */
  {
  /* Add the new block's length to the total length.
   */
  this->len += len;

  /* Copy the new block's data into the context block.
   * Call the Permute() function whenever the context block is full.
   */
  for(unsigned int  i = 0; i < len; i++ )
    {
    block[ b_used ] = src[i];
    b_used++;
    if( 64 == b_used )
      {
      Permute( ABCD, block );
      b_used = 0;
      }
    }

  } /* auth_md5SumCtx */


void Tmd5::done(uint8_t dst[16])
  /* ------------------------------------------------------------------------ **
   * Close an MD5 Message Digest context and generate the final MD5 sum.
   *
   *  Input:  ctx - Pointer to the context in which the MD5 sum is being
   *                built.
   *          dst - A pointer to at least 16 bytes of memory, which will
   *                receive the finished MD5 sum.
   *
   *  Output: A pointer to the closed context (same as <ctx>).
   *          You might use this to free a malloc'd context structure.  :)
   *
   *  Notes:  The context (<ctx>) is returned in an undefined state.
   *          It must be re-initialized before re-use.
   *
   *  See Also:  <auth_md5InitCtx()>, <auth_md5SumCtx()>
   *
   * ------------------------------------------------------------------------ **
   */
  {
  int      i;
  uint32_t l;

  /* Add the required 0x80 padding initiator byte.
   * The auth_md5SumCtx() function always permutes and resets the context
   * block when it gets full, so we know that there must be at least one
   * free byte in the context block.
   */
  block[b_used] = 0x80;
  (b_used)++;

  /* Zero out any remaining free bytes in the context block.
   */
  for( i = b_used; i < 64; i++ )
    block[i] = 0;

  /* We need 8 bytes to store the length field.
   * If we don't have 8, call Permute() and reset the context block.
   */
  if( 56 < b_used )
    {
    Permute( ABCD, block );
    for( i = 0; i < 64; i++ )
      block[i] = 0;
    }

  /* Add the total length and perform the final perumation.
   * Note:  The 60'th byte is read from the *original* <len> value
   *        and shifted to the correct position.  This neatly avoids
   *        any MAXINT numeric overflow issues.
   */
  l = len << 3;
  for( i = 0; i < 4; i++ )
    block[56+i] |= GetLongByte( l, i );
  block[60] = ((GetLongByte( len, 3 ) & 0xE0) >> 5);  /* See Above! */
  Permute( ABCD, block );

  /* Now copy the result into the output buffer and we're done.
   */
  for( i = 0; i < 4; i++ )
    {
    dst[ 0+i] = GetLongByte( ABCD[0], i );
    dst[ 4+i] = GetLongByte( ABCD[1], i );
    dst[ 8+i] = GetLongByte( ABCD[2], i );
    dst[12+i] = GetLongByte( ABCD[3], i );
    }

} /* auth_md5CloseCtx */

⌨️ 快捷键说明

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