TEA(Tiny Encryption Algorithm) 是一种简单高效的加密算法,以加密解密速度快,实现简单著称。算法真的很简单,TEA算法每一次可以操作64-bit(8-byte),采用128-bit(16-byte)作为key,算法采用迭代的形式,推荐的迭代轮数是64轮,最少32轮。只知道QQ一直用的是16轮TEA。具体关于TEA细节参考google搜索
下面看下Qt下面如何使用
首先新建了一个类util,里面只负责字符串的一些简单转换功能:
#ifndef UTIL_H #define UTIL_H #include <QObject> #include <string> #include <cmath> #include <cstdlib> using std::string; class util : public QObject { typedef unsigned char byte; typedef unsigned long ulong; Q_OBJECT public: explicit util(QObject *parent = 0); inline double logbase(double base, double x) { return log(x)/log(base); } /* 16 *convert int to hex char. 17 *example:10 -> 'A',15 -> 'F' 18 */ char intToHexChar(int x); /* 22 *convert hex char to int. 23 *example:'A' -> 10,'F' -> 15 24 */ int hexCharToInt(char hex); /* 29 *convert a byte array to hex string. 30 *hex string format example:"AF B0 80 7D" 31 */ string bytesToHexString(const byte *in, size_t size); /* 35 *convert a hex string to a byte array. 36 *hex string format example:"AF B0 80 7D" 37 */ size_t hexStringToBytes(const string &str, byte *out); public slots: }; #endif // UTIL_H
#include "util.h" #include <vector> using namespace std; util::util(QObject *parent) : QObject(parent) { } char util::intToHexChar(int x) { static const char HEX[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; return HEX[x]; } int util::hexCharToInt(char hex) { hex = toupper(hex); if (isdigit(hex)) return (hex - '0'); if (isalpha(hex)) return (hex - 'A' + 10); return 0; } string util::bytesToHexString(const byte *in, size_t size) { string str; for (size_t i = 0; i < size; ++i) { int t = in[i]; int a = t / 16; int b = t % 16; str.append(1, intToHexChar(a)); str.append(1, intToHexChar(b)); if (i != size - 1) str.append(1, ' '); } return str; } size_t util::hexStringToBytes(const string &str, byte *out) { vector<string> vec; string::size_type currPos = 0, prevPos = 0; while ((currPos = str.find(' ', prevPos)) != string::npos) { string b(str.substr(prevPos, currPos - prevPos)); vec.push_back(b); prevPos = currPos + 1; } 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(); for (sz_type i = 0; i < size; ++i) { int a = hexCharToInt(vec[i][0]); int b = hexCharToInt(vec[i][1]); out[i] = a * 16 + b; } return size; }
其次tea类负责对字符串进行加解密工作:
#ifndef TEA_H #define TEA_H #include <QObject> #include <windows.h> #include <winsock2.h> #include "util.h" class Tea { public: Tea(const byte *key, int round = 32, 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; } // ulong ntoh(ulong netlong); // ulong hton(ulong hostlong); private: int _round; //iteration round to encrypt or decrypt bool _isNetByte; //whether input bytes come from network byte _key[16]; //encrypt or decrypt key }; #endif // TEA_H
#include "tea.h" #include <cstring> //for memcpy,memset #include <cmath> using namespace std; Tea::Tea(const byte *key, int round /*= 32*/, bool isNetByte /*= false*/) :_round(round) ,_isNetByte(isNetByte) { if (key != 0) memcpy(_key, key, 16); else memset(_key, 0, 16); } Tea::Tea(const Tea &rhs) :_round(rhs._round) ,_isNetByte(rhs._isNetByte) { memcpy(_key, rhs._key, 16); } Tea& Tea::operator=(const Tea &rhs) { if (&rhs != this) { _round = rhs._round; _isNetByte = rhs._isNetByte; memcpy(_key, rhs._key, 16); } 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 ulong y = ntoh(in[0]); register ulong z = ntoh(in[1]); register ulong a = ntoh(k[0]); register ulong b = ntoh(k[1]); register ulong c = ntoh(k[2]); register ulong d = ntoh(k[3]); register ulong delta = 0x9E3779B9; /* (sqrt(5)-1)/2*2^32 */ register int round = _round; register ulong sum = 0; while (round--) { /* basic cycle start */ sum += delta; y += ((z << 4) + a) ^ (z + sum) ^ ((z >> 5) + b); z += ((y << 4) + c) ^ (y + sum) ^ ((y >> 5) + d); } /* end cycle */ out[0] = ntoh(y); out[1] = ntoh(z); } void Tea::decrypt(const ulong *in, ulong *out) { ulong *k = (ulong*)_key; register ulong y = ntoh(in[0]); register ulong z = ntoh(in[1]); register ulong a = ntoh(k[0]); register ulong b = ntoh(k[1]); register ulong c = ntoh(k[2]); register ulong d = ntoh(k[3]); register ulong delta = 0x9E3779B9; /* (sqrt(5)-1)/2*2^32 */ register int round = _round; register ulong sum = 0; if (round == 32) sum = 0xC6EF3720; /* delta << 5*/ else if (round == 16) sum = 0xE3779B90; /* delta << 4*/ else sum = delta *(round); while (round--) { /* basic cycle start */ z -= ((y << 4) + c) ^ (y + sum) ^ ((y >> 5) + d); y -= ((z << 4) + a) ^ (z + sum) ^ ((z >> 5) + b); sum -= delta; } /* end cycle */ out[0] = ntoh(y); out[1] = ntoh(z); } //ulong Tea::ntoh(ulong netlong) //{ // return _isNetByte ? ntohl(netlong) : netlong; //} //ulong Tea::hton(ulong hostlong) //{ // return _isNetByte ? htonl(hostlong) : hostlong; //}
#include "mainwindow.h" #include <QApplication> #include "util.h" #include "tea.h" #include <string> #include <QDebug> #include <iostream> using namespace std; int main(int argc, char *argv[]) { QApplication a(argc, argv); MainWindow w; w.show(); util m_Util; 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"); const int SIZE_IN = 8, SIZE_OUT = 8, SIZE_KEY = 16; byte plain[SIZE_IN], crypt[SIZE_OUT], key[SIZE_KEY]; size_t size_in = m_Util.hexStringToBytes(plainStr, plain); size_t size_key = m_Util.hexStringToBytes(keyStr, key); if (size_in != SIZE_IN || size_key != SIZE_KEY) return -1; std::cout << "Plain: " << m_Util.bytesToHexString(plain, size_in) << endl; cout << "Key : " << m_Util.bytesToHexString(key, size_key) << endl; Tea tea(key, 16, true); tea.encrypt(plain, crypt); cout << "Crypt: " << m_Util.bytesToHexString(crypt, SIZE_OUT) << endl; tea.decrypt(crypt, plain); cout << "Plain: " << m_Util.bytesToHexString(plain, SIZE_IN) << endl; // return 0; return a.exec(); }
win32:LIBS += -lsetupapi \
-lws2_32
只有这样才能编译通过