00001
00002
00003
00004
00005
00006
00007
00008
00009 #ifdef __GNUC__
00010 #pragma implementation
00011 #endif
00012
00013 #include <aconf.h>
00014 #include "gmem.h"
00015 #include "Decrypt.h"
00016
00017 static void rc4InitKey(Guchar *key, int keyLen, Guchar *state);
00018 static Guchar rc4DecryptByte(Guchar *state, Guchar *x, Guchar *y, Guchar c);
00019 static void md5(Guchar *msg, int msgLen, Guchar *digest);
00020
00021 static Guchar passwordPad[32] = {
00022 0x28, 0xbf, 0x4e, 0x5e, 0x4e, 0x75, 0x8a, 0x41,
00023 0x64, 0x00, 0x4e, 0x56, 0xff, 0xfa, 0x01, 0x08,
00024 0x2e, 0x2e, 0x00, 0xb6, 0xd0, 0x68, 0x3e, 0x80,
00025 0x2f, 0x0c, 0xa9, 0xfe, 0x64, 0x53, 0x69, 0x7a
00026 };
00027
00028
00029
00030
00031
00032 Decrypt::Decrypt(Guchar *fileKey, int keyLength, int objNum, int objGen) {
00033 int i;
00034
00035
00036 for (i = 0; i < keyLength; ++i) {
00037 objKey[i] = fileKey[i];
00038 }
00039 objKey[keyLength] = objNum & 0xff;
00040 objKey[keyLength + 1] = (objNum >> 8) & 0xff;
00041 objKey[keyLength + 2] = (objNum >> 16) & 0xff;
00042 objKey[keyLength + 3] = objGen & 0xff;
00043 objKey[keyLength + 4] = (objGen >> 8) & 0xff;
00044 md5(objKey, keyLength + 5, objKey);
00045
00046
00047 x = y = 0;
00048 if ((objKeyLength = keyLength + 5) > 16) {
00049 objKeyLength = 16;
00050 }
00051 rc4InitKey(objKey, objKeyLength, state);
00052 }
00053
00054 void Decrypt::reset() {
00055 x = y = 0;
00056 rc4InitKey(objKey, objKeyLength, state);
00057 }
00058
00059 Guchar Decrypt::decryptByte(Guchar c) {
00060 return rc4DecryptByte(state, &x, &y, c);
00061 }
00062
00063 GBool Decrypt::makeFileKey(int encVersion, int encRevision, int keyLength,
00064 GString *ownerKey, GString *userKey,
00065 int permissions, GString *fileID,
00066 GString *ownerPassword, GString *userPassword,
00067 Guchar *fileKey, GBool *ownerPasswordOk) {
00068 Guchar test[32];
00069 GString *userPassword2;
00070 Guchar fState[256];
00071 Guchar fx, fy;
00072 int len, i;
00073
00074
00075 if (ownerPassword) {
00076 len = ownerPassword->getLength();
00077 if (len < 32) {
00078 memcpy(test, ownerPassword->getCString(), len);
00079 memcpy(test + len, passwordPad, 32 - len);
00080 } else {
00081 memcpy(test, ownerPassword->getCString(), 32);
00082 }
00083 } else {
00084 memcpy(test, passwordPad, 32);
00085 }
00086 md5(test, 32, test);
00087 if (encRevision == 3) {
00088 for (i = 0; i < 50; ++i) {
00089 md5(test, 16, test);
00090 }
00091 }
00092 rc4InitKey(test, keyLength, fState);
00093 fx = fy = 0;
00094 for (i = 0; i < 32; ++i) {
00095 test[i] = rc4DecryptByte(fState, &fx, &fy, ownerKey->getChar(i));
00096 }
00097 userPassword2 = new GString((char *)test, 32);
00098 if (makeFileKey2(encVersion, encRevision, keyLength, ownerKey, userKey,
00099 permissions, fileID, userPassword2, fileKey)) {
00100 *ownerPasswordOk = gTrue;
00101 delete userPassword2;
00102 return gTrue;
00103 }
00104 *ownerPasswordOk = gFalse;
00105 delete userPassword2;
00106
00107
00108 return makeFileKey2(encVersion, encRevision, keyLength, ownerKey, userKey,
00109 permissions, fileID, userPassword, fileKey);
00110 }
00111
00112 GBool Decrypt::makeFileKey2(int encVersion, int encRevision, int keyLength,
00113 GString *ownerKey, GString *userKey,
00114 int permissions, GString *fileID,
00115 GString *userPassword, Guchar *fileKey) {
00116 Guchar *buf;
00117 Guchar test[32];
00118 Guchar fState[256];
00119 Guchar tmpKey[16];
00120 Guchar fx, fy;
00121 int len, i, j;
00122 GBool ok;
00123
00124
00125 buf = (Guchar *)gmalloc(68 + fileID->getLength());
00126 if (userPassword) {
00127 len = userPassword->getLength();
00128 if (len < 32) {
00129 memcpy(buf, userPassword->getCString(), len);
00130 memcpy(buf + len, passwordPad, 32 - len);
00131 } else {
00132 memcpy(buf, userPassword->getCString(), 32);
00133 }
00134 } else {
00135 memcpy(buf, passwordPad, 32);
00136 }
00137 memcpy(buf + 32, ownerKey->getCString(), 32);
00138 buf[64] = permissions & 0xff;
00139 buf[65] = (permissions >> 8) & 0xff;
00140 buf[66] = (permissions >> 16) & 0xff;
00141 buf[67] = (permissions >> 24) & 0xff;
00142 memcpy(buf + 68, fileID->getCString(), fileID->getLength());
00143 md5(buf, 68 + fileID->getLength(), fileKey);
00144 if (encRevision == 3) {
00145 for (i = 0; i < 50; ++i) {
00146 md5(fileKey, 16, fileKey);
00147 }
00148 }
00149
00150
00151 if (encRevision == 2) {
00152 rc4InitKey(fileKey, keyLength, fState);
00153 fx = fy = 0;
00154 for (i = 0; i < 32; ++i) {
00155 test[i] = rc4DecryptByte(fState, &fx, &fy, userKey->getChar(i));
00156 }
00157 ok = memcmp(test, passwordPad, 32) == 0;
00158 } else if (encRevision == 3) {
00159 memcpy(test, userKey->getCString(), 32);
00160 for (i = 19; i >= 0; --i) {
00161 for (j = 0; j < keyLength; ++j) {
00162 tmpKey[j] = fileKey[j] ^ i;
00163 }
00164 rc4InitKey(tmpKey, keyLength, fState);
00165 fx = fy = 0;
00166 for (j = 0; j < 32; ++j) {
00167 test[j] = rc4DecryptByte(fState, &fx, &fy, test[j]);
00168 }
00169 }
00170 memcpy(buf, passwordPad, 32);
00171 memcpy(buf + 32, fileID->getCString(), fileID->getLength());
00172 md5(buf, 32 + fileID->getLength(), buf);
00173 ok = memcmp(test, buf, 16) == 0;
00174 } else {
00175 ok = gFalse;
00176 }
00177
00178 gfree(buf);
00179 return ok;
00180 }
00181
00182
00183
00184
00185
00186 static void rc4InitKey(Guchar *key, int keyLen, Guchar *state) {
00187 Guchar index1, index2;
00188 Guchar t;
00189 int i;
00190
00191 for (i = 0; i < 256; ++i)
00192 state[i] = i;
00193 index1 = index2 = 0;
00194 for (i = 0; i < 256; ++i) {
00195 index2 = (key[index1] + state[i] + index2) % 256;
00196 t = state[i];
00197 state[i] = state[index2];
00198 state[index2] = t;
00199 index1 = (index1 + 1) % keyLen;
00200 }
00201 }
00202
00203 static Guchar rc4DecryptByte(Guchar *state, Guchar *x, Guchar *y, Guchar c) {
00204 Guchar x1, y1, tx, ty;
00205
00206 x1 = *x = (*x + 1) % 256;
00207 y1 = *y = (state[*x] + *y) % 256;
00208 tx = state[x1];
00209 ty = state[y1];
00210 state[x1] = ty;
00211 state[y1] = tx;
00212 return c ^ state[(tx + ty) % 256];
00213 }
00214
00215
00216
00217
00218
00219
00220 static inline Gulong rotateLeft(Gulong x, int r) {
00221 x &= 0xffffffff;
00222 return ((x << r) | (x >> (32 - r))) & 0xffffffff;
00223 }
00224
00225 static inline Gulong md5Round1(Gulong a, Gulong b, Gulong c, Gulong d,
00226 Gulong Xk, Gulong s, Gulong Ti) {
00227 return b + rotateLeft((a + ((b & c) | (~b & d)) + Xk + Ti), s);
00228 }
00229
00230 static inline Gulong md5Round2(Gulong a, Gulong b, Gulong c, Gulong d,
00231 Gulong Xk, Gulong s, Gulong Ti) {
00232 return b + rotateLeft((a + ((b & d) | (c & ~d)) + Xk + Ti), s);
00233 }
00234
00235 static inline Gulong md5Round3(Gulong a, Gulong b, Gulong c, Gulong d,
00236 Gulong Xk, Gulong s, Gulong Ti) {
00237 return b + rotateLeft((a + (b ^ c ^ d) + Xk + Ti), s);
00238 }
00239
00240 static inline Gulong md5Round4(Gulong a, Gulong b, Gulong c, Gulong d,
00241 Gulong Xk, Gulong s, Gulong Ti) {
00242 return b + rotateLeft((a + (c ^ (b | ~d)) + Xk + Ti), s);
00243 }
00244
00245 static void md5(Guchar *msg, int msgLen, Guchar *digest) {
00246 Gulong x[16];
00247 Gulong a, b, c, d, aa, bb, cc, dd;
00248 int n64;
00249 int i, j, k;
00250
00251
00252
00253 n64 = (msgLen + 1 + 8 + 63) / 64;
00254
00255
00256 a = 0x67452301;
00257 b = 0xefcdab89;
00258 c = 0x98badcfe;
00259 d = 0x10325476;
00260
00261
00262 k = 0;
00263 for (i = 0; i < n64; ++i) {
00264
00265
00266 for (j = 0; j < 16 && k < msgLen - 3; ++j, k += 4)
00267 x[j] = (((((msg[k+3] << 8) + msg[k+2]) << 8) + msg[k+1]) << 8) + msg[k];
00268 if (i == n64 - 1) {
00269 if (k == msgLen - 3)
00270 x[j] = 0x80000000 + (((msg[k+2] << 8) + msg[k+1]) << 8) + msg[k];
00271 else if (k == msgLen - 2)
00272 x[j] = 0x800000 + (msg[k+1] << 8) + msg[k];
00273 else if (k == msgLen - 1)
00274 x[j] = 0x8000 + msg[k];
00275 else
00276 x[j] = 0x80;
00277 ++j;
00278 while (j < 16)
00279 x[j++] = 0;
00280 x[14] = msgLen << 3;
00281 }
00282
00283
00284 aa = a;
00285 bb = b;
00286 cc = c;
00287 dd = d;
00288
00289
00290 a = md5Round1(a, b, c, d, x[0], 7, 0xd76aa478);
00291 d = md5Round1(d, a, b, c, x[1], 12, 0xe8c7b756);
00292 c = md5Round1(c, d, a, b, x[2], 17, 0x242070db);
00293 b = md5Round1(b, c, d, a, x[3], 22, 0xc1bdceee);
00294 a = md5Round1(a, b, c, d, x[4], 7, 0xf57c0faf);
00295 d = md5Round1(d, a, b, c, x[5], 12, 0x4787c62a);
00296 c = md5Round1(c, d, a, b, x[6], 17, 0xa8304613);
00297 b = md5Round1(b, c, d, a, x[7], 22, 0xfd469501);
00298 a = md5Round1(a, b, c, d, x[8], 7, 0x698098d8);
00299 d = md5Round1(d, a, b, c, x[9], 12, 0x8b44f7af);
00300 c = md5Round1(c, d, a, b, x[10], 17, 0xffff5bb1);
00301 b = md5Round1(b, c, d, a, x[11], 22, 0x895cd7be);
00302 a = md5Round1(a, b, c, d, x[12], 7, 0x6b901122);
00303 d = md5Round1(d, a, b, c, x[13], 12, 0xfd987193);
00304 c = md5Round1(c, d, a, b, x[14], 17, 0xa679438e);
00305 b = md5Round1(b, c, d, a, x[15], 22, 0x49b40821);
00306
00307
00308 a = md5Round2(a, b, c, d, x[1], 5, 0xf61e2562);
00309 d = md5Round2(d, a, b, c, x[6], 9, 0xc040b340);
00310 c = md5Round2(c, d, a, b, x[11], 14, 0x265e5a51);
00311 b = md5Round2(b, c, d, a, x[0], 20, 0xe9b6c7aa);
00312 a = md5Round2(a, b, c, d, x[5], 5, 0xd62f105d);
00313 d = md5Round2(d, a, b, c, x[10], 9, 0x02441453);
00314 c = md5Round2(c, d, a, b, x[15], 14, 0xd8a1e681);
00315 b = md5Round2(b, c, d, a, x[4], 20, 0xe7d3fbc8);
00316 a = md5Round2(a, b, c, d, x[9], 5, 0x21e1cde6);
00317 d = md5Round2(d, a, b, c, x[14], 9, 0xc33707d6);
00318 c = md5Round2(c, d, a, b, x[3], 14, 0xf4d50d87);
00319 b = md5Round2(b, c, d, a, x[8], 20, 0x455a14ed);
00320 a = md5Round2(a, b, c, d, x[13], 5, 0xa9e3e905);
00321 d = md5Round2(d, a, b, c, x[2], 9, 0xfcefa3f8);
00322 c = md5Round2(c, d, a, b, x[7], 14, 0x676f02d9);
00323 b = md5Round2(b, c, d, a, x[12], 20, 0x8d2a4c8a);
00324
00325
00326 a = md5Round3(a, b, c, d, x[5], 4, 0xfffa3942);
00327 d = md5Round3(d, a, b, c, x[8], 11, 0x8771f681);
00328 c = md5Round3(c, d, a, b, x[11], 16, 0x6d9d6122);
00329 b = md5Round3(b, c, d, a, x[14], 23, 0xfde5380c);
00330 a = md5Round3(a, b, c, d, x[1], 4, 0xa4beea44);
00331 d = md5Round3(d, a, b, c, x[4], 11, 0x4bdecfa9);
00332 c = md5Round3(c, d, a, b, x[7], 16, 0xf6bb4b60);
00333 b = md5Round3(b, c, d, a, x[10], 23, 0xbebfbc70);
00334 a = md5Round3(a, b, c, d, x[13], 4, 0x289b7ec6);
00335 d = md5Round3(d, a, b, c, x[0], 11, 0xeaa127fa);
00336 c = md5Round3(c, d, a, b, x[3], 16, 0xd4ef3085);
00337 b = md5Round3(b, c, d, a, x[6], 23, 0x04881d05);
00338 a = md5Round3(a, b, c, d, x[9], 4, 0xd9d4d039);
00339 d = md5Round3(d, a, b, c, x[12], 11, 0xe6db99e5);
00340 c = md5Round3(c, d, a, b, x[15], 16, 0x1fa27cf8);
00341 b = md5Round3(b, c, d, a, x[2], 23, 0xc4ac5665);
00342
00343
00344 a = md5Round4(a, b, c, d, x[0], 6, 0xf4292244);
00345 d = md5Round4(d, a, b, c, x[7], 10, 0x432aff97);
00346 c = md5Round4(c, d, a, b, x[14], 15, 0xab9423a7);
00347 b = md5Round4(b, c, d, a, x[5], 21, 0xfc93a039);
00348 a = md5Round4(a, b, c, d, x[12], 6, 0x655b59c3);
00349 d = md5Round4(d, a, b, c, x[3], 10, 0x8f0ccc92);
00350 c = md5Round4(c, d, a, b, x[10], 15, 0xffeff47d);
00351 b = md5Round4(b, c, d, a, x[1], 21, 0x85845dd1);
00352 a = md5Round4(a, b, c, d, x[8], 6, 0x6fa87e4f);
00353 d = md5Round4(d, a, b, c, x[15], 10, 0xfe2ce6e0);
00354 c = md5Round4(c, d, a, b, x[6], 15, 0xa3014314);
00355 b = md5Round4(b, c, d, a, x[13], 21, 0x4e0811a1);
00356 a = md5Round4(a, b, c, d, x[4], 6, 0xf7537e82);
00357 d = md5Round4(d, a, b, c, x[11], 10, 0xbd3af235);
00358 c = md5Round4(c, d, a, b, x[2], 15, 0x2ad7d2bb);
00359 b = md5Round4(b, c, d, a, x[9], 21, 0xeb86d391);
00360
00361
00362 a += aa;
00363 b += bb;
00364 c += cc;
00365 d += dd;
00366 }
00367
00368
00369 digest[0] = a & 0xff;
00370 digest[1] = (a >>= 8) & 0xff;
00371 digest[2] = (a >>= 8) & 0xff;
00372 digest[3] = (a >>= 8) & 0xff;
00373 digest[4] = b & 0xff;
00374 digest[5] = (b >>= 8) & 0xff;
00375 digest[6] = (b >>= 8) & 0xff;
00376 digest[7] = (b >>= 8) & 0xff;
00377 digest[8] = c & 0xff;
00378 digest[9] = (c >>= 8) & 0xff;
00379 digest[10] = (c >>= 8) & 0xff;
00380 digest[11] = (c >>= 8) & 0xff;
00381 digest[12] = d & 0xff;
00382 digest[13] = (d >>= 8) & 0xff;
00383 digest[14] = (d >>= 8) & 0xff;
00384 digest[15] = (d >>= 8) & 0xff;
00385 }