LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 786|回复: 0

帮忙翻译一个C#的qq_tea加密/解密类,在线等候

[复制链接]
发表于 2005-8-23 21:49:50 | 显示全部楼层 |阅读模式
我在网上找到了VB、C、Java的tea加密算法,就是没有c#的,哪位对c#了解的高手,麻烦帮小弟翻译一份c#的代码。
其GC源码如下:

/**
* The QQ2003C protocol plugin
*
* for gaim
*
* Copyright (C) 2004 Puzzlebird
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*
*
* OICQ encryption algorithm
* Convert from ASM code provided by PerlOICQ
*
* Puzzlebird, Nov-Dec 2002
*/

// START OF FILE
/*****************************************************************************/
/*Notes: (OICQ uses 0x10 iterations, and modified something...)

IN : 64  bits of data in v[0] - v[1].
OUT: 64  bits of data in w[0] - w[1].
KEY: 128 bits of key  in k[0] - k[3].

delta is chosen to be the real part of
the golden ratio: Sqrt(5/4) - 1/2 ~ 0.618034 multiplied by 2^32.

0x61C88647 is what we can track on the ASM codes.!!
*/

#ifndef _WIN32
#include <arpa/inet.h>
#else
#include "win32dep.h"
#endif

#include <string.h>

#include "crypt.h"

/*****************************************************************************/
void qq_encipher(unsigned long *const v, const unsigned long *const k, unsigned long *const w)
{
        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;        /*  0x9E3779B9 - 0x100000000 = -0x61C88647 */

        while (n-- > 0) {
                sum += delta;
                y += ((z << 4) + a) ^ (z + sum) ^ ((z >> 5) + b);
                z += ((y << 4) + c) ^ (y + sum) ^ ((y >> 5) + d);
        }                        // while

        w[0] = htonl(y);
        w[1] = htonl(z);
}                                // qq_enciper

/*****************************************************************************/
void qq_decipher(unsigned long *const v, const unsigned long *const k, unsigned long *const w)
{
        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,        // why this ? must be related with n value
            delta = 0x9E3779B9;

        /* sum = delta<<5, in general sum = delta * n */
        while (n-- > 0) {
                z -= ((y << 4) + c) ^ (y + sum) ^ ((y >> 5) + d);
                y -= ((z << 4) + a) ^ (z + sum) ^ ((z >> 5) + b);
                sum -= delta;
        }

        w[0] = htonl(y);
        w[1] = htonl(z);
}                                // qq_decipher

/********************************************************************
* encrypt part
*******************************************************************/

void qq_encrypt(unsigned char *instr, int instrlen, unsigned char *key, unsigned char *outstr, int *outstrlen_prt)
{
        unsigned char plain[8],        // plain text buffer
         plain_pre_8[8],        // plain text buffer, previous 8 bytes
        *crypted,                // crypted text
        *crypted_pre_8,                // crypted test, previous 8 bytes
        *inp;                        // current position in instr
        int pos_in_byte = 1,        // loop in the byte
            is_header = 1,        // header is one byte
            count = 0,                // number of bytes being crypted
            padding = 0;        // number of padding stuff

        int rand(void) {        // it can be the real random seed function
                return 0xdead;
        }                        // override with number, convenient for debug

  /*** we encrypt every eight byte ***/
        void encrypt_every_8_byte(void) {
                for (pos_in_byte = 0; pos_in_byte < 8; pos_in_byte++) {
                        if (is_header) {
                                plain[pos_in_byte] ^= plain_pre_8[pos_in_byte];
                        } else {
                                plain[pos_in_byte] ^= crypted_pre_8[pos_in_byte];
                        }
                }                // prepare plain text
                qq_encipher((unsigned long *) plain, (unsigned long *) key, (unsigned long *) crypted);        // encrypt it

                for (pos_in_byte = 0; pos_in_byte < 8; pos_in_byte++) {
                        crypted[pos_in_byte] ^= plain_pre_8[pos_in_byte];
                }
                memcpy(plain_pre_8, plain, 8);        // prepare next

                crypted_pre_8 = crypted;        // store position of previous 8 byte
                crypted += 8;        // prepare next output
                count += 8;        // outstrlen increase by 8
                pos_in_byte = 0;        // back to start
                is_header = 0;        // and exit header
        }                        // encrypt_every_8_byte

        pos_in_byte = (instrlen + 0x0a) % 8;        // header padding decided by instrlen
        if (pos_in_byte) {
                pos_in_byte = 8 - pos_in_byte;
        }
        plain[0] = (rand() & 0xf8) | pos_in_byte;

        memset(plain + 1, rand() & 0xff, pos_in_byte++);
        memset(plain_pre_8, 0x00, sizeof(plain_pre_8));

        crypted = crypted_pre_8 = outstr;

        padding = 1;                // pad some stuff in header
        while (padding <= 2) {        // at most two byte
                if (pos_in_byte < 8) {
                        plain[pos_in_byte++] = rand() & 0xff;
                        padding++;
                }
                if (pos_in_byte == 8) {
                        encrypt_every_8_byte();
                }
        }

        inp = instr;
        while (instrlen > 0) {
                if (pos_in_byte < 8) {
                        plain[pos_in_byte++] = *(inp++);
                        instrlen--;
                }
                if (pos_in_byte == 8) {
                        encrypt_every_8_byte();
                }
        }

        padding = 1;                // pad some stuff in tailer
        while (padding <= 7) {        // at most sever byte
                if (pos_in_byte < 8) {
                        plain[pos_in_byte++] = 0x00;
                        padding++;
                }
                if (pos_in_byte == 8) {
                        encrypt_every_8_byte();
                }
        }

        *outstrlen_prt = count;
}                                // qq_encrypt


/********************************************************************
* [decrypt part]
* return 0 if failed, otherwise return 1
********************************************************************/

int qq_decrypt(unsigned char *instr, int instrlen, unsigned char *key, unsigned char *outstr, int *outstrlen_ptr)
{
        unsigned char decrypted[8], m[8], *crypt_buff, *crypt_buff_pre_8, *outp;
        int count, context_start, pos_in_byte, padding;

        int decrypt_every_8_byte(void) {
                for (pos_in_byte = 0; pos_in_byte < 8; pos_in_byte++) {
                        if (context_start + pos_in_byte >= instrlen)
                                return 1;
                        decrypted[pos_in_byte] ^= crypt_buff[pos_in_byte];
                }
                qq_decipher((unsigned long *) decrypted, (unsigned long *) key, (unsigned long *) decrypted);

                context_start += 8;
                crypt_buff += 8;
                pos_in_byte = 0;
                return 1;
        }                        // decrypt_every_8_byte

        // at least 16 bytes and %8 == 0
        if ((instrlen % 8) || (instrlen < 16))
                return 0;
        // get information from header
        qq_decipher((unsigned long *) instr, (unsigned long *) key, (unsigned long *) decrypted);
        pos_in_byte = decrypted[0] & 0x7;
        count = instrlen - pos_in_byte - 10;        // this is the plaintext length
        // return if outstr buffer is not large enought or error plaintext length
        if (*outstrlen_ptr < count || count < 0)
                return 0;

        memset(m, 0, 8);
        crypt_buff_pre_8 = m;
        *outstrlen_ptr = count;        // everything is ok! set return string length

        crypt_buff = instr + 8;        // address of real data start
        context_start = 8;        // context is at the second 8 byte
        pos_in_byte++;                // start of paddng stuff

        padding = 1;                // at least one in header
        while (padding <= 2) {        // there are 2 byte padding stuff in header
                if (pos_in_byte < 8) {        // bypass the padding stuff, none sense data
                        pos_in_byte++;
                        padding++;
                }
                if (pos_in_byte == 8) {
                        crypt_buff_pre_8 = instr;
                        if (!decrypt_every_8_byte())
                                return 0;
                }
        }                        // while

        outp = outstr;
        while (count != 0) {
                if (pos_in_byte < 8) {
                        *outp = crypt_buff_pre_8[pos_in_byte] ^ decrypted[pos_in_byte];
                        outp++;
                        count--;
                        pos_in_byte++;
                }
                if (pos_in_byte == 8) {
                        crypt_buff_pre_8 = crypt_buff - 8;
                        if (!decrypt_every_8_byte())
                                return 0;
                }
        }                        // while

        for (padding = 1; padding < 8; padding++) {
                if (pos_in_byte < 8) {
                        if (crypt_buff_pre_8[pos_in_byte] ^ decrypted[pos_in_byte])
                                return 0;
                        pos_in_byte++;
                }
                if (pos_in_byte == 8) {
                        crypt_buff_pre_8 = crypt_buff;
                        if (!decrypt_every_8_byte())
                                return 0;
                }
        }                        // for
        return 1;
}                                // qq_decrypt

/*****************************************************************************/
/* This is the Public Function */
// return 1 is succeed, otherwise return 0
int qq_crypt(unsigned char flag,
             unsigned char *instr, int instrlen, unsigned char *key, unsigned char *outstr, int *outstrlen_ptr)
{
        if (flag == DECRYPT)
                return qq_decrypt(instr, instrlen, key, outstr, outstrlen_ptr);
        else if (flag == ENCRYPT)
                qq_encrypt(instr, instrlen, key, outstr, outstrlen_ptr);

        return 1;                // flag must be DECRYPT or ENCRYPT
}                                // qq_crypt

/*****************************************************************************/
// END OF FILE
您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表