Top
Tea算法 - C++_C/C++代码_BlackFeather'S Blog
忙忙碌碌,更新不及时诶。

Tea算法 - C++

C/C++代码 blackfeather 679


Tea算法被某公司应用的酣畅淋漓,最近用到了,在测试了多分代码后,推荐此代码。保留原作者信息。


cpypt.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
/**
 * The QQ2003C protocol plugin
 *
 * for gaim
 *
 * Copyright © 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 3 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
 *
 **************************************************
 * Reorganized by Minmin <csdengxm@hotmail.com>, 2005-3-27
 **************************************************
 */
 
#include "stdafx.h"
#include "crypt.h"
 
#include <string.h>
#ifdef _WIN32
#include <winsock.h>
#else
#include <arpa/inet.h>
#endif
#include <cstring>
 
Crypt::Crypt()
{
}
 
Crypt::~Crypt()
{
}
 
void Crypt::teaEncipher(unsigned int *const v, const unsigned int *const k,
            unsigned int *const w)
{
    register unsigned int
        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,       /* do encrypt 16 (0x10) times */
        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);
    }
 
    w[0] = htonl(y); w[1] = htonl(z);
}
void Crypt::teaDecipher(unsigned int *const v, const unsigned int *const k,
            unsigned int *const w)
{
    register unsigned int
        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;
 
    void *p = &a;
    /* 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);
}
 
void Crypt::encrypt( unsigned char* instr, int32 instrlen, unsigned char* key,
            unsigned char*  outstr, int32* outstrlen_ptr)
{
    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*/
 
    //void encrypt_every_8_byte (void);
 
    /*** we encrypt every eight byte ***/
#define encrypt_every_8_byte()  \
    {\
    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*/\
    teaEncipher( (unsigned int *) plain,\
    (unsigned int *) key, \
    (unsigned int *) 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_ptr = count;
 
}
 
int Crypt::rand(void)
{
    /* it can be the real random seed function*/
    return 0xdead; /* override with number, convenient for debug*/
}
 
int Crypt::decrypt( unsigned char* instr, int32 instrlen, unsigned char* key,
            unsigned char*  outstr, int32* outstrlen_ptr)
{
    unsigned char
        decrypted[8], m[8],
        * crypt_buff,
        * crypt_buff_pre_8,
        * outp;
    int
        count,
        context_start,
        pos_in_byte,
        padding;
 
#define decrypt_every_8_byte()  {\
    bool bNeedRet = false;\
    for (pos_in_byte = 0; pos_in_byte < 8; pos_in_byte ++ ) {\
    if (context_start + pos_in_byte >= instrlen) \
    {\
    bNeedRet = true;\
    break;\
    }\
    decrypted[pos_in_byte] ^= crypt_buff[pos_in_byte];\
    }\
    if( !bNeedRet ) { \
    teaDecipher( (unsigned int *) decrypted, \
    (unsigned int *) key, \
    (unsigned int *) decrypted);\
    \
    context_start +=  8;\
    crypt_buff    +=  8;\
    pos_in_byte   =   0;\
    }\
}/* decrypt_every_8_byte*/
 
    /* at least 16 bytes and %8 == 0*/
    if ((instrlen % 8) || (instrlen < 16)) return 0;
    /* get information from header*/
    teaDecipher( (unsigned int *) instr,
        (unsigned int *) key,
        (unsigned int *) 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 stuffv*/
 
    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;
            decrypt_every_8_byte();
        }
    }/* 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;
            decrypt_every_8_byte();
        }
    }/* 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;
            decrypt_every_8_byte();
        }
    }/* for*/
    return 1;
 
}
 
 
int Crypt::qq_crypt ( unsigned char   flag,  unsigned char*  instr,  int32  instrlen,
            unsigned char*  key, unsigned char*  outstr, int32* outstrlen_ptr)
{
    if (flag == DECRYPT)
        return decrypt(instr, instrlen, key, outstr, outstrlen_ptr);
    else
        if (flag == ENCRYPT)
            encrypt(instr, instrlen, key, outstr, outstrlen_ptr);
 
    return 1; /* flag must be DECRYPT or ENCRYPT*/
}/* qq_crypt*/


crypt.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
/**
 * The QQ2003C protocol plugin
 *
 * for gaim
 *
 * Copyright © 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 3 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
 *
 **************************************************
 * Reorganized by Minmin <csdengxm@hotmail.com>, 2005-3-27
 **************************************************
 */
 
#ifndef Crypt_H
#define Crypt_H
 
#define DECRYPT 0x00
#define ENCRYPT 0x01
 
typedef unsigned long int uint32;
typedef unsigned short     uint16;
typedef unsigned char      uint8;
 
typedef signed long int       int32;
typedef signed short       int16;
typedef signed char            int8;
 
class Crypt
{
public:
    Crypt();
    ~Crypt();
 
    static void encrypt( unsigned char* instr, int32 instrlen, unsigned char* key,
                unsigned char*  outstr, int32* outstrlen_ptr);
 
    static int decrypt(unsigned char* instr, int32 instrlen, unsigned char* key,
                unsigned char*  outstr, int32* outstrlen_ptr);
 
private:
    static int rand(void);
    static void teaEncipher(unsigned int *const v, const unsigned int *const k,
                unsigned int *const w);
    static void teaDecipher(unsigned int *const v, const unsigned int *const k,
                unsigned int *const w);
 
    static int qq_crypt ( unsigned char   flag,  unsigned char*  instr,  int32  instrlen,
                unsigned char*  key, unsigned char*  outstr, int32* outstrlen_ptr);
};
 
#endif


可能是作者编码风格,虽然是c++但是都是静态方法,直接调用即可。


评论列表:

发表评论:

验证码