溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

c++如何實現tea加密算法

發布時間:2020-08-04 11:23:47 來源:億速云 閱讀:282 作者:小豬 欄目:編程語言

這篇文章主要講解了c++如何實現tea加密算法,內容清晰明了,對此有興趣的小伙伴可以學習一下,相信大家閱讀完之后會有幫助。

通過c++來實現tea加密算法,最終編譯成so文件,以JNI的方式提供給客戶端調用,主要需要解決以下三個問題:

  • 實現tea算法,這都有開源的代碼可以實現;
  • 解決padding問題;
  • 密鑰做一個混淆,防止編譯生成的庫文件方便的被逆向拿到;

對于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) &#63; 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等字節該怎么辦?那么這里需要涉及到兩個操作:

  • 加密的時在不足8個字節的部分進行填充,直至待加密數據為8的倍數;
  • 加密時將填充的部分去掉;

那么,填充的數據是必須要有一定規則的,解密的人才知道這部分數據是填充的,而非真實的原始數據。填充部分必須有包含有表示填充長度的字段。目前比較常用的是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加密算法有進一步的了解,如果還想學習更多內容,歡迎關注億速云行業資訊頻道。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

亚洲午夜精品一区二区_中文无码日韩欧免_久久香蕉精品视频_欧美主播一区二区三区美女