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 语言实现,代码非常简单。

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

  long btea(long* v, long n, long* k) {
    unsigned ], y=v[], sum=, e, DELTA=0x9e3779b9;
    long p, q ;
    ) {          /* Coding Part */
      q =  + /n;
      ) {
        sum += DELTA;
        e = (sum >> ) & ;
        ; p<n-; p++) y = v[p+], z = v[p] += MX;
        y = v[];
        z = v[n-] += MX;
      }
       ;
    } ) {  /* Decoding Part */
      n = -n;
      q =  + /n;
      sum = q*DELTA ;
      ) {
        e = (sum >> ) & ;
        ; p>; p--) z = v[p-], y = v[p] -= MX;
        z = v[n-];
        y = v[] -= MX;
        sum -= DELTA;
      }
      ;
    }
    ;
  }

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

size_t XXTEAEncode(const unsigned char * pInputBuffer,
                                       unsigned char * pOutputBuffer,
                                       size_t nLength,
                                       const_uint_ptr pUserDefineKey)
{
    size_t nResult = ;
    )
    {
        nResult = nLength / XXTEA_ALIGNMENT_BYTES +
                    (nLength % XXTEA_ALIGNMENT_BYTES ?  : );
        memset(pOutputBuffer, , nResult * XXTEA_ALIGNMENT_BYTES);
        memcpy(pOutputBuffer, pInputBuffer, nLength);
        btea((uint32_t *)pOutputBuffer, nResult * , (uint32_t *)pUserDefineKey);
        nResult *= XXTEA_ALIGNMENT_BYTES;
    }
    return nResult;
}

bool XXTEADecode(const unsigned char * pInputBuffer,
                                     unsigned char * pOutputBuffer,
                                     size_t nLength,
                                     const_uint_ptr pUserDefineKey)
{
    if(nLength %
        return false;

    bool result = false;
    )
    {
        ;
        memset(pOutputBuffer, , nLength);
        memcpy(pOutputBuffer, pInputBuffer, nLength);
        btea((uint32_t *)pOutputBuffer, -nSize, (uint32_t *)pUserDefineKey);
        result = true;
    }
    return result;
}

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

size_t XXTEAEncode(const unsigned char * pInputBuffer,
                                       unsigned char * pOutputBuffer,
                                       size_t nLength,
                                       const_uint_ptr pUserDefineKey)
{
    size_t nResult = ;
    )
    {
        nResult = nLength / XXTEA_ALIGNMENT_BYTES +
                    (nLength % XXTEA_ALIGNMENT_BYTES ?  : );
        memset(pOutputBuffer, , nResult * XXTEA_ALIGNMENT_BYTES);
        memcpy(pOutputBuffer, pInputBuffer, nLength);
        btea((uint32_t *)pOutputBuffer, nResult * , (uint32_t *)pUserDefineKey);
        nResult *= XXTEA_ALIGNMENT_BYTES;
    }
    )
        nResult = ((nLength / XXTEA_ALIGNMENT_BYTES) +
                   (nLength % XXTEA_ALIGNMENT_BYTES ?  : )) * XXTEA_ALIGNMENT_BYTES;

    return nResult;
}

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

NSString * testString = @"Hello XXTEA!";

    ] = {0x12345678, 0x734a67fc, 0xe367a642, 0x78432562};

    int nSize = XXTEAEncode((const unsigned char *)[testString cStringUsingEncoding:NSUTF8StringEncoding], NULL, testString.length, key);

    char * outBuffer = (char *)malloc(nSize);
    XXTEAEncode((const unsigned char *)[testString cStringUsingEncoding:NSUTF8StringEncoding], (unsigned char *)outBuffer, ,nSize, key);

    );
    memset(formatBuffer, , );
    HexToString((const char *)outBuffer, nSize, formatBuffer);
    printf("%s\n\n", formatBuffer);
    free(formatBuffer);
    free(outBuffer);

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

char * testData = "2F49EF03665D18EF294E29A46AE17F7E";
    char * hexData = (char *)malloc(strlen(testData));
    char * decryptBuffer = (char *)malloc(strlen(testData));
    memset(hexData, , strlen(testData));
    memset(decryptBuffer, , strlen(testData));
    int nSize = StringToHex((const char *)testData, hexData);
    XXTEADecode((const unsigned char *)hexData, (unsigned char *)decryptBuffer, nSize, key);
    NSString * decodeString = [NSString stringWithCString:decryptBuffer encoding:NSUTF8StringEncoding];
    NSLog(@"%@", decodeString);
    free(decryptBuffer);
    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. Linux理念

    1.小即是美 2.让程序只做好一件事 3.可移植性比效率更重要 4.一切即文件——使用方便而且吧硬件作为文件处理是安全的 5.使用shell脚本来提高效率和可移植性 6.避免使用可定制性低下的用户界面 ...

  2. mysql左外连接,右外连接,全连接

  3. ios Object Encoding and Decoding with NSSecureCoding Protocol

    Object Encoding and Decoding with NSSecureCoding Protocol February 27, 2014 MISC NSCoding is a fanta ...

  4. oracle_11g 不同用户之间的数据迁移

    众所周知,IMP工具的FROMUSER和TOUSER参数可以实现将一个用户的的数据迁移到另外一个用户.同样的功能在IMPPDP工具中如何得以体现呢?答案就是:使用IMPPDP的REMAP_SCHEMA ...

  5. OC加强-day06

    #program mark - 08 NSMutableDictionary的使用 [掌握] "/08 NSMutableDictionary的使用/1_练习 "练习 1.小明的身 ...

  6. C#创建微信自定义菜单

    string posturl = "https://api.weixin.qq.com/cgi-bin/menu/create?access_token=" + access_to ...

  7. iOS afnetworking最新版报错 没有AFHTTPRequestOperationManager类了

    今天开了一个小项目   用的是pod   然后  安装好 Afnetworking之后   发现 AFHTTPRequestOperationManager  这个类没有了  ,百度之后  发现 原来 ...

  8. swift-07-使用for-in 遍历数组

    //for-in /* for 迭代变量 in集合变量 { 使用迭代变量便利所有数据 } */ //遍历数组 var arr = ["a" ,"b" ,&quo ...

  9. UVA 10066 The Twin Towers(LCS)

    Problem B The Twin Towers Input: standard input Output: standard output Once upon a time, in an anci ...

  10. (hdu)5652 India and China Origins 二分+dfs

    题目链接:http://acm.split.hdu.edu.cn/showproblem.php?pid=5652 Problem Description A long time ago there ...