您好,登录后才能下订单哦!
这篇文章主要讲解了c++如何实现tea加密算法,内容清晰明了,对此有兴趣的小伙伴可以学习一下,相信大家阅读完之后会有帮助。
通过c++来实现tea加密算法,最终编译成so文件,以JNI的方式提供给客户端调用,主要需要解决以下三个问题:
对于tea的加密算法,有成熟的各语言代码可以借鉴,下面是C++的实现:
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;
}生成密钥,并对密钥做一定的混淆
static uint32_t tea_key[4] = {
0x34561234, 0x111f3423, 0x34d57910, 0x00989034
};
static uint32_t salt = 0x12031243;
static int tea_round = 16;
//做简单的混淆
static void confuse_key(uint32_t *key) {
for (int i = 4; i > 0; i--) {
key[4 - i] = tea_key[i - 1] ^ salt;
}
}最后要实现加密算法的padding,首先思考一个问题,为什么要padding呢?
因为Tea是块加密算法,8个字节为一个块。而在现实的场景中,不会所有的要加密的数据都8的倍数。比如我要加密15,35等字节该怎么办?那么这里需要涉及到两个操作:
那么,填充的数据是必须要有一定规则的,解密的人才知道这部分数据是填充的,而非真实的原始数据。填充部分必须有包含有表示填充长度的字段。目前比较常用的是PKCS#7填充法;即:
末尾填充的每个字节均为填充长度
比如填充一个字节就是: 0x01
填充5个字节就是: 0x05,0x05,0x05,0x05,0x05;
还有一个问题:
如果加密的字段正好为8的倍数,需不需要padding呢?
答案是也需要的,因为如果没有padding,解密者可能会把原始数据当做padding来解析(如果此时原始数据的最后几位恰好与某种padding编码相同),那么就解密出错了。
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的整数倍,也要加panding;
//如果input_len % TEA_BLOCK_SIZE = 0, 正好是8的倍数,那么rest_len = 0; padding_len = TEA_BLOCK_SIZE 补8个字节;
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) {
//最后一个block,必定包含padding,需要把padding拿出来;
uint8_t padding_len = ((uint8_t *) (data + 2 * i))[TEA_BLOCK_SIZE - 1];
out.stripData(padding_len);
}
}
return true;
}看完上述内容,是不是对c++如何实现tea加密算法有进一步的了解,如果还想学习更多内容,欢迎关注亿速云行业资讯频道。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。