c++代碼實現(xiàn)tea加密算法的實例詳解
通過c++
來實現(xiàn)tea
加密算法,最終編譯成so文件,以JNI的方式提供給客戶端調用,主要需要解決以下三個問題:
- 實現(xiàn)tea算法,這都有開源的代碼可以實現(xiàn);
- 解決padding問題;
- 密鑰做一個混淆,防止編譯生成的庫文件方便的被逆向拿到;
對于tea的加密算法,有成熟的各語言代碼可以借鑒,下面是C++的實現(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; }
生成密鑰,并對密鑰做一定的混淆
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; } }
最后要實現(xiàn)加密算法的padding
,首先思考一個問題,為什么要padding
呢?
因為Tea是塊加密算法,8個字節(jié)為一個塊。而在現(xiàn)實的場景中,不會所有的要加密的數(shù)據(jù)都8的倍數(shù)。比如我要加密15,35等字節(jié)該怎么辦?那么這里需要涉及到兩個操作:
- 加密的時在不足8個字節(jié)的部分進行填充,直至待加密數(shù)據(jù)為8的倍數(shù);
- 加密時將填充的部分去掉;
那么,填充的數(shù)據(jù)是必須要有一定規(guī)則的,解密的人才知道這部分數(shù)據(jù)是填充的,而非真實的原始數(shù)據(jù)。填充部分必須有包含有表示填充長度的字段。目前比較常用的是PKCS#7填充法;即:
末尾填充的每個字節(jié)均為填充長度
比如填充一個字節(jié)就是: 0x01
填充5個字節(jié)就是: 0x05,0x05,0x05,0x05,0x05;
還有一個問題:
如果加密的字段正好為8的倍數(shù),需不需要padding呢?
答案是也需要的,因為如果沒有padding,解密者可能會把原始數(shù)據(jù)當做padding來解析(如果此時原始數(shù)據(jù)的最后幾位恰好與某種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的整數(shù)倍,也要加panding; //如果input_len % TEA_BLOCK_SIZE = 0, 正好是8的倍數(shù),那么rest_len = 0; padding_len = TEA_BLOCK_SIZE 補8個字節(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) { //最后一個block,必定包含padding,需要把padding拿出來; uint8_t padding_len = ((uint8_t *) (data + 2 * i))[TEA_BLOCK_SIZE - 1]; out.stripData(padding_len); } } return true; }
完整的代碼已經放到github上。https://github.com/kumustone/...
總結
到此這篇關于c++代碼實現(xiàn)tea加密算法的實例詳解的文章就介紹到這了,更多相關TEA加密算法內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
C++ 11 std::function和std::bind使用詳解
這篇文章主要介紹了C++ 11 std::function和std::bind使用詳解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2020-02-02C語言實現(xiàn)通用數(shù)據(jù)結構之通用集合(HashSet)
這篇文章主要為大家詳細介紹了C語言實現(xiàn)通用數(shù)據(jù)結構之通用集合,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-11-11