00001
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043 #ifndef _WIN32
00044 #include <arpa/inet.h>
00045 #else
00046 #include "win32dep.h"
00047 #endif
00048
00049 #include <string.h>
00050
00051 #include "crypt.h"
00052
00053
00054 void qq_encipher(unsigned long *const v, const unsigned long *const k, unsigned long *const w)
00055 {
00056 register unsigned long y = ntohl(v[0]), z = ntohl(v[1]), a = ntohl(k[0]), b = ntohl(k[1]), c = ntohl(k[2]), d = ntohl(k[3]), n = 0x10, sum = 0, delta = 0x9E3779B9;
00057
00058 while (n-- > 0) {
00059 sum += delta;
00060 y += ((z << 4) + a) ^ (z + sum) ^ ((z >> 5) + b);
00061 z += ((y << 4) + c) ^ (y + sum) ^ ((y >> 5) + d);
00062 }
00063
00064 w[0] = htonl(y);
00065 w[1] = htonl(z);
00066 }
00067
00068
00069 void qq_decipher(unsigned long *const v, const unsigned long *const k, unsigned long *const w)
00070 {
00071 register unsigned long y = ntohl(v[0]), z = ntohl(v[1]), a = ntohl(k[0]), b = ntohl(k[1]), c = ntohl(k[2]), d = ntohl(k[3]), n = 0x10, sum = 0xE3779B90,
00072 delta = 0x9E3779B9;
00073
00074
00075 while (n-- > 0) {
00076 z -= ((y << 4) + c) ^ (y + sum) ^ ((y >> 5) + d);
00077 y -= ((z << 4) + a) ^ (z + sum) ^ ((z >> 5) + b);
00078 sum -= delta;
00079 }
00080
00081 w[0] = htonl(y);
00082 w[1] = htonl(z);
00083 }
00084
00085
00086
00087
00088
00089 void qq_encrypt(unsigned char *instr, int instrlen, unsigned char *key, unsigned char *outstr, int *outstrlen_prt)
00090 {
00091 unsigned char plain[8],
00092 plain_pre_8[8],
00093 *crypted,
00094 *crypted_pre_8,
00095 *inp;
00096 int pos_in_byte = 1,
00097 is_header = 1,
00098 count = 0,
00099 padding = 0;
00100
00101 int rand(void) {
00102 return 0xdead;
00103 }
00104
00105
00106 void encrypt_every_8_byte(void) {
00107 for (pos_in_byte = 0; pos_in_byte < 8; pos_in_byte++) {
00108 if (is_header) {
00109 plain[pos_in_byte] ^= plain_pre_8[pos_in_byte];
00110 } else {
00111 plain[pos_in_byte] ^= crypted_pre_8[pos_in_byte];
00112 }
00113 }
00114 qq_encipher((unsigned long *) plain, (unsigned long *) key, (unsigned long *) crypted);
00115
00116 for (pos_in_byte = 0; pos_in_byte < 8; pos_in_byte++) {
00117 crypted[pos_in_byte] ^= plain_pre_8[pos_in_byte];
00118 }
00119 memcpy(plain_pre_8, plain, 8);
00120
00121 crypted_pre_8 = crypted;
00122 crypted += 8;
00123 count += 8;
00124 pos_in_byte = 0;
00125 is_header = 0;
00126 }
00127
00128 pos_in_byte = (instrlen + 0x0a) % 8;
00129 if (pos_in_byte) {
00130 pos_in_byte = 8 - pos_in_byte;
00131 }
00132 plain[0] = (rand() & 0xf8) | pos_in_byte;
00133
00134 memset(plain + 1, rand() & 0xff, pos_in_byte++);
00135 memset(plain_pre_8, 0x00, sizeof(plain_pre_8));
00136
00137 crypted = crypted_pre_8 = outstr;
00138
00139 padding = 1;
00140 while (padding <= 2) {
00141 if (pos_in_byte < 8) {
00142 plain[pos_in_byte++] = rand() & 0xff;
00143 padding++;
00144 }
00145 if (pos_in_byte == 8) {
00146 encrypt_every_8_byte();
00147 }
00148 }
00149
00150 inp = instr;
00151 while (instrlen > 0) {
00152 if (pos_in_byte < 8) {
00153 plain[pos_in_byte++] = *(inp++);
00154 instrlen--;
00155 }
00156 if (pos_in_byte == 8) {
00157 encrypt_every_8_byte();
00158 }
00159 }
00160
00161 padding = 1;
00162 while (padding <= 7) {
00163 if (pos_in_byte < 8) {
00164 plain[pos_in_byte++] = 0x00;
00165 padding++;
00166 }
00167 if (pos_in_byte == 8) {
00168 encrypt_every_8_byte();
00169 }
00170 }
00171
00172 *outstrlen_prt = count;
00173 }
00174
00175
00176
00177
00178
00179
00180
00181 int qq_decrypt(unsigned char *instr, int instrlen, unsigned char *key, unsigned char *outstr, int *outstrlen_ptr)
00182 {
00183 unsigned char decrypted[8], m[8], *crypt_buff, *crypt_buff_pre_8, *outp;
00184 int count, context_start, pos_in_byte, padding;
00185
00186 int decrypt_every_8_byte(void) {
00187 for (pos_in_byte = 0; pos_in_byte < 8; pos_in_byte++) {
00188 if (context_start + pos_in_byte >= instrlen)
00189 return 1;
00190 decrypted[pos_in_byte] ^= crypt_buff[pos_in_byte];
00191 }
00192 qq_decipher((unsigned long *) decrypted, (unsigned long *) key, (unsigned long *) decrypted);
00193
00194 context_start += 8;
00195 crypt_buff += 8;
00196 pos_in_byte = 0;
00197 return 1;
00198 }
00199
00200
00201 if ((instrlen % 8) || (instrlen < 16))
00202 return 0;
00203
00204 qq_decipher((unsigned long *) instr, (unsigned long *) key, (unsigned long *) decrypted);
00205 pos_in_byte = decrypted[0] & 0x7;
00206 count = instrlen - pos_in_byte - 10;
00207
00208 if (*outstrlen_ptr < count || count < 0)
00209 return 0;
00210
00211 memset(m, 0, 8);
00212 crypt_buff_pre_8 = m;
00213 *outstrlen_ptr = count;
00214
00215 crypt_buff = instr + 8;
00216 context_start = 8;
00217 pos_in_byte++;
00218
00219 padding = 1;
00220 while (padding <= 2) {
00221 if (pos_in_byte < 8) {
00222 pos_in_byte++;
00223 padding++;
00224 }
00225 if (pos_in_byte == 8) {
00226 crypt_buff_pre_8 = instr;
00227 if (!decrypt_every_8_byte())
00228 return 0;
00229 }
00230 }
00231
00232 outp = outstr;
00233 while (count != 0) {
00234 if (pos_in_byte < 8) {
00235 *outp = crypt_buff_pre_8[pos_in_byte] ^ decrypted[pos_in_byte];
00236 outp++;
00237 count--;
00238 pos_in_byte++;
00239 }
00240 if (pos_in_byte == 8) {
00241 crypt_buff_pre_8 = crypt_buff - 8;
00242 if (!decrypt_every_8_byte())
00243 return 0;
00244 }
00245 }
00246
00247 for (padding = 1; padding < 8; padding++) {
00248 if (pos_in_byte < 8) {
00249 if (crypt_buff_pre_8[pos_in_byte] ^ decrypted[pos_in_byte])
00250 return 0;
00251 pos_in_byte++;
00252 }
00253 if (pos_in_byte == 8) {
00254 crypt_buff_pre_8 = crypt_buff;
00255 if (!decrypt_every_8_byte())
00256 return 0;
00257 }
00258 }
00259 return 1;
00260 }
00261
00262
00263
00264
00265 int qq_crypt(unsigned char flag,
00266 unsigned char *instr, int instrlen, unsigned char *key, unsigned char *outstr, int *outstrlen_ptr)
00267 {
00268 if (flag == DECRYPT)
00269 return qq_decrypt(instr, instrlen, key, outstr, outstrlen_ptr);
00270 else if (flag == ENCRYPT)
00271 qq_encrypt(instr, instrlen, key, outstr, outstrlen_ptr);
00272
00273 return 1;
00274 }
00275
00276
00277