TEA(Tiny Encryption Algorithm) 是一种简单高效的加密算法,以加密解密速度快,实现简单著称。算法真的很简单,TEA算法每一次可以操作64-bit(8-byte),采用128-bit(16-byte)作为key,算法采用迭代的形式,推荐的迭代轮数是64轮,最少32轮。目前我只知道QQ一直用的是16轮TEA。没什么好说的,先给出C语言的源代码(默认是32轮):

void encrypt(unsigned long *v, unsigned long *k) {
    unsigned ], z=v[], sum=, i;         /* set up */
    unsigned long delta=0x9e3779b9;                 /* a key schedule constant */
    unsigned ], b=k[], c=k[], d=k[];   /* cache key */
    ; i < ; i++) {                        /* basic cycle start */
        sum += delta;
        y += ((z<<) + a) ^ (z + sum) ^ ((z>>) + b);
        z += ((y<<) + c) ^ (y + sum) ^ ((y>>) + d);/* end cycle */
    }
    v[]=y;
    v[]=z;
}

void decrypt(unsigned long *v, unsigned long *k) {
    unsigned ], z=v[], sum=0xC6EF3720, i; /* set up */
    unsigned long delta=0x9e3779b9;                  /* a key schedule constant */
    unsigned ], b=k[], c=k[], d=k[];    /* cache key */
    ; i<; i++) {                            /* basic cycle start */
        z -= ((y<<) + c) ^ (y + sum) ^ ((y>>) + d);
        y -= ((z<<) + a) ^ (z + sum) ^ ((z>>) + b);
        sum -= delta;                                /* end cycle */
    }
    v[]=y;
    v[]=z;
}

C语言写的用起来当然不方便,没关系,用C++封装以下就OK了:

util.h

#ifndef UTIL_H
#define UTIL_H

#include <string>
#include <cstdlib>

typedef unsigned char byte;
typedef unsigned long ulong;

/*
*convert int to hex char.
*example:10 -> 'A',15 -> 'F'
*/
char intToHexChar(int x);

/*
*convert hex char to int.
*example:'A' -> 10,'F' -> 15
*/
int hexCharToInt(char hex);

using std::string;
/*
*convert a byte array to hex string.
*hex string format example:"AF B0 80 7D"
*/
string bytesToHexString(const byte *in, size_t size);

/*
*convert a hex string to a byte array.
*hex string format example:"AF B0 80 7D"
*/
size_t hexStringToBytes(const string &str, byte *out);

#endif/*UTIL_H*/

util.cpp

#include "util.h"
#include <vector>

using namespace std;

char intToHexChar(int x) {
    ] = {
        ',
        ',
        ', 'A', 'B',
        'C', 'D', 'E', 'F'
    };
    return HEX[x];
}

int hexCharToInt(char hex) {
    hex = toupper(hex);
    if (isdigit(hex))
        ');
    if (isalpha(hex))
        );
    ;
}

string bytesToHexString(const byte *in, size_t size) {
    string str;
    ; i < size; ++i) {
        int t = in[i];
        ;
        ;
        str.append(, intToHexChar(a));
        str.append(, intToHexChar(b));
        )
            str.append(, ' ');
    }
    return str;
}

size_t hexStringToBytes(const string &str, byte *out) {

    vector<string> vec;
    , prevPos = ;
    while ((currPos = str.find(' ', prevPos)) != string::npos) {
        string b(str.substr(prevPos, currPos - prevPos));
        vec.push_back(b);
        prevPos = currPos + ;
    }
    if (prevPos < str.size()) {
        string b(str.substr(prevPos));
        vec.push_back(b);
    }
    typedef vector<string>::size_type sz_type;
    sz_type size = vec.size();
    ; i < size; ++i) {
        ]);
        ]);
         + b;
    }
    return size;
}

tea.h

#ifndef TEA_H
#define TEA_H

/*
*for htonl,htonl
*do remember link "ws2_32.lib"
*/
#include <winsock2.h>
#include "util.h"

class TEA {
public:
    TEA(, bool isNetByte = false);
    TEA(const TEA &rhs);
    TEA& operator=(const TEA &rhs);
    void encrypt(const byte *in, byte *out);
    void decrypt(const byte *in, byte *out);
private:
    void encrypt(const ulong *in, ulong *out);
    void decrypt(const ulong *in, ulong *out);
    ulong ntoh(ulong netlong) { return _isNetByte ? ntohl(netlong) : netlong; }
    ulong hton(ulong hostlong) { return _isNetByte ? htonl(hostlong) : hostlong; }
private:
    int _round; //iteration round to encrypt or decrypt
    bool _isNetByte; //whether input bytes come from network
    ]; //encrypt or decrypt key
};

#endif/*TEA_H*/

tea.cpp

#include "tea.h"
#include <cstring> //for memcpy,memset

using namespace std;

TEA::TEA(const byte *key, int round /*= 32*/, bool isNetByte /*= false*/)
:_round(round)
,_isNetByte(isNetByte) {
    )
        memcpy(_key, key, );
    else
        memset(_key, , );
}

TEA::TEA(const TEA &rhs)
:_round(rhs._round)
,_isNetByte(rhs._isNetByte) {
    memcpy(_key, rhs._key, );
}

TEA& TEA::operator=(const TEA &rhs) {
    if (&rhs != this) {
        _round = rhs._round;
        _isNetByte = rhs._isNetByte;
        memcpy(_key, rhs._key, );
    }
    return *this;
}

void TEA::encrypt(const byte *in, byte *out) {
    encrypt((const ulong*)in, (ulong*)out);
}

void TEA::decrypt(const byte *in, byte *out) {
    decrypt((const ulong*)in, (ulong*)out);
}

void TEA::encrypt(const ulong *in, ulong *out) {

    ulong *k = (ulong*)_key;
    register ]);
    register ]);
    register ]);
    register ]);
    register ]);
    register ]);
    register ulong delta = 0x9E3779B9; /* (sqrt(5)-1)/2*2^32 */
    register int round = _round;
    register ;

    while (round--) {    /* basic cycle start */
        sum += delta;
        y += ((z << ) + a) ^ (z + sum) ^ ((z >> ) + b);
        z += ((y << ) + c) ^ (y + sum) ^ ((y >> ) + d);
    }    /* end cycle */
    ] = ntoh(y);
    ] = ntoh(z);
}

void TEA::decrypt(const ulong *in, ulong *out) {

    ulong *k = (ulong*)_key;
    register ]);
    register ]);
    register ]);
    register ]);
    register ]);
    register ]);
    register ulong delta = 0x9E3779B9; /* (sqrt(5)-1)/2*2^32 */
    register int round = _round;
    register ;

    )
        sum = 0xC6EF3720; /* delta << 5*/
    )
        sum = 0xE3779B90; /* delta << 4*/
    else
        sum = delta * round;

    while (round--) {    /* basic cycle start */
        z -= ((y << ) + c) ^ (y + sum) ^ ((y >> ) + d);
        y -= ((z << ) + a) ^ (z + sum) ^ ((z >> ) + b);
        sum -= delta;
    }    /* end cycle */
    ] = ntoh(y);
    ] = ntoh(z);
}

需要说明的是TEA的构造函数:
TEA(const byte *key, int round = 32, bool isNetByte = false);
1.key - 加密或解密用的128-bit(16byte)密钥。
2.round - 加密或解密的轮数,常用的有64,32,16。
3.isNetByte - 用来标记待处理的字节是不是来自网络,为true时在加密/解密前先要转换成本地字节,执行加密/解密,然后再转换回网络字节。偷偷告诉你,QQ就是这样做的!

最后当然少不了测试代码:
test.cpp

#include "tea.h"
#include "util.h"
#include <iostream>

using namespace std;

int main() {

    const string plainStr("AD DE E2 DB B3 E2 DB B3");
    const string keyStr("3A DA 75 21 DB E2 DB B3 11 B4 49 01 A5 C6 EA D4");
    , SIZE_OUT = , SIZE_KEY = ;
    byte plain[SIZE_IN], crypt[SIZE_OUT], key[SIZE_KEY];

    size_t size_in = hexStringToBytes(plainStr, plain);
    size_t size_key = hexStringToBytes(keyStr, key);

    if (size_in != SIZE_IN || size_key != SIZE_KEY)
        ;

    cout << "Plain: " << bytesToHexString(plain, size_in) << endl;
    cout << "Key  : " << bytesToHexString(key, size_key) << endl;

    TEA tea(key, , true);
    tea.encrypt(plain, crypt);
    cout << "Crypt: " << bytesToHexString(crypt, SIZE_OUT) << endl;

    tea.decrypt(crypt, plain);
    cout << "Plain: " << bytesToHexString(plain, SIZE_IN) << endl;
    ;
}

运行结果:

Plain: AD DE E2 DB B3 E2 DB B3
Key  : 3A DA   DB E2 DB B3  B4   A5 C6 EA D4
Crypt: 3B 3B 4D 8C  3A FD F2
Plain: AD DE E2 DB B3 E2 DB B3

TEA加密算法的C/C++实现的更多相关文章

  1. TEA加密算法的文件加密和解密的实现

    一.TEA加密算法简介 TEA加密算法是由英国剑桥大学计算机实验室提出的一种对称分组加密算法.它采用扩散和混乱方法,对64位的明文数据块,用128位密钥分组进行加密,产生64位的密文数据块,其循环轮数 ...

  2. DES、AES、TEA加密算法的比较

    1.     DES算法介绍: DES算法具有对称性, 既可以用于加密又可以用于解密.对称性带来的一个很大的好处在于硬件实现, DES 的加密和解密可以用完全相同的硬件来实现.DES 算法的明文分组是 ...

  3. tea加密算法及其变种的研究

    tea 介绍 "TEA" 的全称为"Tiny Encryption Algorithm" 是1994年由英国剑桥大学的David j.wheeler发明的. T ...

  4. TEA加密算法java版

    这个算法简单,而且效率高,每次可以操作8个字节的数据,加密解密的KEY为16字节,即包含4个int数据的int型数组,加密轮数应为8的倍数,一般比较常用的轮数为64,32,16,推荐用64轮. 源代码 ...

  5. TEA算法

    我们要讨论的最后一个分组密码加密算法是TEA(Tiny Encryption Algorithm).到目前为止,我们在前面所呈现的连线图可能会使你得出如下结论:分组密码加密算法必须是复杂的.TEA却能 ...

  6. 单片机上使用TEA加密通信(转)

    源:单片机上使用TEA加密通信 本文博客链接:http://blog.csdn.net/jdh99,作者:jdh,转载请注明. 环境: 主机:WIN7 开发环境:MDK4.72 单片机:STM32 说 ...

  7. 【搬运】Tea算法Java实现工具类

    最近在做数据加密,目标是实现平台app的数据安全性,所以准备使用AES+Base64进行加密,适逢一个特长的json串AES加密不了,于是在谷歌了各种算法,判断是否合用,参见 各种加密算法比较 一文中 ...

  8. TEA加密/解密算法

    在游戏项目中,一般需要对资源或数据进行加密保护,最简单高效的加密算法就是采用位与或之类的,但是比较容易被人分析出来.TEA加密算法不但比较简单,而且有很强的抗差分分析能力,加密速度也比较快.可以根据项 ...

  9. AliCTF 2016

    上上周参加了阿里的CTF,靠着最后绝杀队伍有幸拿到了国内第一名,也顺利进入了XCTF Final.把自己做的几个题简单写了下,发出来也算个总结吧. PWN-FB 经典的null byte overfl ...

随机推荐

  1. Ubuntu apache 禁止目录浏览

    $ sudo vim /etc/apache2/sites-enabled/000-default 将Options后面Indexes前面加上"-"表示禁止目录浏览: <Di ...

  2. Android使用xml中定义的动画效果

    Animation animation = AnimationUtils.loadAnimation(getActivity(), R.anim.zqrl_out); animation.setFil ...

  3. linux最大文件句柄数量总结

    转载:http://jameswxx.iteye.com/blog/2096461 useradd -g gid -G gid1,gid2 user usermod -g gid -G gid1,gi ...

  4. PowerShell_零基础自学课程_6_PS中获取帮助信息详解、管道、格式化输

    前些文章陆续的说了一些关于这些主题,但是讨论的都不够深入,今天我们深入的了解一下获取帮助信息.管道以及格式化输出的内容. 一.获取帮助信息 在PS中获取帮助信息,最常用的有: -? .get-comm ...

  5. Spring AOP 本质(4)

    这一主要看看Spring AOP是如何实现通知包围的.   Spring AOP包围通知在功能上和前置通知加后置通知类似,但还是有区别的:包围通知可以修改返回值,还可以阻止.替换目标方法的执行.   ...

  6. eclipse php 开发环境配置

    一般常用的是eclipse+pdt.我是直接下载的Eclipse for php :http://www.eclipse.org/downloads/packages/eclipse-php-deve ...

  7. geoip 添加一列,add_field =>["[geoip][request_time]","%{request_time}"]

    "message" => " 10.171.246.184 [11/Sep/2016:14:42:53 +0800] \"GET /wechat/home ...

  8. Find the Celebrity 解答

    Question Suppose you are at a party with n people (labeled from 0 to n - 1) and among them, there ma ...

  9. Find Median from Data Stream 解答

    Question Median is the middle value in an ordered integer list. If the size of the list is even, the ...

  10. mysqldump命令详解(转载)

    1.简介 mysqldump为MySQL逻辑备份工具,产生一系列SQL语句,之后重新执行以产生备份的库.表及数据.也可产生CSV.XML等格式的数据.适用于各类引擎的表. 运行mysqldump需一定 ...