C + + code implementation of tea encryption algorithm examples

Time:2021-3-1

adoptc++To achieveteaEncryption algorithm, which is compiled into so file and provided to the client in JNI mode, mainly needs to solve the following three problems:

  • Implementation of tea algorithm, which has open source code can be achieved;
  • Solve the padding problem;
  • The key should be confused to prevent the library files generated by compilation from being retrieved conveniently;

For the encryption algorithm of tea, there are mature language codes for reference. The following is the implementation of 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;
}

The key is generated and confused

static uint32_t tea_key[4] = {
 0x34561234, 0x111f3423, 0x34d57910, 0x00989034
};

static uint32_t salt = 0x12031243;
static int tea_round = 16;

//Make simple confusions
static void confuse_key(uint32_t *key) {
 for (int i = 4; i > 0; i--) {
 key[4 - i] = tea_key[i - 1] ^ salt;
 }
}

Finally, the implementation of encryption algorithmpaddingFirst, think about a question, whypaddingWhat about it?

Because tea is a block encryption algorithm, 8 bytes is a block. In the real scene, not all the data to be encrypted are multiples of 8. For example, what should I do if I want to encrypt 15, 35 bytes? Two operations need to be involved here:

  • When encrypting, fill in the part less than 8 bytes until the data to be encrypted is a multiple of 8;
  • When encrypting, the filled part will be removed;

Then, the filled data must have certain rules, and the decrypted person knows that this part of data is filled, not the real original data. The fill section must have a field that represents the fill length. At present, PKCs × 7 filling method is commonly used

Each byte padded at the end is the length of the padding

For example, filling a byte is: 0x01

Fill 5 bytes, that is: 0x05, 0x05, 0x05, 0x05, 0x05;

There is another problem

If the encrypted field is a multiple of 8, do you need padding?

The answer is yes, because if there is no padding, the decryptor may parse the original data as padding (if the last few bits of the original data are exactly the same as some kind of padding code), then the decryption is wrong.

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 is a must, even for tea_ BLOCK_ The integer multiple of size should also be added with banding;
 //If input_ len % TEA_ BLOCK_ Size = 0, which is a multiple of 8, then rest_ len = 0; padding_ len = TEA_ BLOCK_ Add 8 bytes to size;
 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);

 //Adding 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) {
  //The last block must contain padding, which needs to be taken out;
  uint8_t padding_len = ((uint8_t *) (data + 2 * i))[TEA_BLOCK_SIZE - 1];
  out.stripData(padding_len);
 }
 }

 return true;
}

The complete code has been put on GitHub. https://github.com/kumustone/…

summary

This article about C + + code implementation of tea encryption algorithm example detailed explanation of the article introduced here, more related to tea encryption algorithm content, please search developer previous articles or continue to browse the following related articles, hope you can support developer more in the future!