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. Java BufferedWriter与BufferedReader操作文本文件

    /** * 采用字符流读取写入文本文件 */ public class FileUtil { /** * 写文件 * @param fileName * @param content */ publi ...

  2. PooledDataSource--mybatis-3-mybatis-3.2.3

    org.apache.ibatis.executor.SimpleExecutor public <E> List<E> doQuery(MappedStatement ms, ...

  3. UVa 147 Dollars(硬币转换)

    题目大意:给出五种硬币,价值分别为 1,5,10,25,50,.当给出一个价值时,求出能够组合的种数(每种硬币可以用无限次). 思路:完全背包, dp[i][j]表示总数 i 能够被表示的种数.状态转 ...

  4. Android应用开发学习之AlertDialog对话框

    作者:刘昊昱 博客:http://blog.csdn.net/liuhaoyutz 本文中我们通过一个例子来看AlertDialog对话框的实现,其运行效果如下: 主布局文件main.xml内容如下: ...

  5. 《Java程序员面试笔试宝典》之Java程序初始化的顺序是怎样的

    在Java语言中,当实例化对象时,对象所在类的所有成员变量首先要进行初始化,只有当所有类成员完成初始化后,才会调用对象所在类的构造函数创建对象. Java程序的初始化一般遵循以下三个原则(以下三原则优 ...

  6. poj 2096 Collecting Bugs(期望 dp 概率 推导 分类讨论)

    Description Ivan is fond of collecting. Unlike other people who collect post stamps, coins or other ...

  7. WPF页面切换及弹窗

    WPF页面切换及弹窗 结构如图: 效果如图: 代码如下: xaml <Window x:Class="PageChange.MainWindow" xmlns="h ...

  8. C#使用自定义字体(从文件获取)

    在进行软件开发,尤其是开发WinForm程序时,有时为了实现界面的美化,不可避免的需要使用一些特殊的字体,但是在开发完成之后,将程序移到其他的机器上时,由于这些机器可能没有安装相应的字体,所以整个界面 ...

  9. 微信jssdk批量展示卡包中的卡券

    <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding= ...

  10. Hacker(十一)----黑客常用入侵方法

    Internet中,为了防止黑客入侵自己的电脑,就必须了解黑客入侵目标计算机的常用方法.黑客常用的入侵方法有数据驱动攻击.系统文件非法利用.伪造信息攻击.远端操纵等. 一.数据驱动攻击 数据驱动攻击是 ...