TEA -- Tiny Encryption Algorithm

http://codereview.stackexchange.com/questions/2050/tiny-encryption-algorithm-tea-for-arbitrary-sized-data#ifndef __TEA.H__
#define __TEA.H__

#include <stdint.h>

void encrypt (uint32_t* v, uint32_t* k);
void decrypt (uint32_t* v, uint32_t* k);
void encryptBlock(uint8_t * data, uint32_t * len, uint32_t * key);
void decryptBlock(uint8_t * data, uint32_t * len, uint32_t * key);

#endif
#include "tea.h"
/* encryptBlock
 *   Encrypts byte array data of length len with key key using TEA
 * Arguments:
 *   data - pointer to 8 bit data array to be encrypted - SEE NOTES
 *   len - length of array
 *   key - Pointer to four integer array (16 bytes) holding TEA key
 * Returns:
 *   data - encrypted data held here
 *   len - size of the new data array
 * Side effects:
 *   Modifies data and len
 * NOTES:
 * data size must be equal to or larger than ((len + 7) / 8) * 8 + 8
 * TEA encrypts in 8 byte blocks, so it must include enough space to
 * hold the entire data to pad out to an 8 byte boundary, plus another
 * 8 bytes at the end to give the length to the decrypt algorithm.
 *
 *  - Shortcut - make sure that data is at least len + 15 bytes in size.
 */
void encryptBlock(uint8_t * data, uint32_t * len, uint32_t * key)
{
   uint32_t blocks, i;
   uint32_t * data32;

   // treat the data as 32 bit unsigned integers
   data32 = (uint32_t *) data;

   // Find the number of 8 byte blocks, add one for the length
   blocks = (((*len) + 7) / 8) + 1;

   // Set the last block to the original data length
   data32[(blocks*2) - 1] = *len;

   // Set the encrypted data length
   *len = blocks * 8;

   for(i = 0; i< blocks; i++)
   {
      encrypt(&data32[i*2], key);
   }
}

/* decryptBlock
 *   Decrypts byte array data of length len with key key using TEA
 * Arguments:
 *   data - pointer to 8 bit data array to be decrypted - SEE NOTES
 *   len - length of array
 *   key - Pointer to four integer array (16 bytes) holding TEA key
 * Returns:
 *   data - decrypted data held here
 *   len - size of the new data array
 * Side effects:
 *   Modifies data and len
 * NOTES:
 *   None
 */
void decryptBlock(uint8_t * data, uint32_t * len, uint32_t * key)
{
   uint32_t blocks, i;
   uint32_t * data32;

   // treat the data as 32 bit unsigned integers
   data32 = (uint32_t *) data;

   // Find the number of 8 byte blocks
   blocks = (*len)/8;

   for(i = 0; i< blocks; i++)
   {
      decrypt(&data32[i*2], key);
   }

   // Return the length of the original data
   *len = data32[(blocks*2) - 1];
}

/* encrypt
 *   Encrypt 64 bits with a 128 bit key using TEA
 *   From http://en.wikipedia.org/wiki/Tiny_Encryption_Algorithm
 * Arguments:
 *   v - array of two 32 bit uints to be encoded in place
 *   k - array of four 32 bit uints to act as key
 * Returns:
 *   v - encrypted result
 * Side effects:
 *   None
 */
void encrypt (uint32_t* v, uint32_t* k) {
    uint32_t v0=v[0], v1=v[1], sum=0, i;           /* set up */
    uint32_t delta=0x9e3779b9;                     /* a key schedule constant */
    uint32_t k0=k[0], k1=k[1], k2=k[2], k3=k[3];   /* cache key */
    for (i=0; i < 32; i++) {                       /* basic cycle start */
        sum += delta;
        v0 += ((v1<<4) + k0) ^ (v1 + sum) ^ ((v1>>5) + k1);
        v1 += ((v0<<4) + k2) ^ (v0 + sum) ^ ((v0>>5) + k3);
    }                                              /* end cycle */
    v[0]=v0; v[1]=v1;
}

/* decrypt
 *   Decrypt 64 bits with a 128 bit key using TEA
 *   From http://en.wikipedia.org/wiki/Tiny_Encryption_Algorithm
 * Arguments:
 *   v - array of two 32 bit uints to be decoded in place
 *   k - array of four 32 bit uints to act as key
 * Returns:
 *   v - decrypted result
 * Side effects:
 *   None
 */
void decrypt (uint32_t* v, uint32_t* k) {
    uint32_t v0=v[0], v1=v[1], sum=0xC6EF3720, i;  /* set up */
    uint32_t delta=0x9e3779b9;                     /* a key schedule constant */
    uint32_t k0=k[0], k1=k[1], k2=k[2], k3=k[3];   /* cache key */
    for (i=0; i<32; i++) {                         /* basic cycle start */
        v1 -= ((v0<<4) + k2) ^ (v0 + sum) ^ ((v0>>5) + k3);
        v0 -= ((v1<<4) + k0) ^ (v1 + sum) ^ ((v1>>5) + k1);
        sum -= delta;
    }                                              /* end cycle */
    v[0]=v0; v[1]=v1;
}

Issues so far:

Coding

  • Using magic numbers in encrypt and decrypt routines - use #defines instead - Kyle
  • If the 64 bit encoding functions aren‘t used outside this module, their prototypes should be in the code, not header - Simon
  • Add sanity checking to input - Rob
  • Require that input len is a multiple of 8 bytes - making a requirement we can‘t enforce or check is a recipe for corruption - Rob

Style

  • Using K&R brace style in some places, ANSI in others - consistency - Simon
  • The long descriptive comment is more useful for the end user if it‘s in the header file (Header for usage, code for implementation) - Rob

Someone asked for the implementation I indicated in the original post, so here it is. Note that I‘ve not cleaned it up for presentation.

To decode a file use decode inputfilename outputfilename. To encode a file use decode inputfilename outputfilename e. ANSI C implementation, so it should work anywhere, although the algorithm itself might be endian dependant.

THE DECRYPTED FILE WILL NOT EXACTLY MATCH THE ORIGINAL FILE. This particular implementation leaves a number of null bytes on the end of the decrypted file that were not present in the original. For my application this was acceptable and simplified my particular usage, but you are likely going to need to modify this for your use.

It uses a fixed key on line 4.

#include <stdio.h>

typedef unsigned long uint32_t;
const uint32_t TEAKey[4] = {0x95a8882c, 0x9d2cc113, 0x815aa0cd, 0xa1c489f7};

void encrypt (uint32_t* v, const uint32_t* k);
void decrypt (uint32_t* v, const uint32_t* k);

void btea(uint32_t *v, int n, uint32_t const k[4]);

void simpleencrypt(unsigned char * buffer);
void simpledecrypt(unsigned char * buffer);

int main(int argc, char **argv)
{
   FILE *fpin, *fpout;
   int bytecount;
   unsigned char buffer[9], bufferin[9], bufferout[9];
   int i;

   if(argc < 3)
   {
      printf("Use: %s [filenameinput] [filenameoutput]\n", argv[0]);
      return 0;
   }

   if( (fpin = fopen(argv[1], "rb")) == NULL)
   {
      printf("Problem opening input file %s.\n", argv[1]);
      return 0;
   }

   if( (fpout = fopen(argv[2], "wb")) == NULL)
   {
      printf("Problem opening output file %s.\n", argv[2]);
      return 0;
   }

   bytecount = 0;

   while(fread(buffer, 1, 8, fpin) == 8)
   {
      if(argc>3)
      {
            for(i=0;i<8;i++)
            {
                bufferin[i] = buffer[i];
            }

          simpleencrypt(buffer);

            for(i=0;i<8;i++)
            {
                bufferout[i] = buffer[i];
            }
            simpledecrypt(bufferout);
            for(i=0;i<8;i++)
            {
                if(bufferin[i] != bufferout[i])
                {
                    printf("Internal decode test failed.\n");
                }
            }

      }
      else
      {
          simpledecrypt(buffer);
      }
      fwrite(buffer, 1, 8, fpout);
      bytecount+=8;
   }

   if (!feof(fpin))
   {
       printf("Unexpected input file error encountered.\n");
   }

   fclose(fpin);
   fclose(fpout);
   printf("%s complete, %i bytes total\n",((argc>3) ? "Encrypt" : "Decrypt"), bytecount);
   return 0;
}

void simpleencrypt(unsigned char * buffer)
{
    uint32_t datablock[2];

    datablock[0] = (buffer[0] << 24) | (buffer[1] << 16)  | (buffer[2] << 8) | (buffer[3]);
    datablock[1] = (buffer[4] << 24) | (buffer[5] << 16)  | (buffer[6] << 8) | (buffer[7]);

    encrypt (datablock, TEAKey);

    buffer[0] = (char) ((datablock[0] >> 24) & 0xFF);
    buffer[1] = (char) ((datablock[0] >> 16) & 0xFF);
    buffer[2] = (char) ((datablock[0] >> 8) & 0xFF);
    buffer[3] = (char) ((datablock[0]) & 0xFF);
    buffer[4] = (char) ((datablock[1] >> 24) & 0xFF);
    buffer[5] = (char) ((datablock[1] >> 16) & 0xFF);
    buffer[6] = (char) ((datablock[1] >> 8) & 0xFF);
    buffer[7] = (char) ((datablock[1]) & 0xFF);
}

void simpledecrypt(unsigned char * buffer)
{
    uint32_t datablock[2];

    datablock[0] = (buffer[0] << 24) | (buffer[1] << 16)  | (buffer[2] << 8) | (buffer[3]);
    datablock[1] = (buffer[4] << 24) | (buffer[5] << 16)  | (buffer[6] << 8) | (buffer[7]);

    decrypt (datablock, TEAKey);

    buffer[0] = (char) ((datablock[0] >> 24) & 0xFF);
    buffer[1] = (char) ((datablock[0] >> 16) & 0xFF);
    buffer[2] = (char) ((datablock[0] >> 8) & 0xFF);
    buffer[3] = (char) ((datablock[0]) & 0xFF);
    buffer[4] = (char) ((datablock[1] >> 24) & 0xFF);
    buffer[5] = (char) ((datablock[1] >> 16) & 0xFF);
    buffer[6] = (char) ((datablock[1] >> 8) & 0xFF);
    buffer[7] = (char) ((datablock[1]) & 0xFF);
}

/* encrypt
 *   Encrypt 64 bits with a 128 bit key using TEA
 *   From http://en.wikipedia.org/wiki/Tiny_Encryption_Algorithm
 * Arguments:
 *   v - array of two 32 bit uints to be encoded in place
 *   k - array of four 32 bit uints to act as key
 * Returns:
 *   v - encrypted result
 * Side effects:
 *   None
 */
void encrypt (uint32_t* v, const uint32_t* k) {
    uint32_t v0=v[0], v1=v[1], sum=0, i;           /* set up */
    uint32_t delta=0x9e3779b9;                     /* a key schedule constant */
    uint32_t k0=k[0], k1=k[1], k2=k[2], k3=k[3];   /* cache key */
    for (i=0; i < 32; i++) {                       /* basic cycle start */
        sum += delta;
        v0 += ((v1<<4) + k0) ^ (v1 + sum) ^ ((v1>>5) + k1);
        v1 += ((v0<<4) + k2) ^ (v0 + sum) ^ ((v0>>5) + k3);
    }                                              /* end cycle */
    v[0]=v0; v[1]=v1;
}

/* decrypt
 *   Decrypt 64 bits with a 128 bit key using TEA
 *   From http://en.wikipedia.org/wiki/Tiny_Encryption_Algorithm
 * Arguments:
 *   v - array of two 32 bit uints to be decoded in place
 *   k - array of four 32 bit uints to act as key
 * Returns:
 *   v - decrypted result
 * Side effects:
 *   None
 */
void decrypt (uint32_t* v, const uint32_t* k) {
    uint32_t v0=v[0], v1=v[1], sum=0xC6EF3720, i;  /* set up */
    uint32_t delta=0x9e3779b9;                     /* a key schedule constant */
    uint32_t k0=k[0], k1=k[1], k2=k[2], k3=k[3];   /* cache key */
    for (i=0; i<32; i++) {                         /* basic cycle start */
        v1 -= ((v0<<4) + k2) ^ (v0 + sum) ^ ((v0>>5) + k3);
        v0 -= ((v1<<4) + k0) ^ (v1 + sum) ^ ((v1>>5) + k1);
        sum -= delta;
    }                                              /* end cycle */
    v[0]=v0; v[1]=v1;
}

#define DELTA 0x9e3779b9
  #define MX ((z>>5^y<<2) + (y>>3^z<<4)) ^ ((sum^y) + (k[(p&3)^e] ^ z));

  void btea(uint32_t *v, int n, uint32_t const k[4]) {
    uint32_t y, z, sum;
    unsigned p, rounds, e;
    if (n > 1) {          /* Coding Part */
      rounds = 6 + 52/n;
      sum = 0;
      z = v[n-1];
      do {
        sum += DELTA;
        e = (sum >> 2) & 3;
        for (p=0; p<n-1; p++)
          y = v[p+1], z = v[p] += MX;
        y = v[0];
        z = v[n-1] += MX;
      } while (--rounds);
    } else if (n < -1) {  /* Decoding Part */
      n = -n;
      rounds = 6 + 52/n;
      sum = rounds*DELTA;
      y = v[0];
      do {
        e = (sum >> 2) & 3;
        for (p=n-1; p>0; p--)
          z = v[p-1], y = v[p] -= MX;
        z = v[n-1];
        y = v[0] -= MX;
      } while ((sum -= DELTA) != 0);
    }
  }
时间: 2024-10-09 20:31:03

TEA -- Tiny Encryption Algorithm的相关文章

XShell 无法匹配的outgoing encryption算法 ,No matching outgoing encryption algorithm found

在链接的属性(SSH -> 安全性) 的加密算法列表中选择 aes256-ctr, mac加密列表中选择hmac-sha2-256,保存即可 To enable hmac-sha2-256 and aes256-ctr go to the SSH > Security page in the session properties. Click the Edit button for Encryption and MAC. Make sure everything is selected for

SSL访问提示 no common encryption algorithm

客户端为:redhat6.4 firefox 10.1 服务器端部署环境为:jdk 1.7, tomcat 版本未知 客户端访问服务器时,提示如下错误: 解决办法: 经过测试,由于tomcat的server.xml文件配置需要修改,具体如下: <Connector protocol="org.apache.coyote.http11.Http11NioProtocol" port="8443" maxThreads="200" scheme

数据的加密传输——单片机上实现TEA加密解密算法(转)

源:数据的加密传输——单片机上实现TEA加密解密算法 各位大侠在做数据传输时,有没有考虑过把数据加密起来进行传输,若在串口或者无线中把所要传的数据加密起来,岂不是增加了通信的安全性.常用的加密解密算法比如DES.RSA等,受限于单片机的内存和运算速度,实现起来比较困难,但一种叫TEA的加密算法特别适合单片机使用. TEA(Tiny Encryption Algorithm)是一种简单高效的加密算法,以加密解密速度快,实现简单著称.算法很简单,TEA算法每一次可以操作64-bit(8-byte),

单片机上使用TEA加密通信

本文博客链接:http://blog.csdn.net/jdh99,作者:jdh,转载请注明. 环境: 主机:WIN7 开发环境:MDK4.72 单片机:STM32 说明: 在项目中单片机会与服务器进行网络通讯.需要对通讯加密,我选择了TEA加密算法. 源码: tea.h /********************************************************************* * TEA算法头文件 * (c)copyright 2013,jdh * All R

各种加密算法比较

各种加密算法比较 算法选择:对称加密AES,非对称加密: ECC,消息摘要: MD5,数字签名:DSA 对称加密算法(加解密密钥相同) 名称 密钥长度 运算速度 安全性 资源消耗 DES 56位 较快 低 中 3DES 112位或168位 慢 中 高 AES 128.192.256位 快 高 低 非对称算法(加密密钥和解密密钥不同) 名称 成熟度 安全性(取决于密钥长度) 运算速度 资源消耗 RSA 高 高 慢 高 DSA 高 高 慢 只能用于数字签名 ECC 低 高 快 低(计算量小,存储空间

xxtea---单片机数据加密算法

转:https://www.cnblogs.com/LittleTiger/p/4384741.html 各位大侠在做数据传输时,有没有考虑过把数据加密起来进行传输,若在串口或者无线中把所要传的数据加密起来,岂不是增加了通信的安全性.常用的加密解密算法比如DES.RSA等,受限于单片机的内存和运算速度,实现起来比较困难,但一种叫TEA的加密算法特别适合单片机使用. TEA(Tiny Encryption Algorithm)是一种简单高效的加密算法,以加密解密速度快,实现简单著称.算法很简单,T

TEA encryption with 128bit key

源:TEA encryption with 128bit key If anyone needs some basic encryption in software, here's one solution. This TEA implementation fits within less than 700 bytes. It's based on original TEA. P89LPC901 needs 300ms for 32 iterations. Compiled with "OPTI

简单有效的源码加密算法-TEA和XTEA算法

最近在项目中用到了XTEA源码加密算法,写下来总结一下: TEA(Tiny Encryption Algorithm)是一种小型的对称加密解密算法,支持128位密码,与BlowFish一样TEA每次只能加密/解密8字节数据.TEA特点是速度 快.效率高,实现也非常简单.由于针对TEA的攻击不断出现,所以TEA也发展出几个版本,分别是XTEA.Block TEA和XXTEA. TEA算法实现非常简单,不到20代码,分享一个加强版的TEA算法XTEA算法实现: /******************

TEA,XXTEA介绍,对称加密

总结:在使用加密的时候,我们可以加入随机数,这样相同的明文,每次加密后得到不同的密文,同时可以在密文中加入密文有效期,控制密文的有效时间长度. 针对有的功能扩展使用,很好的思想. TEA对 64 位数据加密的密钥长达 128 位,安全性相当好.其可靠性是通过加密轮数而不是算法的复杂度来保证的.从中可以看到TEA 算法主要运用了移位和异或运算.密钥在加密过程中始终不变. TEA(Tiny Encryption Algorithm)是一种小型的对称加密解密算法,支持128位密码,与BlowFish一