c++代碼實(shí)現(xiàn)tea加密算法的實(shí)例詳解
通過(guò)c++來(lái)實(shí)現(xiàn)tea加密算法,最終編譯成so文件,以JNI的方式提供給客戶(hù)端調(diào)用,主要需要解決以下三個(gè)問(wèn)題:
- 實(shí)現(xiàn)tea算法,這都有開(kāi)源的代碼可以實(shí)現(xiàn);
- 解決padding問(wèn)題;
- 密鑰做一個(gè)混淆,防止編譯生成的庫(kù)文件方便的被逆向拿到;
對(duì)于tea的加密算法,有成熟的各語(yǔ)言代碼可以借鑒,下面是C++的實(shí)現(xiàn):
static void tea_encrypt(uint32_t *v, uint32_t *k) {
uint32_t v0 = v[0], v1 = v[1], sum = 0, i;
uint32_t delta = 0x9e3779b9;
uint32_t k0 = k[0], k1 = k[1], k2 = k[2], k3 = k[3];
for (i = 0; i < tea_round; i++) {
sum += delta;
v0 += ((v1 << 4) + k0) ^ (v1 + sum) ^ ((v1 >> 5) + k1);
v1 += ((v0 << 4) + k2) ^ (v0 + sum) ^ ((v0 >> 5) + k3);
}
v[0] = v0;
v[1] = v1;
}
static void tea_decrypt(uint32_t *v, uint32_t *k) {
uint32_t v0 = v[0], v1 = v[1], sum, i;
sum = (tea_round == 16) ? 0xE3779B90 : 0xC6EF3720;
uint32_t delta = 0x9e3779b9;
uint32_t k0 = k[0], k1 = k[1], k2 = k[2], k3 = k[3];
for (i = 0; i < tea_round; i++) {
v1 -= ((v0 << 4) + k2) ^ (v0 + sum) ^ ((v0 >> 5) + k3);
v0 -= ((v1 << 4) + k0) ^ (v1 + sum) ^ ((v1 >> 5) + k1);
sum -= delta;
}
v[0] = v0;
v[1] = v1;
}
生成密鑰,并對(duì)密鑰做一定的混淆
static uint32_t tea_key[4] = {
0x34561234, 0x111f3423, 0x34d57910, 0x00989034
};
static uint32_t salt = 0x12031243;
static int tea_round = 16;
//做簡(jiǎn)單的混淆
static void confuse_key(uint32_t *key) {
for (int i = 4; i > 0; i--) {
key[4 - i] = tea_key[i - 1] ^ salt;
}
}
最后要實(shí)現(xiàn)加密算法的padding,首先思考一個(gè)問(wèn)題,為什么要padding呢?
因?yàn)門(mén)ea是塊加密算法,8個(gè)字節(jié)為一個(gè)塊。而在現(xiàn)實(shí)的場(chǎng)景中,不會(huì)所有的要加密的數(shù)據(jù)都8的倍數(shù)。比如我要加密15,35等字節(jié)該怎么辦?那么這里需要涉及到兩個(gè)操作:
- 加密的時(shí)在不足8個(gè)字節(jié)的部分進(jìn)行填充,直至待加密數(shù)據(jù)為8的倍數(shù);
- 加密時(shí)將填充的部分去掉;
那么,填充的數(shù)據(jù)是必須要有一定規(guī)則的,解密的人才知道這部分?jǐn)?shù)據(jù)是填充的,而非真實(shí)的原始數(shù)據(jù)。填充部分必須有包含有表示填充長(zhǎng)度的字段。目前比較常用的是PKCS#7填充法;即:
末尾填充的每個(gè)字節(jié)均為填充長(zhǎng)度
比如填充一個(gè)字節(jié)就是: 0x01
填充5個(gè)字節(jié)就是: 0x05,0x05,0x05,0x05,0x05;
還有一個(gè)問(wèn)題:
如果加密的字段正好為8的倍數(shù),需不需要padding呢?
答案是也需要的,因?yàn)槿绻麤](méi)有padding,解密者可能會(huì)把原始數(shù)據(jù)當(dāng)做padding來(lái)解析(如果此時(shí)原始數(shù)據(jù)的最后幾位恰好與某種padding編碼相同),那么就解密出錯(cuò)了。
bool encrypt(const void *input, int input_len, DataBuffer &out) {
if (input == NULL || input_len <= 0)
return false;
unsigned int rest_len = input_len % TEA_BLOCK_SIZE;
//padding是必須帶的,即便是TEA_BLOCK_SIZE的整數(shù)倍,也要加panding;
//如果input_len % TEA_BLOCK_SIZE = 0, 正好是8的倍數(shù),那么rest_len = 0; padding_len = TEA_BLOCK_SIZE 補(bǔ)8個(gè)字節(jié);
unsigned int padding_len = TEA_BLOCK_SIZE - rest_len;
int blocks = (input_len + padding_len) / TEA_BLOCK_SIZE;
out.expand(blocks * TEA_BLOCK_SIZE);
out.writeBytes((const void *) input, input_len);
//放入padding
for (int i = 0; i < padding_len; i++) {
out.writeInt8(padding_len);
}
uint32_t key[4];
confuse_key(key);
uint32_t *data = (uint32_t *) out.getData();
for (int i = 0; i < blocks; i++) {
tea_encrypt((uint32_t *) (data + 2 * i), key);
}
return true;
}
bool decrypt(const void *input, int input_len, DataBuffer &out) {
if (input == NULL || input_len < 8)
return false;
int blocks = input_len / 8;
out.expand(blocks * 8);
out.writeBytes((const void *) input, blocks * 8);
uint32_t key[4];
confuse_key(key);
uint32_t *data = (uint32_t *) out.getData();
for (int i = 0; i < blocks; i++) {
tea_decrypt((uint32_t *) (data + 2 * i), key);
if (i == blocks - 1) {
//最后一個(gè)block,必定包含padding,需要把padding拿出來(lái);
uint8_t padding_len = ((uint8_t *) (data + 2 * i))[TEA_BLOCK_SIZE - 1];
out.stripData(padding_len);
}
}
return true;
}
完整的代碼已經(jīng)放到github上。https://github.com/kumustone/...
總結(jié)
到此這篇關(guān)于c++代碼實(shí)現(xiàn)tea加密算法的實(shí)例詳解的文章就介紹到這了,更多相關(guān)TEA加密算法內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
最新VScode C/C++ 環(huán)境配置的詳細(xì)教程
這篇文章主要介紹了最新VScode C/C++ 環(huán)境配置的詳細(xì)教程,本文通過(guò)圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-11-11
使用C++將yolov8 onnx格式轉(zhuǎn)化為tensorrt格式
這篇文章主要為大家詳細(xì)介紹了如何使用C++將yolov8 onnx格式轉(zhuǎn)化為tensorrt格式,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解一下2024-11-11
C和MFC巧妙獲取外網(wǎng)IP的兩種實(shí)現(xiàn)方法
這篇文章主要介紹了C和MFC巧妙獲取外網(wǎng)IP的兩種實(shí)現(xiàn)方法,功能非常的實(shí)用,需要的朋友可以參考下2014-07-07
解決scanf_s輸入%d%c%d格式錯(cuò)誤的問(wèn)題
這篇文章主要介紹了解決scanf_s輸入%d%c%d格式錯(cuò)誤的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-12-12
簡(jiǎn)單了解C++語(yǔ)言中的二元運(yùn)算符和賦值運(yùn)算符
這篇文章主要介紹了C++語(yǔ)言中的二元運(yùn)算符和賦值運(yùn)算符,文中列出了可重載的運(yùn)算符列表,需要的朋友可以參考下2016-01-01

