Back to index

php5  5.3.10
md5.c
Go to the documentation of this file.
00001 /*
00002    +----------------------------------------------------------------------+
00003    | PHP Version 5                                                        |
00004    +----------------------------------------------------------------------+
00005    | Copyright (c) 1997-2012 The PHP Group                                |
00006    +----------------------------------------------------------------------+
00007    | This source file is subject to version 3.01 of the PHP license,      |
00008    | that is bundled with this package in the file LICENSE, and is        |
00009    | available through the world-wide-web at the following url:           |
00010    | http://www.php.net/license/3_01.txt                                  |
00011    | If you did not receive a copy of the PHP license and are unable to   |
00012    | obtain it through the world-wide-web, please send a note to          |
00013    | license@php.net so we can mail you a copy immediately.               |
00014    +----------------------------------------------------------------------+
00015    | Author: Alexander Peslyak (Solar Designer) <solar at openwall.com>   |
00016    |         Lachlan Roche                                                |
00017    |         Alessandro Astarita <aleast@capri.it>                        |
00018    +----------------------------------------------------------------------+
00019 */
00020 
00021 /* $Id: md5.c 321634 2012-01-01 13:15:04Z felipe $ */
00022 
00023 #include "php.h"
00024 #include "md5.h"
00025 
00026 PHPAPI void make_digest(char *md5str, const unsigned char *digest) /* {{{ */
00027 {
00028        make_digest_ex(md5str, digest, 16);
00029 }
00030 /* }}} */
00031 
00032 PHPAPI void make_digest_ex(char *md5str, const unsigned char *digest, int len) /* {{{ */
00033 {
00034        static const char hexits[17] = "0123456789abcdef";
00035        int i;
00036 
00037        for (i = 0; i < len; i++) {
00038               md5str[i * 2]       = hexits[digest[i] >> 4];
00039               md5str[(i * 2) + 1] = hexits[digest[i] &  0x0F];
00040        }
00041        md5str[len * 2] = '\0';
00042 }
00043 /* }}} */
00044 
00045 /* {{{ proto string md5(string str, [ bool raw_output])
00046    Calculate the md5 hash of a string */
00047 PHP_NAMED_FUNCTION(php_if_md5)
00048 {
00049        char *arg;
00050        int arg_len;
00051        zend_bool raw_output = 0;
00052        char md5str[33];
00053        PHP_MD5_CTX context;
00054        unsigned char digest[16];
00055        
00056        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b", &arg, &arg_len, &raw_output) == FAILURE) {
00057               return;
00058        }
00059        
00060        md5str[0] = '\0';
00061        PHP_MD5Init(&context);
00062        PHP_MD5Update(&context, arg, arg_len);
00063        PHP_MD5Final(digest, &context);
00064        if (raw_output) {
00065               RETURN_STRINGL(digest, 16, 1);
00066        } else {
00067               make_digest_ex(md5str, digest, 16);
00068               RETVAL_STRING(md5str, 1);
00069        }
00070 
00071 }
00072 /* }}} */
00073 
00074 /* {{{ proto string md5_file(string filename [, bool raw_output])
00075    Calculate the md5 hash of given filename */
00076 PHP_NAMED_FUNCTION(php_if_md5_file)
00077 {
00078        char          *arg;
00079        int           arg_len;
00080        zend_bool raw_output = 0;
00081        char          md5str[33];
00082        unsigned char buf[1024];
00083        unsigned char digest[16];
00084        PHP_MD5_CTX   context;
00085        int           n;
00086        php_stream    *stream;
00087 
00088        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b", &arg, &arg_len, &raw_output) == FAILURE) {
00089               return;
00090        }
00091        
00092        stream = php_stream_open_wrapper(arg, "rb", REPORT_ERRORS | ENFORCE_SAFE_MODE, NULL);
00093        if (!stream) {
00094               RETURN_FALSE;
00095        }
00096 
00097        PHP_MD5Init(&context);
00098 
00099        while ((n = php_stream_read(stream, buf, sizeof(buf))) > 0) {
00100               PHP_MD5Update(&context, buf, n);
00101        }
00102 
00103        PHP_MD5Final(digest, &context);
00104 
00105        php_stream_close(stream);
00106 
00107        if (n<0) {
00108               RETURN_FALSE;
00109        }
00110 
00111        if (raw_output) {
00112               RETURN_STRINGL(digest, 16, 1);
00113        } else {
00114               make_digest_ex(md5str, digest, 16);
00115               RETVAL_STRING(md5str, 1);
00116        }
00117 }
00118 /* }}} */
00119 
00120 /*
00121  * This is an OpenSSL-compatible implementation of the RSA Data Security,
00122  * Inc. MD5 Message-Digest Algorithm (RFC 1321).
00123  *
00124  * Written by Solar Designer <solar at openwall.com> in 2001, and placed
00125  * in the public domain.  There's absolutely no warranty.
00126  *
00127  * This differs from Colin Plumb's older public domain implementation in
00128  * that no 32-bit integer data type is required, there's no compile-time
00129  * endianness configuration, and the function prototypes match OpenSSL's.
00130  * The primary goals are portability and ease of use.
00131  *
00132  * This implementation is meant to be fast, but not as fast as possible.
00133  * Some known optimizations are not included to reduce source code size
00134  * and avoid compile-time configuration.
00135  */
00136 
00137 #include <string.h>
00138 
00139 /*
00140  * The basic MD5 functions.
00141  *
00142  * F and G are optimized compared to their RFC 1321 definitions for
00143  * architectures that lack an AND-NOT instruction, just like in Colin Plumb's
00144  * implementation.
00145  */
00146 #define F(x, y, z)                 ((z) ^ ((x) & ((y) ^ (z))))
00147 #define G(x, y, z)                 ((y) ^ ((z) & ((x) ^ (y))))
00148 #define H(x, y, z)                 ((x) ^ (y) ^ (z))
00149 #define I(x, y, z)                 ((y) ^ ((x) | ~(z)))
00150 
00151 /*
00152  * The MD5 transformation for all four rounds.
00153  */
00154 #define STEP(f, a, b, c, d, x, t, s) \
00155        (a) += f((b), (c), (d)) + (x) + (t); \
00156        (a) = (((a) << (s)) | (((a) & 0xffffffff) >> (32 - (s)))); \
00157        (a) += (b);
00158 
00159 /*
00160  * SET reads 4 input bytes in little-endian byte order and stores them
00161  * in a properly aligned word in host byte order.
00162  *
00163  * The check for little-endian architectures that tolerate unaligned
00164  * memory accesses is just an optimization.  Nothing will break if it
00165  * doesn't work.
00166  */
00167 #if defined(__i386__) || defined(__x86_64__) || defined(__vax__)
00168 # define SET(n) \
00169        (*(php_uint32 *)&ptr[(n) * 4])
00170 # define GET(n) \
00171        SET(n)
00172 #else
00173 # define SET(n) \
00174        (ctx->block[(n)] = \
00175        (php_uint32)ptr[(n) * 4] | \
00176        ((php_uint32)ptr[(n) * 4 + 1] << 8) | \
00177        ((php_uint32)ptr[(n) * 4 + 2] << 16) | \
00178        ((php_uint32)ptr[(n) * 4 + 3] << 24))
00179 # define GET(n) \
00180        (ctx->block[(n)])
00181 #endif
00182 
00183 /*
00184  * This processes one or more 64-byte data blocks, but does NOT update
00185  * the bit counters.  There are no alignment requirements.
00186  */
00187 static const void *body(PHP_MD5_CTX *ctx, const void *data, size_t size)
00188 {
00189        const unsigned char *ptr;
00190        php_uint32 a, b, c, d;
00191        php_uint32 saved_a, saved_b, saved_c, saved_d;
00192 
00193        ptr = data;
00194 
00195        a = ctx->a;
00196        b = ctx->b;
00197        c = ctx->c;
00198        d = ctx->d;
00199 
00200        do {
00201               saved_a = a;
00202               saved_b = b;
00203               saved_c = c;
00204               saved_d = d;
00205 
00206 /* Round 1 */
00207               STEP(F, a, b, c, d, SET(0), 0xd76aa478, 7)
00208               STEP(F, d, a, b, c, SET(1), 0xe8c7b756, 12)
00209               STEP(F, c, d, a, b, SET(2), 0x242070db, 17)
00210               STEP(F, b, c, d, a, SET(3), 0xc1bdceee, 22)
00211               STEP(F, a, b, c, d, SET(4), 0xf57c0faf, 7)
00212               STEP(F, d, a, b, c, SET(5), 0x4787c62a, 12)
00213               STEP(F, c, d, a, b, SET(6), 0xa8304613, 17)
00214               STEP(F, b, c, d, a, SET(7), 0xfd469501, 22)
00215               STEP(F, a, b, c, d, SET(8), 0x698098d8, 7)
00216               STEP(F, d, a, b, c, SET(9), 0x8b44f7af, 12)
00217               STEP(F, c, d, a, b, SET(10), 0xffff5bb1, 17)
00218               STEP(F, b, c, d, a, SET(11), 0x895cd7be, 22)
00219               STEP(F, a, b, c, d, SET(12), 0x6b901122, 7)
00220               STEP(F, d, a, b, c, SET(13), 0xfd987193, 12)
00221               STEP(F, c, d, a, b, SET(14), 0xa679438e, 17)
00222               STEP(F, b, c, d, a, SET(15), 0x49b40821, 22)
00223 
00224 /* Round 2 */
00225               STEP(G, a, b, c, d, GET(1), 0xf61e2562, 5)
00226               STEP(G, d, a, b, c, GET(6), 0xc040b340, 9)
00227               STEP(G, c, d, a, b, GET(11), 0x265e5a51, 14)
00228               STEP(G, b, c, d, a, GET(0), 0xe9b6c7aa, 20)
00229               STEP(G, a, b, c, d, GET(5), 0xd62f105d, 5)
00230               STEP(G, d, a, b, c, GET(10), 0x02441453, 9)
00231               STEP(G, c, d, a, b, GET(15), 0xd8a1e681, 14)
00232               STEP(G, b, c, d, a, GET(4), 0xe7d3fbc8, 20)
00233               STEP(G, a, b, c, d, GET(9), 0x21e1cde6, 5)
00234               STEP(G, d, a, b, c, GET(14), 0xc33707d6, 9)
00235               STEP(G, c, d, a, b, GET(3), 0xf4d50d87, 14)
00236               STEP(G, b, c, d, a, GET(8), 0x455a14ed, 20)
00237               STEP(G, a, b, c, d, GET(13), 0xa9e3e905, 5)
00238               STEP(G, d, a, b, c, GET(2), 0xfcefa3f8, 9)
00239               STEP(G, c, d, a, b, GET(7), 0x676f02d9, 14)
00240               STEP(G, b, c, d, a, GET(12), 0x8d2a4c8a, 20)
00241 
00242 /* Round 3 */
00243               STEP(H, a, b, c, d, GET(5), 0xfffa3942, 4)
00244               STEP(H, d, a, b, c, GET(8), 0x8771f681, 11)
00245               STEP(H, c, d, a, b, GET(11), 0x6d9d6122, 16)
00246               STEP(H, b, c, d, a, GET(14), 0xfde5380c, 23)
00247               STEP(H, a, b, c, d, GET(1), 0xa4beea44, 4)
00248               STEP(H, d, a, b, c, GET(4), 0x4bdecfa9, 11)
00249               STEP(H, c, d, a, b, GET(7), 0xf6bb4b60, 16)
00250               STEP(H, b, c, d, a, GET(10), 0xbebfbc70, 23)
00251               STEP(H, a, b, c, d, GET(13), 0x289b7ec6, 4)
00252               STEP(H, d, a, b, c, GET(0), 0xeaa127fa, 11)
00253               STEP(H, c, d, a, b, GET(3), 0xd4ef3085, 16)
00254               STEP(H, b, c, d, a, GET(6), 0x04881d05, 23)
00255               STEP(H, a, b, c, d, GET(9), 0xd9d4d039, 4)
00256               STEP(H, d, a, b, c, GET(12), 0xe6db99e5, 11)
00257               STEP(H, c, d, a, b, GET(15), 0x1fa27cf8, 16)
00258               STEP(H, b, c, d, a, GET(2), 0xc4ac5665, 23)
00259 
00260 /* Round 4 */
00261               STEP(I, a, b, c, d, GET(0), 0xf4292244, 6)
00262               STEP(I, d, a, b, c, GET(7), 0x432aff97, 10)
00263               STEP(I, c, d, a, b, GET(14), 0xab9423a7, 15)
00264               STEP(I, b, c, d, a, GET(5), 0xfc93a039, 21)
00265               STEP(I, a, b, c, d, GET(12), 0x655b59c3, 6)
00266               STEP(I, d, a, b, c, GET(3), 0x8f0ccc92, 10)
00267               STEP(I, c, d, a, b, GET(10), 0xffeff47d, 15)
00268               STEP(I, b, c, d, a, GET(1), 0x85845dd1, 21)
00269               STEP(I, a, b, c, d, GET(8), 0x6fa87e4f, 6)
00270               STEP(I, d, a, b, c, GET(15), 0xfe2ce6e0, 10)
00271               STEP(I, c, d, a, b, GET(6), 0xa3014314, 15)
00272               STEP(I, b, c, d, a, GET(13), 0x4e0811a1, 21)
00273               STEP(I, a, b, c, d, GET(4), 0xf7537e82, 6)
00274               STEP(I, d, a, b, c, GET(11), 0xbd3af235, 10)
00275               STEP(I, c, d, a, b, GET(2), 0x2ad7d2bb, 15)
00276               STEP(I, b, c, d, a, GET(9), 0xeb86d391, 21)
00277 
00278               a += saved_a;
00279               b += saved_b;
00280               c += saved_c;
00281               d += saved_d;
00282 
00283               ptr += 64;
00284        } while (size -= 64);
00285 
00286        ctx->a = a;
00287        ctx->b = b;
00288        ctx->c = c;
00289        ctx->d = d;
00290 
00291        return ptr;
00292 }
00293 
00294 PHPAPI void PHP_MD5Init(PHP_MD5_CTX *ctx)
00295 {
00296        ctx->a = 0x67452301;
00297        ctx->b = 0xefcdab89;
00298        ctx->c = 0x98badcfe;
00299        ctx->d = 0x10325476;
00300 
00301        ctx->lo = 0;
00302        ctx->hi = 0;
00303 }
00304 
00305 PHPAPI void PHP_MD5Update(PHP_MD5_CTX *ctx, const void *data, size_t size)
00306 {
00307        php_uint32 saved_lo;
00308        php_uint32 used, free;
00309 
00310        saved_lo = ctx->lo;
00311        if ((ctx->lo = (saved_lo + size) & 0x1fffffff) < saved_lo) {
00312               ctx->hi++;
00313        }
00314        ctx->hi += size >> 29;
00315 
00316        used = saved_lo & 0x3f;
00317 
00318        if (used) {
00319               free = 64 - used;
00320 
00321               if (size < free) {
00322                      memcpy(&ctx->buffer[used], data, size);
00323                      return;
00324               }
00325 
00326               memcpy(&ctx->buffer[used], data, free);
00327               data = (unsigned char *)data + free;
00328               size -= free;
00329               body(ctx, ctx->buffer, 64);
00330        }
00331 
00332        if (size >= 64) {
00333               data = body(ctx, data, size & ~(size_t)0x3f);
00334               size &= 0x3f;
00335        }
00336 
00337        memcpy(ctx->buffer, data, size);
00338 }
00339 
00340 PHPAPI void PHP_MD5Final(unsigned char *result, PHP_MD5_CTX *ctx)
00341 {
00342        php_uint32 used, free;
00343 
00344        used = ctx->lo & 0x3f;
00345 
00346        ctx->buffer[used++] = 0x80;
00347 
00348        free = 64 - used;
00349 
00350        if (free < 8) {
00351               memset(&ctx->buffer[used], 0, free);
00352               body(ctx, ctx->buffer, 64);
00353               used = 0;
00354               free = 64;
00355        }
00356 
00357        memset(&ctx->buffer[used], 0, free - 8);
00358 
00359        ctx->lo <<= 3;
00360        ctx->buffer[56] = ctx->lo;
00361        ctx->buffer[57] = ctx->lo >> 8;
00362        ctx->buffer[58] = ctx->lo >> 16;
00363        ctx->buffer[59] = ctx->lo >> 24;
00364        ctx->buffer[60] = ctx->hi;
00365        ctx->buffer[61] = ctx->hi >> 8;
00366        ctx->buffer[62] = ctx->hi >> 16;
00367        ctx->buffer[63] = ctx->hi >> 24;
00368 
00369        body(ctx, ctx->buffer, 64);
00370 
00371        result[0] = ctx->a;
00372        result[1] = ctx->a >> 8;
00373        result[2] = ctx->a >> 16;
00374        result[3] = ctx->a >> 24;
00375        result[4] = ctx->b;
00376        result[5] = ctx->b >> 8;
00377        result[6] = ctx->b >> 16;
00378        result[7] = ctx->b >> 24;
00379        result[8] = ctx->c;
00380        result[9] = ctx->c >> 8;
00381        result[10] = ctx->c >> 16;
00382        result[11] = ctx->c >> 24;
00383        result[12] = ctx->d;
00384        result[13] = ctx->d >> 8;
00385        result[14] = ctx->d >> 16;
00386        result[15] = ctx->d >> 24;
00387 
00388        memset(ctx, 0, sizeof(*ctx));
00389 }