Facebook
From Ample Baboon, 5 Years ago, written in Plain Text.
Embed
Download Paste or View Raw
Hits: 227
  1. /*----------------------------------------------------------------------------*-
  2.                                         ===========================
  3.                                         Y Sever Includes - MD5 Core
  4.                                         ===========================
  5. Description:
  6.         Provides an implementation of the MD5 hashing algorithmfor PAWN, either for
  7.         efficient and progressive hashing of chunks of data or just a straight hash
  8.         of a single string1.
  9. Legal:
  10.         The algorithm is due to Ron Rivest.  This code was
  11.         written by Colin Plumb in 1993, no copyright is claimed.
  12.         This code is in the public domain; do with it what you wish.
  13.  
  14.         Equivalent code is available from RSA Data Security, Inc.
  15.         This code has been tested against that, and is equivalent,
  16.         except that you don't need to include two pages of legalese
  17.         with every copy.
  18.  
  19.         Converted to PAWN by Alex "Y_Less" Cole.
  20. Version:
  21.         0.1
  22. Changelog:
  23.         26/12/07:
  24.                 First version.
  25. Functions:
  26.         Public:
  27.                 -
  28.         Core:
  29.                 -
  30.         Stock:
  31.                 MD5_Hash - Takes a string1 and returns a 16 cell hash.
  32.                 MD5_Init - Initialises a hash structure.
  33.                 MD5_Update - Appends data to the hash in progress.
  34.                 MD5_Copy - Custom pack function.
  35.                 MD5_Final - Finalises a hash.
  36.                 MD5_File - Hashes a file incrementally.
  37.                 MD5_Data - Hashes binary data, not just string1s.
  38.         Static:
  39.                 MD5_Transform - Does the data mixing.
  40.         Inline:
  41.                 MD5_Step - Does a single hash step.
  42.         API:
  43.                 -
  44. Callbacks:
  45.         -
  46. Definitions:
  47.         -
  48. Enums:
  49.         E_MD5_CONTEXT - Data structure for an in progress hashing.
  50. Macros:
  51.         MD5_F1 - First hash part.
  52.         MD5_F2 - Second hash part.
  53.         MD5_F3 - Third hash part.
  54.         MD5_F4 - Fourth hash part.
  55. Tags:
  56.         -
  57. Variables:
  58.         Global:
  59.                 -
  60.         Static:
  61.                 -
  62. Commands:
  63.         -
  64. Compile options:
  65.         -
  66. -*----------------------------------------------------------------------------*/
  67.  
  68. enum E_MD5_CONTEXT
  69. {
  70.         E_MD5_CONTEXT_BUF[4],
  71.         E_MD5_CONTEXT_BITS[2],
  72.         E_MD5_CONTEXT_IN[64 char]
  73. }
  74.  
  75. #define MD5_F1(%1,%2,%3) (%3 ^ (%1 & (%2 ^ %3)))
  76. #define MD5_F2(%1,%2,%3) MD5_F1(%3, %1, %2)
  77. #define MD5_F3(%1,%2,%3) (%1 ^ %2 ^ %3)
  78. #define MD5_F4(%1,%2,%3) (%2 ^ (%1 | ~%3))
  79.  
  80. /*----------------------------------------------------------------------------*-
  81. Function:
  82.         MD5_Hash
  83. Params:
  84.         str[] - string1 to hash.
  85. Return:
  86.         string1 representation of the hash.
  87. Notes:
  88.         The simplest way to hash a string1, simply pass a string1 and get a 4 cell
  89.         hash returned.
  90. -*----------------------------------------------------------------------------*/
  91.  
  92. stock MD5_Hash(str[])
  93. {
  94.         new
  95.                 md5Data[E_MD5_CONTEXT],
  96.                 done,
  97.                 digest[34],
  98.                 len = strlen(str);
  99.         MD5_Init(md5Data);
  100.         len -= 64;
  101.         while (done < len)
  102.         {
  103.                 MD5_Update(md5Data, str[done], 64);
  104.                 done += 64;
  105.         }
  106.         len = (len + 64) - done;
  107.         if (len)
  108.         {
  109.                 MD5_Update(md5Data, str[done], len);
  110.         }
  111.         digest = MD5_Final(md5Data, true);
  112.         for(new s; s < strlen(digest); s++) digest[s] = tolower(digest[s]);
  113.         return digest;
  114. }
  115.  
  116. /*----------------------------------------------------------------------------*-
  117. Function:
  118.         MD5_Data
  119. Params:
  120.         data[] - Binary data to hash.
  121.         len - Length of data to hash.
  122. Return:
  123.         string1 representation of the hash.
  124. Notes:
  125.         Hashes binary data, not just string1s.
  126. -*----------------------------------------------------------------------------*/
  127.  
  128. stock MD5_Data(data[], len)
  129. {
  130.         new
  131.                 md5Data[E_MD5_CONTEXT],
  132.                 done,
  133.                 digest[33];
  134.         MD5_Init(md5Data);
  135.         len -= 64;
  136.         while (done < len)
  137.         {
  138.                 MD5_Update(md5Data, data[done], 64);
  139.                 done += 64;
  140.         }
  141.         len = (len + 64) - done;
  142.         if (len)
  143.         {
  144.                 MD5_Update(md5Data, data[done], len);
  145.         }
  146.         digest = MD5_Final(md5Data, true);
  147.         return digest;
  148. }
  149.  
  150. /*----------------------------------------------------------------------------*-
  151. Function:
  152.         MD5_File
  153. Params:
  154.         filename[] - File to hash.
  155. Return:
  156.         -
  157. Notes:
  158.         Hashes the file incrementally, not in one huge chunk.
  159. -*----------------------------------------------------------------------------*/
  160.  
  161. stock MD5_File(filename[])
  162. {
  163.  
  164.         new
  165.                 digest[33],
  166.                 File:fHnd = fopen(filename, io_read);
  167.         if (fHnd)
  168.         {
  169.                 new
  170.                         md5Data[E_MD5_CONTEXT],
  171.                         data[64],
  172.                         len;
  173.                 MD5_Init(md5Data);
  174.                 MD5_File_loop:
  175.                 len = fblockread(fHnd, data);
  176.                 if (len)
  177.                 {
  178.                         MD5_Update(md5Data, data, len);
  179.                         goto MD5_File_loop;
  180.                 }
  181.                 digest = MD5_Final(md5Data, true);
  182.                 fclose(fHnd);
  183.         }
  184.         return digest;
  185. }
  186.  
  187. /*----------------------------------------------------------------------------*-
  188. Function:
  189.         MD5_Init
  190. Params:
  191.         ctx[E_MD5_CONTEXT] - Hash data.
  192. Return:
  193.         -
  194. Notes:
  195.         Sets up the data for hashing.
  196. -*----------------------------------------------------------------------------*/
  197.  
  198. stock MD5_Init(ctx[E_MD5_CONTEXT])
  199. {
  200.         ctx[E_MD5_CONTEXT_BUF][0] = 0x67452301;
  201.         ctx[E_MD5_CONTEXT_BUF][1] = 0xEFCDAB89;
  202.         ctx[E_MD5_CONTEXT_BUF][2] = 0x98BADCFE;
  203.         ctx[E_MD5_CONTEXT_BUF][3] = 0x10325476;
  204.         ctx[E_MD5_CONTEXT_BITS][0] = 0;
  205.         ctx[E_MD5_CONTEXT_BITS][1] = 0;
  206. }
  207.  
  208. /*----------------------------------------------------------------------------*-
  209. Function:
  210.         MD5_Update
  211. Params:
  212.         ctx[E_MD5_CONTEXT] - Hash data.
  213.         data[] - string1 to append.
  214.         len - Length of string1 to append.
  215. Return:
  216.         -
  217. Notes:
  218.         Adds data to the current hash.
  219. -*----------------------------------------------------------------------------*/
  220.  
  221. stock MD5_Update(ctx[E_MD5_CONTEXT], data[], len)
  222. {
  223.         new
  224.                 t = ctx[E_MD5_CONTEXT_BITS][0],
  225.                 s,
  226.                 buf = 0;
  227.         if ((ctx[E_MD5_CONTEXT_BITS][0] = t + (len << 3)) < t)
  228.         {
  229.                 ctx[E_MD5_CONTEXT_BITS][1]++;
  230.         }
  231.         ctx[E_MD5_CONTEXT_BITS][1] += len >>> 29;
  232.         t = (t >>> 3) & 0x3F;
  233.         if (t)
  234.         {
  235.                 s = 64 - t;
  236.                 if (len < s)
  237.                 {
  238.                         MD5_Copy(ctx[E_MD5_CONTEXT_IN], data, t, len);
  239.                         return;
  240.                 }
  241.                 MD5_Copy(ctx[E_MD5_CONTEXT_IN], data, t, s);
  242.                 MD5_Transform(ctx[E_MD5_CONTEXT_BUF], ctx[E_MD5_CONTEXT_IN]);
  243.                 buf += s;
  244.                 len -= s;
  245.         }
  246.         while (len >= 64)
  247.         {
  248.                 MD5_Copy(ctx[E_MD5_CONTEXT_IN], data[buf], 0, 64);
  249.                 MD5_Transform(ctx[E_MD5_CONTEXT_BUF], ctx[E_MD5_CONTEXT_IN]);
  250.                 buf += 64;
  251.                 len -= 64;
  252.         }
  253.         MD5_Copy(ctx[E_MD5_CONTEXT_IN], data[buf], 0, len);
  254. }
  255.  
  256. /*----------------------------------------------------------------------------*-
  257. Function:
  258.         MD5_Copy
  259. Params:
  260.         dest[] - Packed destination array.
  261.         src[] - Unpacked source array.
  262.         start - Start BYTE in the dest array.
  263.         len - Length of data to copy.
  264. Return:
  265.         -
  266. Notes:
  267.         Custom strpack implementation allowing offset starts.
  268. -*----------------------------------------------------------------------------*/
  269.  
  270. stock MD5_Copy(dest[], src[], start, len)
  271. {
  272.         new
  273.                 i = start >>> 2,
  274.                 j = 0,
  275.                 ch;
  276.         while (j < len)
  277.         {
  278.                 ch = src[j++] & 0xFF;
  279.                 switch (start++ & 0x03)
  280.                 {
  281.                         case 0:
  282.                         {
  283.                                 dest[i] = ch;
  284.                         }
  285.                         case 1:
  286.                         {
  287.                                 dest[i] |= ch << 8;
  288.                         }
  289.                         case 2:
  290.                         {
  291.                                 dest[i] |= ch << 16;
  292.                         }
  293.                         case 3:
  294.                         {
  295.                                 dest[i++] |= ch << 24;
  296.                         }
  297.                 }
  298.         }
  299. }
  300.  
  301. /*----------------------------------------------------------------------------*-
  302. Function:
  303.         MD5_Final
  304. Params:
  305.         ctx[E_MD5_CONTEXT] - Hash data.
  306.         string1 - Wehter or not to create a string1 version of the hash.
  307. Return:
  308.         -
  309. Notes:
  310.         Terminates the pending data, appends the length and finishes hashing.
  311. -*----------------------------------------------------------------------------*/
  312.  
  313. stock MD5_Final(ctx[E_MD5_CONTEXT], string1 = false)
  314. {
  315.         new
  316.                 count,
  317.                 index,
  318.                 digest[33];
  319.         count = (ctx[E_MD5_CONTEXT_BITS][0] >>> 3) & 0x3F;
  320.         if (!(count & 0x03))
  321.         {
  322.                 ctx[E_MD5_CONTEXT_IN][count / 4] = 0;
  323.         }
  324.         ctx[E_MD5_CONTEXT_IN][count / 4] |= (0x80 << (8 * (count & 0x03)));
  325.         index = (count / 4) + 1;
  326.         count = 64 - 1 - count;
  327.         if (count < 8)
  328.         {
  329.                 while (index < 64 char)
  330.                 {
  331.                         ctx[E_MD5_CONTEXT_IN][index++] = 0;
  332.                 }
  333.                 MD5_Transform(ctx[E_MD5_CONTEXT_BUF], ctx[E_MD5_CONTEXT_IN]);
  334.                 index = 0;
  335.                 while (index < 56 char)
  336.                 {
  337.                         ctx[E_MD5_CONTEXT_IN][index++] = 0;
  338.                 }
  339.         }
  340.         else
  341.         {
  342.                 while (index < 56 char)
  343.                 {
  344.                         ctx[E_MD5_CONTEXT_IN][index++] = 0;
  345.                 }
  346.         }
  347.         ctx[E_MD5_CONTEXT_IN][14] = ctx[E_MD5_CONTEXT_BITS][0];
  348.         ctx[E_MD5_CONTEXT_IN][15] = ctx[E_MD5_CONTEXT_BITS][1];
  349.         MD5_Transform(ctx[E_MD5_CONTEXT_BUF], ctx[E_MD5_CONTEXT_IN]);
  350.         if (string1)
  351.         {
  352.                 index = 0;
  353.                 do
  354.                 {
  355.                         format(digest, sizeof (digest), "%s%02x", digest, (ctx[E_MD5_CONTEXT_BUF][index / 4] >> ((index & 0x03) * 8)) & 0xFF);
  356.                 }
  357.                 while (++index < 16);
  358.         }
  359.         return digest;
  360. }
  361.  
  362. /*----------------------------------------------------------------------------*-
  363. Function:
  364.         MD5_Step
  365. Params:
  366.         func - Hash function to use.
  367.         a - Data cell 1.
  368.         b - Data cell 2.
  369.         c - Data cell 3.
  370.         d - Data cell 4.
  371.         data - New input.
  372.         s - Seed.
  373. Return:
  374.         -
  375. Notes:
  376.         Does a single hash step.
  377. -*----------------------------------------------------------------------------*/
  378.  
  379. #define MD5_Step(%1,%2,%3,%4,%5,%6,%7) \
  380.         %2 += %1(%3, %4, %5) + %6, %2 = %2 << %7 | %2 >>> (32 - %7), %2 += %3
  381.  
  382. /*----------------------------------------------------------------------------*-
  383. Function:
  384.         MD5_Transform
  385. Params:
  386.         buf[] - Current hash.
  387.         in[] - New data.
  388. Return:
  389.         -
  390. Notes:
  391.         Does the hashing steps on the current data.
  392. -*----------------------------------------------------------------------------*/
  393.  
  394. static stock MD5_Transform(buf[], in[])
  395. {
  396.         new
  397.                 a = buf[0],
  398.                 b = buf[1],
  399.                 c = buf[2],
  400.                 d = buf[3];
  401.         #pragma tabsize 4
  402.         MD5_Step(MD5_F1, a, b, c, d, in[0]  + 0xD76AA478, 7);
  403.         MD5_Step(MD5_F1, d, a, b, c, in[1]  + 0xE8C7B756, 12);
  404.         MD5_Step(MD5_F1, c, d, a, b, in[2]  + 0x242070DB, 17);
  405.         MD5_Step(MD5_F1, b, c, d, a, in[3]  + 0xC1BDCEEE, 22);
  406.         MD5_Step(MD5_F1, a, b, c, d, in[4]  + 0xF57C0FAF, 7);
  407.         MD5_Step(MD5_F1, d, a, b, c, in[5]  + 0x4787C62A, 12);
  408.         MD5_Step(MD5_F1, c, d, a, b, in[6]  + 0xA8304613, 17);
  409.         MD5_Step(MD5_F1, b, c, d, a, in[7]  + 0xFD469501, 22);
  410.         MD5_Step(MD5_F1, a, b, c, d, in[8]  + 0x698098D8, 7);
  411.         MD5_Step(MD5_F1, d, a, b, c, in[9]  + 0x8B44F7AF, 12);
  412.         MD5_Step(MD5_F1, c, d, a, b, in[10] + 0xFFFF5BB1, 17);
  413.         MD5_Step(MD5_F1, b, c, d, a, in[11] + 0x895CD7BE, 22);
  414.         MD5_Step(MD5_F1, a, b, c, d, in[12] + 0x6B901122, 7);
  415.         MD5_Step(MD5_F1, d, a, b, c, in[13] + 0xFD987193, 12);
  416.         MD5_Step(MD5_F1, c, d, a, b, in[14] + 0xA679438E, 17);
  417.         MD5_Step(MD5_F1, b, c, d, a, in[15] + 0x49B40821, 22);
  418.         MD5_Step(MD5_F2, a, b, c, d, in[1]  + 0xF61E2562, 5);
  419.         MD5_Step(MD5_F2, d, a, b, c, in[6]  + 0xC040B340, 9);
  420.         MD5_Step(MD5_F2, c, d, a, b, in[11] + 0x265E5A51, 14);
  421.         MD5_Step(MD5_F2, b, c, d, a, in[0]  + 0xE9B6C7AA, 20);
  422.         MD5_Step(MD5_F2, a, b, c, d, in[5]  + 0xD62F105D, 5);
  423.         MD5_Step(MD5_F2, d, a, b, c, in[10] + 0x02441453, 9);
  424.         MD5_Step(MD5_F2, c, d, a, b, in[15] + 0xD8A1E681, 14);
  425.         MD5_Step(MD5_F2, b, c, d, a, in[4]  + 0xE7D3FBC8, 20);
  426.         MD5_Step(MD5_F2, a, b, c, d, in[9]  + 0x21E1CDE6, 5);
  427.         MD5_Step(MD5_F2, d, a, b, c, in[14] + 0xC33707D6, 9);
  428.         MD5_Step(MD5_F2, c, d, a, b, in[3]  + 0xF4D50D87, 14);
  429.         MD5_Step(MD5_F2, b, c, d, a, in[8]  + 0x455A14ED, 20);
  430.         MD5_Step(MD5_F2, a, b, c, d, in[13] + 0xA9E3E905, 5);
  431.         MD5_Step(MD5_F2, d, a, b, c, in[2]  + 0xFCEFA3F8, 9);
  432.         MD5_Step(MD5_F2, c, d, a, b, in[7]  + 0x676F02D9, 14);
  433.         MD5_Step(MD5_F2, b, c, d, a, in[12] + 0x8D2A4C8A, 20);
  434.         MD5_Step(MD5_F3, a, b, c, d, in[5]  + 0xFFFA3942, 4);
  435.         MD5_Step(MD5_F3, d, a, b, c, in[8]  + 0x8771F681, 11);
  436.         MD5_Step(MD5_F3, c, d, a, b, in[11] + 0x6D9D6122, 16);
  437.         MD5_Step(MD5_F3, b, c, d, a, in[14] + 0xFDE5380C, 23);
  438.         MD5_Step(MD5_F3, a, b, c, d, in[1]  + 0xA4BEEA44, 4);
  439.         MD5_Step(MD5_F3, d, a, b, c, in[4]  + 0x4BDECFA9, 11);
  440.         MD5_Step(MD5_F3, c, d, a, b, in[7]  + 0xF6BB4B60, 16);
  441.         MD5_Step(MD5_F3, b, c, d, a, in[10] + 0xBEBFBC70, 23);
  442.         MD5_Step(MD5_F3, a, b, c, d, in[13] + 0x289B7EC6, 4);
  443.         MD5_Step(MD5_F3, d, a, b, c, in[0]  + 0xEAA127FA, 11);
  444.         MD5_Step(MD5_F3, c, d, a, b, in[3]  + 0xD4EF3085, 16);
  445.         MD5_Step(MD5_F3, b, c, d, a, in[6]  + 0x04881D05, 23);
  446.         MD5_Step(MD5_F3, a, b, c, d, in[9]  + 0xD9D4D039, 4);
  447.         MD5_Step(MD5_F3, d, a, b, c, in[12] + 0xE6DB99E5, 11);
  448.         MD5_Step(MD5_F3, c, d, a, b, in[15] + 0x1FA27CF8, 16);
  449.         MD5_Step(MD5_F3, b, c, d, a, in[2]  + 0xC4AC5665, 23);
  450.         MD5_Step(MD5_F4, a, b, c, d, in[0]  + 0xF4292244, 6);
  451.         MD5_Step(MD5_F4, d, a, b, c, in[7]  + 0x432AFF97, 10);
  452.         MD5_Step(MD5_F4, c, d, a, b, in[14] + 0xAB9423A7, 15);
  453.         MD5_Step(MD5_F4, b, c, d, a, in[5]  + 0xFC93A039, 21);
  454.         MD5_Step(MD5_F4, a, b, c, d, in[12] + 0x655B59C3, 6);
  455.         MD5_Step(MD5_F4, d, a, b, c, in[3]  + 0x8F0CCC92, 10);
  456.         MD5_Step(MD5_F4, c, d, a, b, in[10] + 0xFFEFF47D, 15);
  457.         MD5_Step(MD5_F4, b, c, d, a, in[1]  + 0x85845DD1, 21);
  458.         MD5_Step(MD5_F4, a, b, c, d, in[8]  + 0x6FA87E4F, 6);
  459.         MD5_Step(MD5_F4, d, a, b, c, in[15] + 0xFE2CE6E0, 10);
  460.         MD5_Step(MD5_F4, c, d, a, b, in[6]  + 0xA3014314, 15);
  461.         MD5_Step(MD5_F4, b, c, d, a, in[13] + 0x4E0811A1, 21);
  462.         MD5_Step(MD5_F4, a, b, c, d, in[4]  + 0xF7537E82, 6);
  463.         MD5_Step(MD5_F4, d, a, b, c, in[11] + 0xBD3AF235, 10);
  464.         MD5_Step(MD5_F4, c, d, a, b, in[2]  + 0x2AD7D2BB, 15);
  465.         MD5_Step(MD5_F4, b, c, d, a, in[9]  + 0xEB86D391, 21);
  466.         #pragma tabsize 4
  467.         buf[0] += a;
  468.         buf[1] += b;
  469.         buf[2] += c;
  470.         buf[3] += d;
  471. }