QQ的Encrypt和Decrypt原代码

5月 23, 2008 | 4:40 下午分类:MSN && QQ && FETION | 1,792 次浏览

QQ的Encrypt和Decrypt原代码

/*
 * Copyright (c) 2001 shellcode@sina.com.cn
 * All rights reserved.
 * Translated to C from FOICQ's qqencrypt.asm
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *      This product includes software developed by Paul Kranenburg.
 * 4. The name of the author may not be used to endorse or promote products
 *    derived from this software without specific prior written permission
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * qqencrypt.c, v 1.0 2001/12/12 Shell Code
 */

unsigned int swapu32(unsigned int n)
{
        return(((n & 0xff000000) >> 24) | ((n & 0x000000ff) << 24) |
                ((n & 0x00ff0000) >> 8) | ((n & 0x0000ff00) << 8));
}

void encrypt_qword(unsigned long *, unsigned long *, unsigned long *);
void decrypt_qword(unsigned long *, unsigned long *, unsigned long *);

/* use key to encrypt in buffer
 * key must be 16+ bytes long!
 */
void encrypt_msg(unsigned char *in, int inlen, unsigned long *key, unsigned char *out, unsigned long *outlen)
{
        register int m, i, j, count, p = 1;
        unsigned char q[12], *q1, *q2, *inp;
        unsigned char mkey[8];

        m = (inlen+10)%8;

        if (m)  m = 8-m;
        q[0] = (rand()&0xf8) | m;
        i = j = 1;
        while(m>0) {
                q[i++] = rand()&0xff;
                m –;
        }
        count = *outlen = 0;
        q2 = q1 = out;
        memset(mkey, 0, sizeof(mkey));
        while( p <= 2 ) {
                if (i < 8) {
                        q[i++] = rand()&0xff;
                        p ++;
                }
                if (i == 8) {
                        for (i = 0; i < 8; i ++)
                                q[i] ^= mkey[i];
                        encrypt_qword((unsigned long *)q, key, (unsigned long *)out);
                        for (i = 0; i < 8; i ++)
                                q1[i] ^= mkey[i];
                        q2 = q1;
                        q1 += 8;
                        count += 8;
                        memcpy(mkey, q, 8);
                        j = i = 0;
                }
        }
        inp = in;
        while (inlen > 0) {
                if (i < 8) {
                        q[i] = inp[0];
                        inp ++;
                        i ++;
                        inlen –;
                }
                if (i == 8) {
                        for (i = 0; i < 8; i ++)  {
                                if (j) q[i] ^= mkey[i];
                                else q[i] ^= q2[i];
                        }
                        j = 0;
                        encrypt_qword((unsigned long *)q, key, (unsigned long *)q1);
                        for (i = 0; i < 8; i ++)
                                q1[i] ^= mkey[i];
                        count += 8;
                        memcpy(mkey, q, 8);
                        q2 = q1;
                        q1 += 8;
                        i = 0;
                }
        }
        p = 1;
        while (p < 8) {
                if (i < 8) {
                        memset(q+i, 0, 4);
                        p++;
                        i++;
                }
                if (i == 8) {
                        for (i = 0; i < 8; i ++)
                                q[i] ^= q2[i];
                        encrypt_qword((unsigned long *)q, key, (unsigned long *)q1);
                        for (i = 0; i < 8; i ++)
                                q1[i] ^= mkey[i];
                        memcpy(mkey, q, 8);
                        count += 8;
                        q2 = q1;
                        q1 += 8;
                        i = 0;
                }
        }
        *outlen = count;
}

/* decrypt a encrypted string
 * key must be 16+ bytes long
 * return 0 if failed.
 * otherwise return 1.
 */
int decrypt_msg(unsigned char *in, int inlen, unsigned long *key, unsigned char *out, unsigned long *outlen)
{
        unsigned char q[8], mkey[8], *q1, *q2, *outp;
        register int count, i, j, m, p;

        if (inlen%8 || inlen<16) return 0;
        /* get basic information of the packet */
        decrypt_qword((unsigned long *)in, key, (unsigned long *)q);
        j = q[0]&0×7;
        count = inlen - j - 10;
        if (*outlen < count || count < 0) return 0;
        *outlen = count;

        memset(mkey, 0, 8);
        q2 = mkey;
        i = 8; p = 1;
        q1 = in+8;
        j ++;
        while (p <= 2) {
                if (j < 8) {
                        j ++;
                        p ++;
                } else if (j == 8) {
                        q2 = in;
                        for (j = 0; j < 8; j ++ ) {
                                if (i + j >= inlen) return 0;
                                q[j] ^= q1[j];
                        }
                        decrypt_qword((unsigned long *)q, key, (unsigned long *) q);
                        i += 8;
                        q1 += 8;
                        j = 0;
                }
        }
        outp = out;
        while(count !=0) {
                if (j < 8) {
                        outp[0] = q2[j] ^ q[j];
                        outp ++;
                        count –;
                        j ++;
                } else if (j == 8) {
                        q2 = q1-8;
                        for (j = 0; j < 8; j ++ ) {
                                if (i + j >= inlen) return 0;
                                q[j] ^= q1[j];
                        }
                        decrypt_qword((unsigned long *)q, key, (unsigned long *) q);
                        i += 8;
                        q1 += 8;
                        j = 0;
                }
        }
        for (p = 1; p < 8; p ++) {
                if (j < 8) {
                        if (q2[j]^q[j])
                                return 0;
                        j ++;
                } else if (j == 8 ) {
                        q2 = q1;
                        for (j = 0; j < 8; j ++ ) {
                                if (i + j >= inlen) return 0;
                                q[j] ^= q1[j];
                        }
                        decrypt_qword((unsigned long *)q, key, (unsigned long *) q);
                        i += 8;
                        q1 += 8;
                        j = 0;
                }
        }
        return 1;
}

void encrypt_qword(unsigned long *in, unsigned long *key, unsigned long *out)
{
        unsigned long code[4];
        register unsigned long i = 16, j = 0, m, n;

        m = swapu32(in[0]);
        n = swapu32(in[1]);

        code[0] = swapu32(key[0]); code[1] = swapu32(key[1]);
        code[2] = swapu32(key[2]); code[3] = swapu32(key[3]);

        while(i–>0)
        {
                j -= 0×61c88647;
                m += (n>>5)+code[1] ^ (n<<4) +code[0] ^ j+n;
                n += (m>>5)+code[3] ^ (m<<4) +code[2] ^ j+m;
        }
        out[0] = swapu32(m);
        out[1] = swapu32(n);
}

void decrypt_qword(unsigned long *in, unsigned long *key, unsigned long *out)
{
        unsigned long code[4];
        register unsigned long i=16, j=0xe3779B90, m, n;

        m = swapu32(in[0]);
        n = swapu32(in[1]);

        code[0] = swapu32(key[0]); code[1] = swapu32(key[1]);
        code[2] = swapu32(key[2]); code[3] = swapu32(key[3]);

        while(i– >0)
        {
                n -= ((m>>5)+code[3])^((m<<4)+code[2])^(j+m);
                m -= ((n>>5)+code[1])^((n<<4)+code[0])^(j+n);
                j += 0×61C88647;
        }
        out[0] = swapu32(m);
        out[1] = swapu32(n);
}

void transform_msg(const unsigned char *in, int inlen, unsigned char *out, unsigned int *number)
{
        unsigned char c;
        unsigned int i, j;

        for (i = 0, j = 0 ; j < inlen ; j++) {
                if (i >= 0×3ff) break;
                c = in[j];
                if (c == 0) {
                        out[i++] |= 0xff;
                        out[i] = 0×30;
                } else if (c == 0xff) {
                        out[i++] |= 0xff;
                        out[i] |= 0xff;
                } else
                        out[i] = c;
                i ++;
        }
        *number = i;
}

void detransform_msg(const unsigned char *in, int inlen, unsigned char *out, unsigned int *number)
{
        unsigned char c;
        unsigned int i, j;

        for ( i = 0,j = 0; j < inlen; j ++) {
                if (i >= 0×3ff) break;
                c = in[j];
                if (c == 0xff) {
                        if (in[j+1] == 0×30) {
                                out[i++] = 0;
                                j ++;
                                continue;
                        }
                        if (in[j+1] == 0xff) {
                                out[i++] = 0xff;
                                j ++;
                                continue;
                        }
                }
                out[i++] = c;
        }
        out[i] = ‘\0′;
        *number = i;
}

#ifdef TEST
/* test.c */

#include <string.h>
#include <stdio.h>
/*
void encrypt_msg(unsigned char* ,int ,unsigned long* ,unsigned char* ,unsigned int* );
int  decrypt_msg(unsigned char* ,int ,unsigned long* inbuf2,unsigned char* ,unsigned int* );
void transform_msg(unsigned char* ,int ,unsigned char* ,unsigned int* );
*/
#define LINE 100

int main(int argc, char **argv)
{
        char key[] = “ZheqpGVkdd7ufqF1″; /* key must be 16+ bytes long */
        char out[LINE], c[LINE];
        int i, outlen, result;

        if (argc < 2)
                printf(”please supply arguments!\n”);
        else {
                memset(out, 0, LINE);
                memset(c, 0, LINE);
                i = strlen(argv[1]);
//              encrypt_msg(0, 0, (unsigned long *)key, c, &outlen);
                encrypt_msg(argv[1], i, (unsigned long *)key, c, &outlen);
                result = decrypt_msg(c, outlen, (unsigned long *)key, out, &i);
                /*
                transform_msg(c, outlen, out, &i);
                */
                printf(”result=%d len=%d out=%s\n”, result, i, out);
        }
}
#endif

发表您的评论

您的名字:

您的邮箱: (*不会被公布

您的网站: