home *** CD-ROM | disk | FTP | other *** search
/ PSION CD 2 / PsionCDVol2.iso / Programs / 720 / PDF090B4-SorceCode / pdf / decrypt.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2000-09-28  |  10.3 KB  |  319 lines

  1. //========================================================================
  2. //
  3. // Decrypt.cc
  4. //
  5. // Copyright 1996 Derek B. Noonburg
  6. //
  7. //========================================================================
  8. //
  9. // Ported to EPOC by Sander van der Wal
  10. //
  11. // $Log: decrypt.cpp $
  12. // Revision 1.1  2000-09-28 09:25:10+02  svdwal
  13. // Initial checkin
  14. //
  15.  
  16. #ifdef __GNUC__
  17. #pragma implementation
  18. #endif
  19.  
  20. //#include "gmem.h"
  21. #include "Decrypt.h"
  22.  
  23. //static inline void* memcpy(void* s1, const void* s2, size_t n)
  24. //{ return (void*) Mem::Copy(s1, s2, n); }
  25.  
  26. //static inline int memcmp(const void* s1, const void* s2, size_t n)
  27. //{ return Mem::Compare((const TUint8*)s1, n, (const TUint8*)s2, n); }
  28.  
  29. static void rc4InitKey(Guchar *key, int keyLen, Guchar *state);
  30. static Guchar rc4DecryptByte(Guchar *state, Guchar *x, Guchar *y, Guchar c);
  31. static void md5(Guchar *msg, int msgLen, Guchar *digest);
  32.  
  33. static const Guchar passwordPad[32] = {
  34.   0x28, 0xbf, 0x4e, 0x5e, 0x4e, 0x75, 0x8a, 0x41,
  35.   0x64, 0x00, 0x4e, 0x56, 0xff, 0xfa, 0x01, 0x08, 
  36.   0x2e, 0x2e, 0x00, 0xb6, 0xd0, 0x68, 0x3e, 0x80, 
  37.   0x2f, 0x0c, 0xa9, 0xfe, 0x64, 0x53, 0x69, 0x7a
  38. };
  39.  
  40. //------------------------------------------------------------------------
  41. // Decrypt
  42. //------------------------------------------------------------------------
  43.  
  44. Decrypt::Decrypt(Guchar *fileKey, int objNum, int objGen) {
  45.   // construct object key
  46.   objKey[0] = fileKey[0];
  47.   objKey[1] = fileKey[1];
  48.   objKey[2] = fileKey[2];
  49.   objKey[3] = fileKey[3];
  50.   objKey[4] = fileKey[4];
  51.   objKey[5] = objNum & 0xff;
  52.   objKey[6] = (objNum >> 8) & 0xff;
  53.   objKey[7] = (objNum >> 16) & 0xff;
  54.   objKey[8] = objGen & 0xff;
  55.   objKey[9] = (objGen >> 8) & 0xff;
  56.   md5(objKey, 10, objKey);
  57.  
  58.   // set up for decryption
  59.   x = y = 0;
  60.   rc4InitKey(objKey, 10, state);
  61. }
  62.  
  63. void Decrypt::reset() {
  64.   x = y = 0;
  65.   rc4InitKey(objKey, 10, state);
  66. }
  67.  
  68. Guchar Decrypt::decryptByte(Guchar c) {
  69.   return rc4DecryptByte(state, &x, &y, c);
  70. }
  71.  
  72. GBool Decrypt::makeFileKeyL(GString *ownerKey, GString *userKey,
  73.                 int permissions, GString *fileID,
  74.                 GString *userPassword, Guchar *fileKey) {
  75.   Guchar *buf;
  76.   Guchar userTest[32];
  77.   Guchar fState[256];
  78.   Guchar fx, fy;
  79.   int len, i;
  80.   GBool ok;
  81.  
  82.   // generate file key
  83.   buf = (Guchar *)User::AllocLC(68 + fileID->getLength());
  84.   if (userPassword) {
  85.     len = userPassword->getLength();
  86.     if (len < 32) {
  87.       Mem::Copy(buf, userPassword->getCString(), len);
  88.       Mem::Copy(buf + len, passwordPad, 32 - len);
  89.     } else {
  90.       Mem::Copy(buf, userPassword->getCString(), 32);
  91.     }
  92.   } else {
  93.     Mem::Copy(buf, passwordPad, 32);
  94.   }
  95.   Mem::Copy(buf + 32, ownerKey->getCString(), 32);
  96.   buf[64] = permissions & 0xff;
  97.   buf[65] = (permissions >> 8) & 0xff;
  98.   buf[66] = (permissions >> 16) & 0xff;
  99.   buf[67] = (permissions >> 24) & 0xff;
  100.   Mem::Copy(buf + 68, fileID->getCString(), fileID->getLength());
  101.   md5(buf, 68 + fileID->getLength(), fileKey);
  102.  
  103.   // test user key
  104.   fx = fy = 0;
  105.   rc4InitKey(fileKey, 5, fState);
  106.   for (i = 0; i < 32; ++i) {
  107.     userTest[i] = rc4DecryptByte(fState, &fx, &fy, userKey->getChar(i));
  108.   }
  109.   ok = Mem::Compare(userTest, 32, passwordPad, 32) == 0;
  110.  
  111.   CleanupStack::PopAndDestroy(); // buf;
  112.  
  113.   return ok;
  114. }
  115.  
  116. //------------------------------------------------------------------------
  117. // RC4-compatible decryption
  118. //------------------------------------------------------------------------
  119.  
  120. static void rc4InitKey(Guchar *key, int keyLen, Guchar *state) {
  121.   Guchar index1, index2;
  122.   Guchar t;
  123.   int i;
  124.  
  125.   for (i = 0; i < 256; ++i)
  126.     state[i] = i;
  127.   index1 = index2 = 0;
  128.   for (i = 0; i < 256; ++i) {
  129.     index2 = (key[index1] + state[i] + index2) % 256;
  130.     t = state[i];
  131.     state[i] = state[index2];
  132.     state[index2] = t;
  133.     index1 = (index1 + 1) % keyLen;
  134.   }
  135. }
  136.  
  137. static Guchar rc4DecryptByte(Guchar *state, Guchar *x, Guchar *y, Guchar c) {
  138.   Guchar x1, y1, tx, ty;
  139.  
  140.   x1 = *x = (*x + 1) % 256;
  141.   y1 = *y = (state[*x] + *y) % 256;
  142.   tx = state[x1];
  143.   ty = state[y1];
  144.   state[x1] = ty;
  145.   state[y1] = tx;
  146.   return c ^ state[(tx + ty) % 256];
  147. }
  148.  
  149. //------------------------------------------------------------------------
  150. // MD5 message digest
  151. //------------------------------------------------------------------------
  152.  
  153. static inline Gulong rotateLeft(Gulong x, int r) {
  154.   x &= 0xffffffff;
  155.   return ((x << r) | (x >> (32 - r))) & 0xffffffff;
  156. }
  157.  
  158. static inline Gulong md5Round1(Gulong a, Gulong b, Gulong c, Gulong d,
  159.                    Gulong Xk,  Gulong s, Gulong Ti) {
  160.   return b + rotateLeft((a + ((b & c) | (~b & d)) + Xk + Ti), s);
  161. }
  162.  
  163. static inline Gulong md5Round2(Gulong a, Gulong b, Gulong c, Gulong d,
  164.                    Gulong Xk,  Gulong s, Gulong Ti) {
  165.   return b + rotateLeft((a + ((b & d) | (c & ~d)) + Xk + Ti), s);
  166. }
  167.  
  168. static inline Gulong md5Round3(Gulong a, Gulong b, Gulong c, Gulong d,
  169.                    Gulong Xk,  Gulong s, Gulong Ti) {
  170.   return b + rotateLeft((a + (b ^ c ^ d) + Xk + Ti), s);
  171. }
  172.  
  173. static inline Gulong md5Round4(Gulong a, Gulong b, Gulong c, Gulong d,
  174.                    Gulong Xk,  Gulong s, Gulong Ti) {
  175.   return b + rotateLeft((a + (c ^ (b | ~d)) + Xk + Ti), s);
  176. }
  177.  
  178. static void md5(Guchar *msg, int msgLen, Guchar *digest) {
  179.   Gulong x[16];
  180.   Gulong a, b, c, d, aa, bb, cc, dd;
  181.   int n64;
  182.   int i, j, k;
  183.  
  184.   // compute number of 64-byte blocks
  185.   // (length + pad byte (0x80) + 8 bytes for length)
  186.   n64 = (msgLen + 1 + 8 + 63) / 64;
  187.  
  188.   // initialize a, b, c, d
  189.   a = 0x67452301;
  190.   b = 0xefcdab89;
  191.   c = 0x98badcfe;
  192.   d = 0x10325476;
  193.  
  194.   // loop through blocks
  195.   k = 0;
  196.   for (i = 0; i < n64; ++i) {
  197.  
  198.     // grab a 64-byte block
  199.     for (j = 0; j < 16 && k < msgLen - 3; ++j, k += 4)
  200.       x[j] = (((((msg[k+3] << 8) + msg[k+2]) << 8) + msg[k+1]) << 8) + msg[k];
  201.     if (i == n64 - 1) {
  202.       if (k == msgLen - 3)
  203.     x[j] = 0x80000000 + (((msg[k+2] << 8) + msg[k+1]) << 8) + msg[k];
  204.       else if (k == msgLen - 2)
  205.     x[j] = 0x800000 + (msg[k+1] << 8) + msg[k];
  206.       else if (k == msgLen - 1)
  207.     x[j] = 0x8000 + msg[k];
  208.       else
  209.     x[j] = 0x80;
  210.       ++j;
  211.       while (j < 16)
  212.     x[j++] = 0;
  213.       x[14] = msgLen << 3;
  214.     }
  215.  
  216.     // save a, b, c, d
  217.     aa = a;
  218.     bb = b;
  219.     cc = c;
  220.     dd = d;
  221.  
  222.     // round 1
  223.     a = md5Round1(a, b, c, d, x[0],   7, 0xd76aa478);
  224.     d = md5Round1(d, a, b, c, x[1],  12, 0xe8c7b756);
  225.     c = md5Round1(c, d, a, b, x[2],  17, 0x242070db);
  226.     b = md5Round1(b, c, d, a, x[3],  22, 0xc1bdceee);
  227.     a = md5Round1(a, b, c, d, x[4],   7, 0xf57c0faf);
  228.     d = md5Round1(d, a, b, c, x[5],  12, 0x4787c62a);
  229.     c = md5Round1(c, d, a, b, x[6],  17, 0xa8304613);
  230.     b = md5Round1(b, c, d, a, x[7],  22, 0xfd469501);
  231.     a = md5Round1(a, b, c, d, x[8],   7, 0x698098d8);
  232.     d = md5Round1(d, a, b, c, x[9],  12, 0x8b44f7af);
  233.     c = md5Round1(c, d, a, b, x[10], 17, 0xffff5bb1);
  234.     b = md5Round1(b, c, d, a, x[11], 22, 0x895cd7be);
  235.     a = md5Round1(a, b, c, d, x[12],  7, 0x6b901122);
  236.     d = md5Round1(d, a, b, c, x[13], 12, 0xfd987193);
  237.     c = md5Round1(c, d, a, b, x[14], 17, 0xa679438e);
  238.     b = md5Round1(b, c, d, a, x[15], 22, 0x49b40821);
  239.  
  240.     // round 2
  241.     a = md5Round2(a, b, c, d, x[1],   5, 0xf61e2562);
  242.     d = md5Round2(d, a, b, c, x[6],   9, 0xc040b340);
  243.     c = md5Round2(c, d, a, b, x[11], 14, 0x265e5a51);
  244.     b = md5Round2(b, c, d, a, x[0],  20, 0xe9b6c7aa);
  245.     a = md5Round2(a, b, c, d, x[5],   5, 0xd62f105d);
  246.     d = md5Round2(d, a, b, c, x[10],  9, 0x02441453);
  247.     c = md5Round2(c, d, a, b, x[15], 14, 0xd8a1e681);
  248.     b = md5Round2(b, c, d, a, x[4],  20, 0xe7d3fbc8);
  249.     a = md5Round2(a, b, c, d, x[9],   5, 0x21e1cde6);
  250.     d = md5Round2(d, a, b, c, x[14],  9, 0xc33707d6);
  251.     c = md5Round2(c, d, a, b, x[3],  14, 0xf4d50d87);
  252.     b = md5Round2(b, c, d, a, x[8],  20, 0x455a14ed);
  253.     a = md5Round2(a, b, c, d, x[13],  5, 0xa9e3e905);
  254.     d = md5Round2(d, a, b, c, x[2],   9, 0xfcefa3f8);
  255.     c = md5Round2(c, d, a, b, x[7],  14, 0x676f02d9);
  256.     b = md5Round2(b, c, d, a, x[12], 20, 0x8d2a4c8a);
  257.  
  258.     // round 3
  259.     a = md5Round3(a, b, c, d, x[5],   4, 0xfffa3942);
  260.     d = md5Round3(d, a, b, c, x[8],  11, 0x8771f681);
  261.     c = md5Round3(c, d, a, b, x[11], 16, 0x6d9d6122);
  262.     b = md5Round3(b, c, d, a, x[14], 23, 0xfde5380c);
  263.     a = md5Round3(a, b, c, d, x[1],   4, 0xa4beea44);
  264.     d = md5Round3(d, a, b, c, x[4],  11, 0x4bdecfa9);
  265.     c = md5Round3(c, d, a, b, x[7],  16, 0xf6bb4b60);
  266.     b = md5Round3(b, c, d, a, x[10], 23, 0xbebfbc70);
  267.     a = md5Round3(a, b, c, d, x[13],  4, 0x289b7ec6);
  268.     d = md5Round3(d, a, b, c, x[0],  11, 0xeaa127fa);
  269.     c = md5Round3(c, d, a, b, x[3],  16, 0xd4ef3085);
  270.     b = md5Round3(b, c, d, a, x[6],  23, 0x04881d05);
  271.     a = md5Round3(a, b, c, d, x[9],   4, 0xd9d4d039);
  272.     d = md5Round3(d, a, b, c, x[12], 11, 0xe6db99e5);
  273.     c = md5Round3(c, d, a, b, x[15], 16, 0x1fa27cf8);
  274.     b = md5Round3(b, c, d, a, x[2],  23, 0xc4ac5665);
  275.  
  276.     // round 4
  277.     a = md5Round4(a, b, c, d, x[0],   6, 0xf4292244);
  278.     d = md5Round4(d, a, b, c, x[7],  10, 0x432aff97);
  279.     c = md5Round4(c, d, a, b, x[14], 15, 0xab9423a7);
  280.     b = md5Round4(b, c, d, a, x[5],  21, 0xfc93a039);
  281.     a = md5Round4(a, b, c, d, x[12],  6, 0x655b59c3);
  282.     d = md5Round4(d, a, b, c, x[3],  10, 0x8f0ccc92);
  283.     c = md5Round4(c, d, a, b, x[10], 15, 0xffeff47d);
  284.     b = md5Round4(b, c, d, a, x[1],  21, 0x85845dd1);
  285.     a = md5Round4(a, b, c, d, x[8],   6, 0x6fa87e4f);
  286.     d = md5Round4(d, a, b, c, x[15], 10, 0xfe2ce6e0);
  287.     c = md5Round4(c, d, a, b, x[6],  15, 0xa3014314);
  288.     b = md5Round4(b, c, d, a, x[13], 21, 0x4e0811a1);
  289.     a = md5Round4(a, b, c, d, x[4],   6, 0xf7537e82);
  290.     d = md5Round4(d, a, b, c, x[11], 10, 0xbd3af235);
  291.     c = md5Round4(c, d, a, b, x[2],  15, 0x2ad7d2bb);
  292.     b = md5Round4(b, c, d, a, x[9],  21, 0xeb86d391);
  293.  
  294.     // increment a, b, c, d
  295.     a += aa;
  296.     b += bb;
  297.     c += cc;
  298.     d += dd;
  299.   }
  300.  
  301.   // break digest into bytes
  302.   digest[0] = a & 0xff;
  303.   digest[1] = (a >>= 8) & 0xff;
  304.   digest[2] = (a >>= 8) & 0xff;
  305.   digest[3] = (a >>= 8) & 0xff;
  306.   digest[4] = b & 0xff;
  307.   digest[5] = (b >>= 8) & 0xff;
  308.   digest[6] = (b >>= 8) & 0xff;
  309.   digest[7] = (b >>= 8) & 0xff;
  310.   digest[8] = c & 0xff;
  311.   digest[9] = (c >>= 8) & 0xff;
  312.   digest[10] = (c >>= 8) & 0xff;
  313.   digest[11] = (c >>= 8) & 0xff;
  314.   digest[12] = d & 0xff;
  315.   digest[13] = (d >>= 8) & 0xff;
  316.   digest[14] = (d >>= 8) & 0xff;
  317.   digest[15] = (d >>= 8) & 0xff;
  318. }
  319.