TEA(Tiny Encryption Algorithm)是一种小型的对称加密解密算法,最初是由剑桥计算机实验室的 David Wheeler 和 Roger Needham 在 1994 年设计。采用128位密钥,以8字节(64位)对数据分块进行加密 / 解密。TEA特点是速度快、效率高,实现也非常简单。
  TEA出现后针对它的攻击也不断出现,在被发现存在缺陷后,TEA也发展出几个版本,分别是XTEA、Block TEA和XXTEA。XTEA 跟 TEA 使用了相同的简单运算,但它采用了截然不同的顺序,为了阻止密钥表攻击,四个子密钥(在加密过程中,原 128 位的密钥被拆分为 4 个 32 位的子密钥)采用了一种不太正规的方式进行混合,但速度更慢了。Block TEA 是XTEA算法的变种,它可以对 32 位大小任意倍数的变量块进行操作。该算法将 XTEA 轮循函数依次应用于块中的每个字,并且将它附加于它的邻字。该操作重复多少轮依赖于块的大小,但至少需要 6 轮。该方法的优势在于它无需操作模式(CBC,OFB,CFB 等),密钥可直接用于信息。对于长的信息它可能比 XTEA 更有效率。
在 1998 年,Markku-Juhani Saarinen 给出了一个可有效攻击 Block TEA 算法的代码,但之后很快 David J. Wheeler 和 Roger M. Needham 就给出了 Block TEA 算法的修订版,这个算法被称为 XXTEA。XXTEA 使用跟 Block TEA 相似的结构,但在处理块中每个字时利用了相邻字。它利用一个更复杂的 MX 函数代替了 XTEA 轮循函数。
XXTEA 算法很安全,而且非常快速,非常适合应用于 Web 及嵌入式系统开发中。 但名气不大,采用的人比较少。我们在开发 iOS 系统程序时,由于大量的设定数据都是采用明文格式进行保存,容易被人分析修改。如现在常见的 iOS 非越狱机器上的内购应用破解,游戏数值修改等等。所以我们考虑利用XXTEA来对这些明文数据进行加密,来提高安全性。
  英文 Wiki 上面提供了 XXTEA 的 C 语言实现,代码非常简单。

  1. #define MX (z>>5^y<<2) + (y>>3^z<<4)^(sum^y) + (k[p&3^e]^z);
  2.  
  3. long btea(long* v, long n, long* k) {
  4. unsigned ], y=v[], sum=, e, DELTA=0x9e3779b9;
  5. long p, q ;
  6. ) { /* Coding Part */
  7. q = + /n;
  8. ) {
  9. sum += DELTA;
  10. e = (sum >> ) & ;
  11. ; p<n-; p++) y = v[p+], z = v[p] += MX;
  12. y = v[];
  13. z = v[n-] += MX;
  14. }
  15. ;
  16. } ) { /* Decoding Part */
  17. n = -n;
  18. q = + /n;
  19. sum = q*DELTA ;
  20. ) {
  21. e = (sum >> ) & ;
  22. ; p>; p--) z = v[p-], y = v[p] -= MX;
  23. z = v[n-];
  24. y = v[] -= MX;
  25. sum -= DELTA;
  26. }
  27. ;
  28. }
  29. ;
  30. }

  函数把输入的数据当成一个整型数组 long* v ,其长度为 long n,加密采用的密钥也由数组传入long* k。由于要求传入的数据必须是整型对齐的,而我们平时应用中的数据长度不定。而且加密解密都在一个函数内进行操作,以长度 n 的值为正或负来进行区分也容易忽略,所以对它进行一下封装。作成单独的加密和解密函数

  1. size_t XXTEAEncode(const unsigned char * pInputBuffer,
  2. unsigned char * pOutputBuffer,
  3. size_t nLength,
  4. const_uint_ptr pUserDefineKey)
  5. {
  6. size_t nResult = ;
  7. )
  8. {
  9. nResult = nLength / XXTEA_ALIGNMENT_BYTES +
  10. (nLength % XXTEA_ALIGNMENT_BYTES ? : );
  11. memset(pOutputBuffer, , nResult * XXTEA_ALIGNMENT_BYTES);
  12. memcpy(pOutputBuffer, pInputBuffer, nLength);
  13. btea((uint32_t *)pOutputBuffer, nResult * , (uint32_t *)pUserDefineKey);
  14. nResult *= XXTEA_ALIGNMENT_BYTES;
  15. }
  16. return nResult;
  17. }
  18.  
  19. bool XXTEADecode(const unsigned char * pInputBuffer,
  20. unsigned char * pOutputBuffer,
  21. size_t nLength,
  22. const_uint_ptr pUserDefineKey)
  23. {
  24. if(nLength %
  25. return false;
  26.  
  27. bool result = false;
  28. )
  29. {
  30. ;
  31. memset(pOutputBuffer, , nLength);
  32. memcpy(pOutputBuffer, pInputBuffer, nLength);
  33. btea((uint32_t *)pOutputBuffer, -nSize, (uint32_t *)pUserDefineKey);
  34. result = true;
  35. }
  36. return result;
  37. }

XXTEAEncode为加密函数,XXTEADecode为解密函数,他们的输入参数相同,源数据指针pInputBuffer,输出缓冲区指针pOutputBuffer,源数据长度nLength,和密钥数组pUserDefineKey。这里输出缓冲区的指针需要由调用者预先分配好,但是究竟需要多少内存呢?解密函数比较容易解决,因为解密后的数据肯定不会超过源数据长度,但是加密的时候由于需要将数据设置为整型对齐,数据可能长于输入数据长度。我们模仿 Windows API 的做法,修改一下加密函数,在输入参数中如果输出缓冲区指针为空,返回需要的buffer长度:

  1. size_t XXTEAEncode(const unsigned char * pInputBuffer,
  2. unsigned char * pOutputBuffer,
  3. size_t nLength,
  4. const_uint_ptr pUserDefineKey)
  5. {
  6. size_t nResult = ;
  7. )
  8. {
  9. nResult = nLength / XXTEA_ALIGNMENT_BYTES +
  10. (nLength % XXTEA_ALIGNMENT_BYTES ? : );
  11. memset(pOutputBuffer, , nResult * XXTEA_ALIGNMENT_BYTES);
  12. memcpy(pOutputBuffer, pInputBuffer, nLength);
  13. btea((uint32_t *)pOutputBuffer, nResult * , (uint32_t *)pUserDefineKey);
  14. nResult *= XXTEA_ALIGNMENT_BYTES;
  15. }
  16. )
  17. nResult = ((nLength / XXTEA_ALIGNMENT_BYTES) +
  18. (nLength % XXTEA_ALIGNMENT_BYTES ? : )) * XXTEA_ALIGNMENT_BYTES;
  19.  
  20. return nResult;
  21. }

现在我们就可以通过加密函数来取得需要的 buffer 长度并且分配好内存,然后进行加密处理了。
来测试一下。首先声明一个字符串 NSString stringTest = @”Hello XXTEA!”;  写下这个字符串之后又想到一个问题。iOS系统中的字符是采用UTF-16编码格式,也就是说所有的字符都是双字节,和平常 C 语言下的 ANSI 字符不同,虽然一样可以取得缓冲区指针进行加密,但是在iOS下我们需要处理的各种设定数据基本都是英文字符的文本,对于一个设置文件来说比ANSI字符多了一倍的空间,我们还是转换一下让英文字符恢复到8位编码。查资料可以发现iOS系统不支持ANSI格式的双字节字符编码,我们选用UTF-8来兼容单、双字节字符,同时节省空间。

  1. NSString * testString = @"Hello XXTEA!";
  2.  
  3. ] = {0x12345678, 0x734a67fc, 0xe367a642, 0x78432562};
  4.  
  5. int nSize = XXTEAEncode((const unsigned char *)[testString cStringUsingEncoding:NSUTF8StringEncoding], NULL, testString.length, key);
  6.  
  7. char * outBuffer = (char *)malloc(nSize);
  8. XXTEAEncode((const unsigned char *)[testString cStringUsingEncoding:NSUTF8StringEncoding], (unsigned char *)outBuffer, ,nSize, key);
  9.  
  10. );
  11. memset(formatBuffer, , );
  12. HexToString((const char *)outBuffer, nSize, formatBuffer);
  13. printf("%s\n\n", formatBuffer);
  14. free(formatBuffer);
  15. free(outBuffer);

运行上面的代码得到输出结果:2F49EF03665D18EF294E29A46AE17F7E 。我们再对这串字符进行下解密处理来验证是否可以还原。

  1. char * testData = "2F49EF03665D18EF294E29A46AE17F7E";
  2. char * hexData = (char *)malloc(strlen(testData));
  3. char * decryptBuffer = (char *)malloc(strlen(testData));
  4. memset(hexData, , strlen(testData));
  5. memset(decryptBuffer, , strlen(testData));
  6. int nSize = StringToHex((const char *)testData, hexData);
  7. XXTEADecode((const unsigned char *)hexData, (unsigned char *)decryptBuffer, nSize, key);
  8. NSString * decodeString = [NSString stringWithCString:decryptBuffer encoding:NSUTF8StringEncoding];
  9. NSLog(@"%@", decodeString);
  10. free(decryptBuffer);
  11. free(hexData);

在Xcode的Debug窗口中看到输出信息:test[4559:f803] Hello XXTEA! 。解密完成。现在我们可以用XXTEA来处理明文文件,不会再被轻易篡改。

利用TEA算法进行数据加密的更多相关文章

  1. 【搬运】Tea算法Java实现工具类

    最近在做数据加密,目标是实现平台app的数据安全性,所以准备使用AES+Base64进行加密,适逢一个特长的json串AES加密不了,于是在谷歌了各种算法,判断是否合用,参见 各种加密算法比较 一文中 ...

  2. 【常见加密方法】Base64编码&Tea算法简介

    Base64编码 [Base64编码是什么] Base64是一种基于64个可打印字符来表示二进制数据的表示方法. ——维基百科 Base64,顾名思义,是基于64种可视字符的编码方式.这64种符号由A ...

  3. 利用Manacher算法寻找字符串中的最长回文序列(palindrome)

    寻找字符串中的最长回文序列和所有回文序列(正向和反向一样的序列,如aba,abba等)算是挺早以前提出的算法问题了,最近再刷Leetcode算法题的时候遇到了一个(题目),所以就顺便写下. 如果用正反 ...

  4. 在opencv3中实现机器学习算法之:利用最近邻算法(knn)实现手写数字分类

    手写数字digits分类,这可是深度学习算法的入门练习.而且还有专门的手写数字MINIST库.opencv提供了一张手写数字图片给我们,先来看看 这是一张密密麻麻的手写数字图:图片大小为1000*20 ...

  5. 利用Apriori算法对交通路况的研究

    首先简单描述一下Apriori算法:Apriori算法分为频繁项集的产生和规则的产生. Apriori算法频繁项集的产生: 令ck为候选k-项集的集合,而Fk为频繁k-项集的集合. 1.首先通过单遍扫 ...

  6. TEA算法

    我们要讨论的最后一个分组密码加密算法是TEA(Tiny Encryption Algorithm).到目前为止,我们在前面所呈现的连线图可能会使你得出如下结论:分组密码加密算法必须是复杂的.TEA却能 ...

  7. opencv利用hough概率变换拟合得到直线后,利用DDA算法得到直线上的像素点坐标

    图片霍夫变换拟合得到直线后,怎样获得直线上的像素点坐标? 这是我今天在图像处理学习中遇到的问题,霍夫变换采用的概率霍夫变换,所以拟合得到的直线信息其实是直线的两个端点的坐标,这样一个比较直接的思路就是 ...

  8. SA:利用SA算法解决TSP(数据是14个虚拟城市的横纵坐标)问题——Jason niu

    %SA:利用SA算法解决TSP(数据是14个虚拟城市的横纵坐标)问题——Jason niu X = [16.4700 96.1000 16.4700 94.4400 20.0900 92.5400 2 ...

  9. 实战--利用Lloyd算法进行酵母基因表达数据的聚类分析

    背景:酵母会在一定的时期发生diauxic shift,有一些基因的表达上升,有一些基因表达被抑制,通过聚类算法,将基因表达的变化模式聚成6类. ORF Name R1.Ratio R2.Ratio ...

随机推荐

  1. 实现View弹性滑动例子

    弹性滑动原理 将一次大的滑动非为若干次小的滑动,并在一个时间段内完成.有一种顺畅的感觉更-好的用户体验 实现方式很多种,包括用Scroller.动画.延时策略. 使用Handler实现弹性滑动 效果可 ...

  2. C#微信公众号开发 -- (五)自定义菜单创建

    公众号中,底部都是有自己定义的功能按钮,通过点击某个按钮来实现指定的业务逻辑操作. 下面就来说说这些按钮是怎样放到微信公众平台的,还是先来看看微信的官方解释: 请注意: 1.自定义菜单最多包括3个一级 ...

  3. store procedure example

    SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO -- ============================================= -- ...

  4. PAT_1072 Gas Station

    1072. Gas Station (30) 时间限制  200 ms 内存限制  32000 kB 代码长度限制  16000 B 判题程序    Standard 作者    CHEN, Yue ...

  5. Visual C++ 打印编程技术-编程基础-获取打印机

    标准方法是用: EnumPrinters() 函数获取 #define PRINTER_ENUM_DEFAULT 0x00000001 #define PRINTER_ENUM_LOCAL 0x000 ...

  6. javascript函数 第14节

    <html> <head> <title>function</title> </head> <body> 1.函数形式<b ...

  7. 14_输出映射2_resultMap

    [resultMap] 如果查询出来的列名和pojo的属性名不一致,通过定义一个resultMap对列名和pojo属性名之间做一个映射列表. 1.定义resultMap,(在UserMapper.xm ...

  8. bzoj3202:[Sdoi2013]项链

    思路:首先考虑如何求珠子个数,一个珠子由a,b,c三个数组成且属于区间[1,a],并满足gcd(a,b,c)=1.由于要求本质相同,对于a,b,c这样的一个无序的数列且满足gcd(a,b,c)=1,设 ...

  9. centos 安装php-fpm , nginx二级域名配置 ,但为什么必须要 域名提供商 哪里解析新的二级域名一下 才能用呢?

    yum -y install php-fpm php-mysql(当然还有其它扩展) /etc/init.d/php-fpm restart (重启php-fpm) /etc/php.ini (php ...

  10. ubuntu基本使用

    sudo nautilus xxx指定目录去打开 这个命令就是以root权限打开一个窗口,来管理文件