1 //========================================================================
5 // Copyright 1996-2003 Glyph & Cog, LLC
7 //========================================================================
11 #ifdef USE_GCC_PRAGMAS
12 #pragma implementation
19 static void rc4InitKey(Guchar
*key
, int keyLen
, Guchar
*state
);
20 static Guchar
rc4DecryptByte(Guchar
*state
, Guchar
*x
, Guchar
*y
, Guchar c
);
21 static void aesKeyExpansion(DecryptAESState
*s
,
22 Guchar
*objKey
, int objKeyLen
);
23 static void aesDecryptBlock(DecryptAESState
*s
, Guchar
*in
, GBool last
);
24 static void md5(Guchar
*msg
, int msgLen
, Guchar
*digest
);
26 static Guchar passwordPad
[32] = {
27 0x28, 0xbf, 0x4e, 0x5e, 0x4e, 0x75, 0x8a, 0x41,
28 0x64, 0x00, 0x4e, 0x56, 0xff, 0xfa, 0x01, 0x08,
29 0x2e, 0x2e, 0x00, 0xb6, 0xd0, 0x68, 0x3e, 0x80,
30 0x2f, 0x0c, 0xa9, 0xfe, 0x64, 0x53, 0x69, 0x7a
33 //------------------------------------------------------------------------
35 //------------------------------------------------------------------------
37 GBool
Decrypt::makeFileKey(int encVersion
, int encRevision
, int keyLength
,
38 GString
*ownerKey
, GString
*userKey
,
39 int permissions
, GString
*fileID
,
40 GString
*ownerPassword
, GString
*userPassword
,
41 Guchar
*fileKey
, GBool encryptMetadata
,
42 GBool
*ownerPasswordOk
) {
43 Guchar test
[32], test2
[32];
44 GString
*userPassword2
;
50 // try using the supplied owner password to generate the user password
51 *ownerPasswordOk
= gFalse
;
53 len
= ownerPassword
->getLength();
55 memcpy(test
, ownerPassword
->getCString(), len
);
56 memcpy(test
+ len
, passwordPad
, 32 - len
);
58 memcpy(test
, ownerPassword
->getCString(), 32);
61 if (encRevision
== 3) {
62 for (i
= 0; i
< 50; ++i
) {
66 if (encRevision
== 2) {
67 rc4InitKey(test
, keyLength
, fState
);
69 for (i
= 0; i
< 32; ++i
) {
70 test2
[i
] = rc4DecryptByte(fState
, &fx
, &fy
, ownerKey
->getChar(i
));
73 memcpy(test2
, ownerKey
->getCString(), 32);
74 for (i
= 19; i
>= 0; --i
) {
75 for (j
= 0; j
< keyLength
; ++j
) {
76 tmpKey
[j
] = test
[j
] ^ i
;
78 rc4InitKey(tmpKey
, keyLength
, fState
);
80 for (j
= 0; j
< 32; ++j
) {
81 test2
[j
] = rc4DecryptByte(fState
, &fx
, &fy
, test2
[j
]);
85 userPassword2
= new GString((char *)test2
, 32);
86 if (makeFileKey2(encVersion
, encRevision
, keyLength
, ownerKey
, userKey
,
87 permissions
, fileID
, userPassword2
, fileKey
,
89 *ownerPasswordOk
= gTrue
;
96 // try using the supplied user password
97 return makeFileKey2(encVersion
, encRevision
, keyLength
, ownerKey
, userKey
,
98 permissions
, fileID
, userPassword
, fileKey
,
102 GBool
Decrypt::makeFileKey2(int encVersion
, int encRevision
, int keyLength
,
103 GString
*ownerKey
, GString
*userKey
,
104 int permissions
, GString
*fileID
,
105 GString
*userPassword
, Guchar
*fileKey
,
106 GBool encryptMetadata
) {
116 buf
= (Guchar
*)gmalloc(72 + fileID
->getLength());
118 len
= userPassword
->getLength();
120 memcpy(buf
, userPassword
->getCString(), len
);
121 memcpy(buf
+ len
, passwordPad
, 32 - len
);
123 memcpy(buf
, userPassword
->getCString(), 32);
126 memcpy(buf
, passwordPad
, 32);
128 memcpy(buf
+ 32, ownerKey
->getCString(), 32);
129 buf
[64] = permissions
& 0xff;
130 buf
[65] = (permissions
>> 8) & 0xff;
131 buf
[66] = (permissions
>> 16) & 0xff;
132 buf
[67] = (permissions
>> 24) & 0xff;
133 memcpy(buf
+ 68, fileID
->getCString(), fileID
->getLength());
134 len
= 68 + fileID
->getLength();
135 if (!encryptMetadata
) {
141 md5(buf
, len
, fileKey
);
142 if (encRevision
== 3) {
143 for (i
= 0; i
< 50; ++i
) {
144 md5(fileKey
, keyLength
, fileKey
);
148 // test user password
149 if (encRevision
== 2) {
150 rc4InitKey(fileKey
, keyLength
, fState
);
152 for (i
= 0; i
< 32; ++i
) {
153 test
[i
] = rc4DecryptByte(fState
, &fx
, &fy
, userKey
->getChar(i
));
155 ok
= memcmp(test
, passwordPad
, 32) == 0;
156 } else if (encRevision
== 3) {
157 memcpy(test
, userKey
->getCString(), 32);
158 for (i
= 19; i
>= 0; --i
) {
159 for (j
= 0; j
< keyLength
; ++j
) {
160 tmpKey
[j
] = fileKey
[j
] ^ i
;
162 rc4InitKey(tmpKey
, keyLength
, fState
);
164 for (j
= 0; j
< 32; ++j
) {
165 test
[j
] = rc4DecryptByte(fState
, &fx
, &fy
, test
[j
]);
168 memcpy(buf
, passwordPad
, 32);
169 memcpy(buf
+ 32, fileID
->getCString(), fileID
->getLength());
170 md5(buf
, 32 + fileID
->getLength(), buf
);
171 ok
= memcmp(test
, buf
, 16) == 0;
180 //------------------------------------------------------------------------
182 //------------------------------------------------------------------------
184 DecryptStream::DecryptStream(Stream
*strA
, Guchar
*fileKey
,
185 CryptAlgorithm algoA
, int keyLength
,
186 int objNum
, int objGen
):
193 // construct xObject key
194 for (i
= 0; i
< keyLength
; ++i
) {
195 objKey
[i
] = fileKey
[i
];
197 objKey
[keyLength
] = objNum
& 0xff;
198 objKey
[keyLength
+ 1] = (objNum
>> 8) & 0xff;
199 objKey
[keyLength
+ 2] = (objNum
>> 16) & 0xff;
200 objKey
[keyLength
+ 3] = objGen
& 0xff;
201 objKey
[keyLength
+ 4] = (objGen
>> 8) & 0xff;
202 if (algo
== cryptAES
) {
203 objKey
[keyLength
+ 5] = 0x73; // 's'
204 objKey
[keyLength
+ 6] = 0x41; // 'A'
205 objKey
[keyLength
+ 7] = 0x6c; // 'l'
206 objKey
[keyLength
+ 8] = 0x54; // 'T'
211 md5(objKey
, n
, objKey
);
212 if ((objKeyLength
= keyLength
+ 5) > 16) {
217 DecryptStream::~DecryptStream() {
221 void DecryptStream::reset() {
227 state
.rc4
.x
= state
.rc4
.y
= 0;
228 rc4InitKey(objKey
, objKeyLength
, state
.rc4
.state
);
232 aesKeyExpansion(&state
.aes
, objKey
, objKeyLength
);
233 for (i
= 0; i
< 16; ++i
) {
234 state
.aes
.cbc
[i
] = str
->getChar();
236 state
.aes
.bufIdx
= 16;
241 int DecryptStream::getChar() {
245 c
= EOF
; // make gcc happy
248 if (state
.rc4
.buf
== EOF
) {
251 state
.rc4
.buf
= rc4DecryptByte(state
.rc4
.state
, &state
.rc4
.x
,
252 &state
.rc4
.y
, (Guchar
)c
);
259 if (state
.aes
.bufIdx
== 16) {
260 for (i
= 0; i
< 16; ++i
) {
261 if ((c
= str
->getChar()) == EOF
) {
266 aesDecryptBlock(&state
.aes
, in
, str
->lookChar() == EOF
);
268 if (state
.aes
.bufIdx
== 16) {
271 c
= state
.aes
.buf
[state
.aes
.bufIdx
++];
278 int DecryptStream::lookChar() {
282 c
= EOF
; // make gcc happy
285 if (state
.rc4
.buf
== EOF
) {
288 state
.rc4
.buf
= rc4DecryptByte(state
.rc4
.state
, &state
.rc4
.x
,
289 &state
.rc4
.y
, (Guchar
)c
);
295 if (state
.aes
.bufIdx
== 16) {
296 for (i
= 0; i
< 16; ++i
) {
297 if ((c
= str
->getChar()) == EOF
) {
302 aesDecryptBlock(&state
.aes
, in
, str
->lookChar() == EOF
);
304 if (state
.aes
.bufIdx
== 16) {
307 c
= state
.aes
.buf
[state
.aes
.bufIdx
];
314 GBool
DecryptStream::isBinary(GBool last
) {
315 return str
->isBinary(last
);
318 //------------------------------------------------------------------------
319 // RC4-compatible decryption
320 //------------------------------------------------------------------------
322 static void rc4InitKey(Guchar
*key
, int keyLen
, Guchar
*state
) {
323 Guchar index1
, index2
;
327 for (i
= 0; i
< 256; ++i
)
330 for (i
= 0; i
< 256; ++i
) {
331 index2
= (key
[index1
] + state
[i
] + index2
) % 256;
333 state
[i
] = state
[index2
];
335 index1
= (index1
+ 1) % keyLen
;
339 static Guchar
rc4DecryptByte(Guchar
*state
, Guchar
*x
, Guchar
*y
, Guchar c
) {
340 Guchar x1
, y1
, tx
, ty
;
342 x1
= *x
= (*x
+ 1) % 256;
343 y1
= *y
= (state
[*x
] + *y
) % 256;
348 return c
^ state
[(tx
+ ty
) % 256];
351 //------------------------------------------------------------------------
353 //------------------------------------------------------------------------
355 static Guchar sbox
[256] = {
356 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
357 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
358 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
359 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
360 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
361 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
362 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
363 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
364 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
365 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
366 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
367 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
368 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
369 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
370 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
371 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16
374 static Guchar invSbox
[256] = {
375 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb,
376 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb,
377 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
378 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25,
379 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92,
380 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,
381 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06,
382 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b,
383 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,
384 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e,
385 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b,
386 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
387 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f,
388 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef,
389 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
390 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d
393 static Guint rcon
[11] = {
394 0x00000000, // unused
407 static inline Guint
subWord(Guint x
) {
408 return (sbox
[x
>> 24] << 24)
409 | (sbox
[(x
>> 16) & 0xff] << 16)
410 | (sbox
[(x
>> 8) & 0xff] << 8)
414 static inline Guint
rotWord(Guint x
) {
415 return ((x
<< 8) & 0xffffffff) | (x
>> 24);
418 static inline void invSubBytes(Guchar
*state
) {
421 for (i
= 0; i
< 16; ++i
) {
422 state
[i
] = invSbox
[state
[i
]];
426 static inline void invShiftRows(Guchar
*state
) {
436 state
[8] = state
[10];
439 state
[9] = state
[11];
443 state
[12] = state
[13];
444 state
[13] = state
[14];
445 state
[14] = state
[15];
450 static inline Guchar
mul09(Guchar s
) {
453 s2
= (s
& 0x80) ? ((s
<< 1) ^ 0x1b) : (s
<< 1);
454 s4
= (s2
& 0x80) ? ((s2
<< 1) ^ 0x1b) : (s2
<< 1);
455 s8
= (s4
& 0x80) ? ((s4
<< 1) ^ 0x1b) : (s4
<< 1);
460 static inline Guchar
mul0b(Guchar s
) {
463 s2
= (s
& 0x80) ? ((s
<< 1) ^ 0x1b) : (s
<< 1);
464 s4
= (s2
& 0x80) ? ((s2
<< 1) ^ 0x1b) : (s2
<< 1);
465 s8
= (s4
& 0x80) ? ((s4
<< 1) ^ 0x1b) : (s4
<< 1);
470 static inline Guchar
mul0d(Guchar s
) {
473 s2
= (s
& 0x80) ? ((s
<< 1) ^ 0x1b) : (s
<< 1);
474 s4
= (s2
& 0x80) ? ((s2
<< 1) ^ 0x1b) : (s2
<< 1);
475 s8
= (s4
& 0x80) ? ((s4
<< 1) ^ 0x1b) : (s4
<< 1);
480 static inline Guchar
mul0e(Guchar s
) {
483 s2
= (s
& 0x80) ? ((s
<< 1) ^ 0x1b) : (s
<< 1);
484 s4
= (s2
& 0x80) ? ((s2
<< 1) ^ 0x1b) : (s2
<< 1);
485 s8
= (s4
& 0x80) ? ((s4
<< 1) ^ 0x1b) : (s4
<< 1);
489 static inline void invMixColumns(Guchar
*state
) {
491 Guchar s0
, s1
, s2
, s3
;
493 for (c
= 0; c
< 4; ++c
) {
498 state
[c
] = mul0e(s0
) ^ mul0b(s1
) ^ mul0d(s2
) ^ mul09(s3
);
499 state
[4+c
] = mul09(s0
) ^ mul0e(s1
) ^ mul0b(s2
) ^ mul0d(s3
);
500 state
[8+c
] = mul0d(s0
) ^ mul09(s1
) ^ mul0e(s2
) ^ mul0b(s3
);
501 state
[12+c
] = mul0b(s0
) ^ mul0d(s1
) ^ mul09(s2
) ^ mul0e(s3
);
505 static inline void invMixColumnsW(Guint
*w
) {
507 Guchar s0
, s1
, s2
, s3
;
509 for (c
= 0; c
< 4; ++c
) {
514 w
[c
] = ((mul0e(s0
) ^ mul0b(s1
) ^ mul0d(s2
) ^ mul09(s3
)) << 24)
515 | ((mul09(s0
) ^ mul0e(s1
) ^ mul0b(s2
) ^ mul0d(s3
)) << 16)
516 | ((mul0d(s0
) ^ mul09(s1
) ^ mul0e(s2
) ^ mul0b(s3
)) << 8)
517 | (mul0b(s0
) ^ mul0d(s1
) ^ mul09(s2
) ^ mul0e(s3
));
521 static inline void addRoundKey(Guchar
*state
, Guint
*w
) {
524 for (c
= 0; c
< 4; ++c
) {
525 state
[c
] ^= w
[c
] >> 24;
526 state
[4+c
] ^= w
[c
] >> 16;
527 state
[8+c
] ^= w
[c
] >> 8;
532 static void aesKeyExpansion(DecryptAESState
*s
,
533 Guchar
*objKey
, int objKeyLen
) {
537 //~ this assumes objKeyLen == 16
539 for (i
= 0; i
< 4; ++i
) {
540 s
->w
[i
] = (objKey
[4*i
] << 24) + (objKey
[4*i
+1] << 16) +
541 (objKey
[4*i
+2] << 8) + objKey
[4*i
+3];
543 for (i
= 4; i
< 44; ++i
) {
546 temp
= subWord(rotWord(temp
)) ^ rcon
[i
/4];
548 s
->w
[i
] = s
->w
[i
-4] ^ temp
;
550 for (round
= 1; round
<= 9; ++round
) {
551 invMixColumnsW(&s
->w
[round
* 4]);
555 static void aesDecryptBlock(DecryptAESState
*s
, Guchar
*in
, GBool last
) {
559 for (c
= 0; c
< 4; ++c
) {
560 s
->state
[c
] = in
[4*c
];
561 s
->state
[4+c
] = in
[4*c
+1];
562 s
->state
[8+c
] = in
[4*c
+2];
563 s
->state
[12+c
] = in
[4*c
+3];
567 addRoundKey(s
->state
, &s
->w
[10 * 4]);
570 for (round
= 9; round
>= 1; --round
) {
571 invSubBytes(s
->state
);
572 invShiftRows(s
->state
);
573 invMixColumns(s
->state
);
574 addRoundKey(s
->state
, &s
->w
[round
* 4]);
578 invSubBytes(s
->state
);
579 invShiftRows(s
->state
);
580 addRoundKey(s
->state
, &s
->w
[0]);
583 for (c
= 0; c
< 4; ++c
) {
584 s
->buf
[4*c
] = s
->state
[c
] ^ s
->cbc
[4*c
];
585 s
->buf
[4*c
+1] = s
->state
[4+c
] ^ s
->cbc
[4*c
+1];
586 s
->buf
[4*c
+2] = s
->state
[8+c
] ^ s
->cbc
[4*c
+2];
587 s
->buf
[4*c
+3] = s
->state
[12+c
] ^ s
->cbc
[4*c
+3];
590 // save the input block for the next CBC
591 for (i
= 0; i
< 16; ++i
) {
599 for (i
= 15; i
>= n
; --i
) {
600 s
->buf
[i
] = s
->buf
[i
-n
];
606 //------------------------------------------------------------------------
607 // MD5 message digest
608 //------------------------------------------------------------------------
610 // this works around a bug in older Sun compilers
611 static inline Gulong
rotateLeft(Gulong x
, int r
) {
613 return ((x
<< r
) | (x
>> (32 - r
))) & 0xffffffff;
616 static inline Gulong
md5Round1(Gulong a
, Gulong b
, Gulong c
, Gulong d
,
617 Gulong Xk
, Gulong s
, Gulong Ti
) {
618 return b
+ rotateLeft((a
+ ((b
& c
) | (~b
& d
)) + Xk
+ Ti
), s
);
621 static inline Gulong
md5Round2(Gulong a
, Gulong b
, Gulong c
, Gulong d
,
622 Gulong Xk
, Gulong s
, Gulong Ti
) {
623 return b
+ rotateLeft((a
+ ((b
& d
) | (c
& ~d
)) + Xk
+ Ti
), s
);
626 static inline Gulong
md5Round3(Gulong a
, Gulong b
, Gulong c
, Gulong d
,
627 Gulong Xk
, Gulong s
, Gulong Ti
) {
628 return b
+ rotateLeft((a
+ (b
^ c
^ d
) + Xk
+ Ti
), s
);
631 static inline Gulong
md5Round4(Gulong a
, Gulong b
, Gulong c
, Gulong d
,
632 Gulong Xk
, Gulong s
, Gulong Ti
) {
633 return b
+ rotateLeft((a
+ (c
^ (b
| ~d
)) + Xk
+ Ti
), s
);
636 static void md5(Guchar
*msg
, int msgLen
, Guchar
*digest
) {
638 Gulong a
, b
, c
, d
, aa
, bb
, cc
, dd
;
642 // compute number of 64-byte blocks
643 // (length + pad byte (0x80) + 8 bytes for length)
644 n64
= (msgLen
+ 1 + 8 + 63) / 64;
646 // initialize a, b, c, d
652 // loop through blocks
654 for (i
= 0; i
< n64
; ++i
) {
656 // grab a 64-byte block
657 for (j
= 0; j
< 16 && k
< msgLen
- 3; ++j
, k
+= 4)
658 x
[j
] = (((((msg
[k
+3] << 8) + msg
[k
+2]) << 8) + msg
[k
+1]) << 8) + msg
[k
];
661 x
[j
] = 0x80000000 + (((msg
[k
+2] << 8) + msg
[k
+1]) << 8) + msg
[k
];
662 else if (k
== msgLen
- 2)
663 x
[j
] = 0x800000 + (msg
[k
+1] << 8) + msg
[k
];
664 else if (k
== msgLen
- 1)
665 x
[j
] = 0x8000 + msg
[k
];
681 a
= md5Round1(a
, b
, c
, d
, x
[0], 7, 0xd76aa478);
682 d
= md5Round1(d
, a
, b
, c
, x
[1], 12, 0xe8c7b756);
683 c
= md5Round1(c
, d
, a
, b
, x
[2], 17, 0x242070db);
684 b
= md5Round1(b
, c
, d
, a
, x
[3], 22, 0xc1bdceee);
685 a
= md5Round1(a
, b
, c
, d
, x
[4], 7, 0xf57c0faf);
686 d
= md5Round1(d
, a
, b
, c
, x
[5], 12, 0x4787c62a);
687 c
= md5Round1(c
, d
, a
, b
, x
[6], 17, 0xa8304613);
688 b
= md5Round1(b
, c
, d
, a
, x
[7], 22, 0xfd469501);
689 a
= md5Round1(a
, b
, c
, d
, x
[8], 7, 0x698098d8);
690 d
= md5Round1(d
, a
, b
, c
, x
[9], 12, 0x8b44f7af);
691 c
= md5Round1(c
, d
, a
, b
, x
[10], 17, 0xffff5bb1);
692 b
= md5Round1(b
, c
, d
, a
, x
[11], 22, 0x895cd7be);
693 a
= md5Round1(a
, b
, c
, d
, x
[12], 7, 0x6b901122);
694 d
= md5Round1(d
, a
, b
, c
, x
[13], 12, 0xfd987193);
695 c
= md5Round1(c
, d
, a
, b
, x
[14], 17, 0xa679438e);
696 b
= md5Round1(b
, c
, d
, a
, x
[15], 22, 0x49b40821);
699 a
= md5Round2(a
, b
, c
, d
, x
[1], 5, 0xf61e2562);
700 d
= md5Round2(d
, a
, b
, c
, x
[6], 9, 0xc040b340);
701 c
= md5Round2(c
, d
, a
, b
, x
[11], 14, 0x265e5a51);
702 b
= md5Round2(b
, c
, d
, a
, x
[0], 20, 0xe9b6c7aa);
703 a
= md5Round2(a
, b
, c
, d
, x
[5], 5, 0xd62f105d);
704 d
= md5Round2(d
, a
, b
, c
, x
[10], 9, 0x02441453);
705 c
= md5Round2(c
, d
, a
, b
, x
[15], 14, 0xd8a1e681);
706 b
= md5Round2(b
, c
, d
, a
, x
[4], 20, 0xe7d3fbc8);
707 a
= md5Round2(a
, b
, c
, d
, x
[9], 5, 0x21e1cde6);
708 d
= md5Round2(d
, a
, b
, c
, x
[14], 9, 0xc33707d6);
709 c
= md5Round2(c
, d
, a
, b
, x
[3], 14, 0xf4d50d87);
710 b
= md5Round2(b
, c
, d
, a
, x
[8], 20, 0x455a14ed);
711 a
= md5Round2(a
, b
, c
, d
, x
[13], 5, 0xa9e3e905);
712 d
= md5Round2(d
, a
, b
, c
, x
[2], 9, 0xfcefa3f8);
713 c
= md5Round2(c
, d
, a
, b
, x
[7], 14, 0x676f02d9);
714 b
= md5Round2(b
, c
, d
, a
, x
[12], 20, 0x8d2a4c8a);
717 a
= md5Round3(a
, b
, c
, d
, x
[5], 4, 0xfffa3942);
718 d
= md5Round3(d
, a
, b
, c
, x
[8], 11, 0x8771f681);
719 c
= md5Round3(c
, d
, a
, b
, x
[11], 16, 0x6d9d6122);
720 b
= md5Round3(b
, c
, d
, a
, x
[14], 23, 0xfde5380c);
721 a
= md5Round3(a
, b
, c
, d
, x
[1], 4, 0xa4beea44);
722 d
= md5Round3(d
, a
, b
, c
, x
[4], 11, 0x4bdecfa9);
723 c
= md5Round3(c
, d
, a
, b
, x
[7], 16, 0xf6bb4b60);
724 b
= md5Round3(b
, c
, d
, a
, x
[10], 23, 0xbebfbc70);
725 a
= md5Round3(a
, b
, c
, d
, x
[13], 4, 0x289b7ec6);
726 d
= md5Round3(d
, a
, b
, c
, x
[0], 11, 0xeaa127fa);
727 c
= md5Round3(c
, d
, a
, b
, x
[3], 16, 0xd4ef3085);
728 b
= md5Round3(b
, c
, d
, a
, x
[6], 23, 0x04881d05);
729 a
= md5Round3(a
, b
, c
, d
, x
[9], 4, 0xd9d4d039);
730 d
= md5Round3(d
, a
, b
, c
, x
[12], 11, 0xe6db99e5);
731 c
= md5Round3(c
, d
, a
, b
, x
[15], 16, 0x1fa27cf8);
732 b
= md5Round3(b
, c
, d
, a
, x
[2], 23, 0xc4ac5665);
735 a
= md5Round4(a
, b
, c
, d
, x
[0], 6, 0xf4292244);
736 d
= md5Round4(d
, a
, b
, c
, x
[7], 10, 0x432aff97);
737 c
= md5Round4(c
, d
, a
, b
, x
[14], 15, 0xab9423a7);
738 b
= md5Round4(b
, c
, d
, a
, x
[5], 21, 0xfc93a039);
739 a
= md5Round4(a
, b
, c
, d
, x
[12], 6, 0x655b59c3);
740 d
= md5Round4(d
, a
, b
, c
, x
[3], 10, 0x8f0ccc92);
741 c
= md5Round4(c
, d
, a
, b
, x
[10], 15, 0xffeff47d);
742 b
= md5Round4(b
, c
, d
, a
, x
[1], 21, 0x85845dd1);
743 a
= md5Round4(a
, b
, c
, d
, x
[8], 6, 0x6fa87e4f);
744 d
= md5Round4(d
, a
, b
, c
, x
[15], 10, 0xfe2ce6e0);
745 c
= md5Round4(c
, d
, a
, b
, x
[6], 15, 0xa3014314);
746 b
= md5Round4(b
, c
, d
, a
, x
[13], 21, 0x4e0811a1);
747 a
= md5Round4(a
, b
, c
, d
, x
[4], 6, 0xf7537e82);
748 d
= md5Round4(d
, a
, b
, c
, x
[11], 10, 0xbd3af235);
749 c
= md5Round4(c
, d
, a
, b
, x
[2], 15, 0x2ad7d2bb);
750 b
= md5Round4(b
, c
, d
, a
, x
[9], 21, 0xeb86d391);
752 // increment a, b, c, d
759 // break digest into bytes
760 digest
[0] = (Guchar
)(a
& 0xff);
761 digest
[1] = (Guchar
)((a
>>= 8) & 0xff);
762 digest
[2] = (Guchar
)((a
>>= 8) & 0xff);
763 digest
[3] = (Guchar
)((a
>>= 8) & 0xff);
764 digest
[4] = (Guchar
)(b
& 0xff);
765 digest
[5] = (Guchar
)((b
>>= 8) & 0xff);
766 digest
[6] = (Guchar
)((b
>>= 8) & 0xff);
767 digest
[7] = (Guchar
)((b
>>= 8) & 0xff);
768 digest
[8] = (Guchar
)(c
& 0xff);
769 digest
[9] = (Guchar
)((c
>>= 8) & 0xff);
770 digest
[10] = (Guchar
)((c
>>= 8) & 0xff);
771 digest
[11] = (Guchar
)((c
>>= 8) & 0xff);
772 digest
[12] = (Guchar
)(d
& 0xff);
773 digest
[13] = (Guchar
)((d
>>= 8) & 0xff);
774 digest
[14] = (Guchar
)((d
>>= 8) & 0xff);
775 digest
[15] = (Guchar
)((d
>>= 8) & 0xff);