]> granicus.if.org Git - php/commitdiff
Add md2 algo support
authorSara Golemon <pollita@php.net>
Tue, 21 Feb 2006 20:37:12 +0000 (20:37 +0000)
committerSara Golemon <pollita@php.net>
Tue, 21 Feb 2006 20:37:12 +0000 (20:37 +0000)
ext/hash/hash.c
ext/hash/hash_md.c
ext/hash/package.xml
ext/hash/php_hash.h
ext/hash/php_hash_md.h
ext/hash/tests/md2.phpt [new file with mode: 0644]

index 21f2f5a13e16a9256857cc5f9fa8742fbe4ea54c..a03890e377968167206325c876dc8df23e783621 100644 (file)
@@ -516,6 +516,7 @@ PHP_MINIT_FUNCTION(hash)
 
        zend_hash_init(&php_hash_hashtable, 35, NULL, NULL, 1);
 
+       php_hash_register_algo("md2",                   &php_hash_md2_ops);
        php_hash_register_algo("md4",                   &php_hash_md4_ops);
        php_hash_register_algo("md5",                   &php_hash_md5_ops);
        php_hash_register_algo("sha1",                  &php_hash_sha1_ops);
index 1ff0eba63a9eee5131bae8b97bdcffcf5a914108..8c43845cde61c42687df6dd480db2979bdc91dc7 100644 (file)
@@ -39,6 +39,15 @@ php_hash_ops php_hash_md4_ops = {
        sizeof(PHP_MD4_CTX)
 };
 
+php_hash_ops php_hash_md2_ops = {
+       (php_hash_init_func_t) PHP_MD2Init,
+       (php_hash_update_func_t) PHP_MD2Update,
+       (php_hash_final_func_t) PHP_MD2Final,
+       16,
+       16,
+       sizeof(PHP_MD2_CTX)
+};
+
 /* MD common stuff */
 
 static unsigned char PADDING[64] =
@@ -579,6 +588,95 @@ PHP_HASH_API void PHP_MD4Final(unsigned char digest[16], PHP_MD4_CTX * context)
 }
 /* }}} */
 
+/* MD2 */
+
+static unsigned char MD2_S[256] = {
+        41,  46,  67, 201, 162, 216, 124,   1,  61,  54,  84, 161, 236, 240,   6,  19,
+        98, 167,   5, 243, 192, 199, 115, 140, 152, 147,  43, 217, 188,  76, 130, 202,
+        30, 155,  87,  60, 253, 212, 224,  22, 103,  66, 111,  24, 138,  23, 229,  18,
+       190,  78, 196, 214, 218, 158, 222,  73, 160, 251, 245, 142, 187,  47, 238, 122,
+       169, 104, 121, 145,  21, 178,   7,  63, 148, 194,  16, 137,  11,  34,  95,  33,
+       128, 127,  93, 154,  90, 144,  50,  39,  53,  62, 204, 231, 191, 247, 151,   3,
+       255,  25,  48, 179,  72, 165, 181, 209, 215,  94, 146,  42, 172,  86, 170, 198,
+        79, 184,  56, 210, 150, 164, 125, 182, 118, 252, 107, 226, 156, 116,   4, 241,
+        69, 157, 112,  89, 100, 113, 135,  32, 134,  91, 207, 101, 230,  45, 168,   2,
+        27,  96,  37, 173, 174, 176, 185, 246,  28,  70,  97, 105,  52,  64, 126,  15,
+        85,  71, 163,  35, 221,  81, 175,  58, 195,  92, 249, 206, 186, 197, 234,  38,
+        44,  83,  13, 110, 133,  40, 132,   9, 211, 223, 205, 244,  65, 129,  77,  82,
+       106, 220,  55, 200, 108, 193, 171, 250,  36, 225, 123,   8,  12, 189, 177,  74,
+       120, 136, 149, 139, 227,  99, 232, 109, 233, 203, 213, 254,  59,   0,  29,  57,
+       242, 239, 183,  14, 102,  88, 208, 228, 166, 119, 114, 248, 235, 117,  75,  10,
+        49,  68,  80, 180, 143, 237,  31,  26, 219, 153, 141,  51, 159,  17, 131,  20 };
+
+PHP_HASH_API void PHP_MD2Init(PHP_MD2_CTX *context)
+{
+       memset(context, 0, sizeof(PHP_MD2_CTX));
+}
+
+static void MD2_Transform(PHP_MD2_CTX *context, const unsigned char *block)
+{
+       unsigned char i,j,t = 0;
+
+       for(i = 0; i < 16; i++) {
+               context->state[16+i] = block[i];
+               context->state[32+i] = (context->state[16+i] ^ context->state[i]);
+       }
+
+       for(i = 0; i < 18; i++) {
+               for(j = 0; j < 48; j++) {
+                       t = context->state[j] = context->state[j] ^ MD2_S[t];
+               }
+               t += i;
+       }
+
+       /* Update checksum -- must be after transform to avoid fouling up last message block */
+       t = context->checksum[15];
+       for(i = 0; i < 16; i++) {
+               t = context->checksum[i] ^= MD2_S[block[i] ^ t];
+       }
+}
+
+PHP_HASH_API void PHP_MD2Update(PHP_MD2_CTX *context, const unsigned char *buf, unsigned int len)
+{
+       const unsigned char *p = buf, *e = buf + len;
+
+       if (context->in_buffer) {
+               if (context->in_buffer + len < 16) {
+                       /* Not enough for block, just pass into buffer */
+                       memcpy(context->buffer + context->in_buffer, p, len);
+                       context->in_buffer += len;
+                       return;
+               }
+               /* Put buffered data together with inbound for a single block */
+               memcpy(context->buffer + context->in_buffer, p, 16 - context->in_buffer);
+               MD2_Transform(context, context->buffer);
+               p += 16 - context->in_buffer;
+               context->in_buffer = 0;
+       }
+
+       /* Process as many whole blocks as remain */
+       while ((p + 16) <= e) {
+               MD2_Transform(context, p);
+               p += 16;
+       }
+
+       /* Copy remaining data to buffer */
+       if (p < e) {
+               memcpy(context->buffer, p, e - p);
+               context->in_buffer = e - p;
+       }
+}
+
+PHP_HASH_API void PHP_MD2Final(unsigned char output[16], PHP_MD2_CTX *context)
+{
+       memset(context->buffer + context->in_buffer, 16 - context->in_buffer, 16 - context->in_buffer);
+       MD2_Transform(context, context->buffer);
+       MD2_Transform(context, context->checksum);
+
+       memcpy(output, context->state, 16);
+}
+
+
 /*
  * Local variables:
  * tab-width: 4
index 7aaf7ff027dde34efd47392f2387f68964030499..2ff444a8fa45b0e24067fc3f4ff08b9fe99cd5d6 100644 (file)
@@ -26,6 +26,7 @@
     <date>2006-02-00</date>
     <notes>
 Fixed tiger algorithm generating wrong results on big endian platforms.
+Add md2 support
     </notes>
    </release>
 
@@ -82,6 +83,7 @@ Supported Algorithms:
    <file role="doc" name="README"/>
    <dir role="test" name="tests">
     <file role="test" name="hmac-md5.phpt"/>
+    <file role="test" name="md2.phpt"/>
     <file role="test" name="md4.phpt"/>
     <file role="test" name="md5.phpt"/>
     <file role="test" name="sha1.phpt"/>
index 4587f2b518db4beb5135d660fc2a8b672eeb7e6a..524b2b755165e36925a379e58726ba407077a390 100644 (file)
@@ -52,6 +52,7 @@ typedef struct _php_hash_data {
        unsigned char *key;
 } php_hash_data;
 
+extern php_hash_ops php_hash_md2_ops;
 extern php_hash_ops php_hash_md4_ops;
 extern php_hash_ops php_hash_md5_ops;
 extern php_hash_ops php_hash_sha1_ops;
index 30bf6a160206c5f4ac0998cb06dab5a0be6a68dd..66a0c88ef5944a0fe75e897980d703a82025c34a 100644 (file)
@@ -85,4 +85,16 @@ typedef struct {
 PHP_HASH_API void PHP_MD4Update(PHP_MD4_CTX *context, const unsigned char *, unsigned int);
 PHP_HASH_API void PHP_MD4Final(unsigned char[16], PHP_MD4_CTX *);
 
+/* MD2 context */
+typedef struct {
+       unsigned char state[48];
+       unsigned char checksum[16];
+       unsigned char buffer[16];
+       char in_buffer;
+} PHP_MD2_CTX;
+
+PHP_HASH_API void PHP_MD2Init(PHP_MD2_CTX *context);
+PHP_HASH_API void PHP_MD2Update(PHP_MD2_CTX *context, const unsigned char *, unsigned int);
+PHP_HASH_API void PHP_MD2Final(unsigned char[16], PHP_MD2_CTX *);
+
 #endif
diff --git a/ext/hash/tests/md2.phpt b/ext/hash/tests/md2.phpt
new file mode 100644 (file)
index 0000000..c98ad34
--- /dev/null
@@ -0,0 +1,21 @@
+--TEST--
+md2 algorithm
+--SKIPIF--
+<?php if(!extension_loaded("hash")) print "skip"; ?>
+--FILE--
+<?php
+echo hash('md2', '') . "\n";
+echo hash('md2', 'a') . "\n";
+echo hash('md2', 'abc') . "\n";
+echo hash('md2', 'message digest') . "\n";
+echo hash('md2', 'abcdefghijklmnopqrstuvwxyz') . "\n";
+echo hash('md2', 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789') . "\n";
+echo hash('md2', '12345678901234567890123456789012345678901234567890123456789012345678901234567890') . "\n";
+--EXPECT--
+8350e5a3e24c153df2275c9f80692773
+32ec01ec4a6dac72c0ab96fb34c0b5d1
+da853b0d3f88d99b30283a69e6ded6bb
+ab4f496bfb2a530b219ff33031fe06b0
+4e8ddff3650292ab5a4108c3aa47940b
+da33def2a42df13975352846c30338cd
+d5976f79d83d3a0dc9806c3c66f3efd8