COPY的资料:
微型加密算法(TEA)及其相关变种(XTEA,Block TEA,XXTEA) 都是分组加密算法,它们很容易被描述,实现也很简单(典型的几行代码)。
TEA 算法最初是由剑桥计算机实验室的 David Wheeler 和 Roger Needham 在 1994 年设计的。该算法使用 128 位的密钥为 64 位的信息块进行加密,它需要进行 64 轮迭代,尽管作者认为 32 轮已经足够了。该算法使用了一个神秘常数δ作为倍数,它来源于黄金比率,以保证每一轮加密都不相同。但δ的精确值似乎并不重要,这里 TEA 把它定义为 δ=「(√5 - 1)231」(也就是程序中的 0×9E3779B9)。之后 TEA 算法被发现存在缺陷,作为回应,设计者提出了一个 TEA 的升级版本——XTEA(有时也被称为“tean”)。XTEA 跟 TEA 使用了相同的简单运算,但它采用了截然不同的顺序,为了阻止密钥表攻击,四个子密钥(在加密过程中,原 128 位的密钥被拆分为 4 个 32 位的子密钥)采用了一种不太正规的方式进行混合,但速度更慢了。
在跟描述 XTEA 算法的同一份报告中,还介绍了另外一种被称为 Block TEA 算法的变种,它可以对 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 轮循函数,MX 使用 2 个输入量。
XXTEA算法在加密、解密时需要提供给算法一个自己设计的密码本,此密码本必须严密保护,不可对外泄露,可以是任意字符,甚至可以是中文。
C#实现:
- /* xxtea.cs
- *
- * Author: Ma Bingyao <andot@ujn.edu.cn>
- * Copyright: CoolCode.CN
- * Version: 1.1
- * LastModified: 2006-05-05
- * This library is free. You can redistribute it and/or modify it.
- * http://www.coolcode.cn/?p=163
- */
- using System;
- class XXTEA
- {
- public static Byte[] Encrypt(Byte[] Data, Byte[] Key)
- {
- if (Data.Length == 0)
- {
- return Data;
- }
- return ToByteArray(Encrypt(ToUInt32Array(Data, true), ToUInt32Array(Key, false)), false);
- }
- public static Byte[] Decrypt(Byte[] Data, Byte[] Key)
- {
- if (Data.Length == 0)
- {
- return Data;
- }
- return ToByteArray(Decrypt(ToUInt32Array(Data, false), ToUInt32Array(Key, false)), true);
- }
- public static UInt32[] Encrypt(UInt32[] v, UInt32[] k)
- {
- Int32 n = v.Length - 1;
- if (n < 1)
- {
- return v;
- }
- if (k.Length < 4)
- {
- UInt32[] Key = new UInt32[4];
- k.CopyTo(Key, 0);
- k = Key;
- }
- UInt32 z = v[n], y = v[0], delta = 0x9E3779B9, sum = 0, e;
- Int32 p, q = 6 + 52 / (n + 1);
- while (q-- > 0)
- {
- sum = unchecked(sum + delta);
- e = sum >> 2 & 3;
- for (p = 0; p < n; p++)
- {
- y = v[p + 1];
- z = unchecked(v[p] += (z >> 5 ^ y << 2) + (y >> 3 ^ z << 4) ^ (sum ^ y) + (k[p & 3 ^ e] ^ z));
- }
- y = v[0];
- z = unchecked(v[n] += (z >> 5 ^ y << 2) + (y >> 3 ^ z << 4) ^ (sum ^ y) + (k[p & 3 ^ e] ^ z));
- }
- return v;
- }
- public static UInt32[] Decrypt(UInt32[] v, UInt32[] k)
- {
- Int32 n = v.Length - 1;
- if (n < 1)
- {
- return v;
- }
- if (k.Length < 4)
- {
- UInt32[] Key = new UInt32[4];
- k.CopyTo(Key, 0);
- k = Key;
- }
- UInt32 z = v[n], y = v[0], delta = 0x9E3779B9, sum, e;
- Int32 p, q = 6 + 52 / (n + 1);
- sum = unchecked((UInt32)(q * delta));
- while (sum != 0)
- {
- e = sum >> 2 & 3;
- for (p = n; p > 0; p--)
- {
- z = v[p - 1];
- y = unchecked(v[p] -= (z >> 5 ^ y << 2) + (y >> 3 ^ z << 4) ^ (sum ^ y) + (k[p & 3 ^ e] ^ z));
- }
- z = v[n];
- y = unchecked(v[0] -= (z >> 5 ^ y << 2) + (y >> 3 ^ z << 4) ^ (sum ^ y) + (k[p & 3 ^ e] ^ z));
- sum = unchecked(sum - delta);
- }
- return v;
- }
- //
- private static UInt32[] ToUInt32Array(Byte[] Data, Boolean IncludeLength)
- {
- //将加密字节根据长度进行位移运算得出&3的key
- Int32 n = (((Data.Length & 3) == 0) ? (Data.Length >> 2) : ((Data.Length >> 2) + 1));
- UInt32[] Result;
- if (IncludeLength)
- {
- Result = new UInt32[n + 1];
- Result[n] = (UInt32)Data.Length;
- }
- else
- {
- Result = new UInt32[n];
- }
- n = Data.Length;
- for (Int32 i = 0; i < n; i++)
- {
- Result[i >> 2] |= (UInt32)Data[i] << ((i & 3) << 3);
- }
- return Result;
- }
- private static Byte[] ToByteArray(UInt32[] Data, Boolean IncludeLength)
- {
- Int32 n;
- if (IncludeLength)
- {
- n = (Int32)Data[Data.Length - 1];
- }
- else
- {
- n = Data.Length << 2;
- }
- Byte[] Result = new Byte[n];
- for (Int32 i = 0; i < n; i++)
- {
- Result[i] = (Byte)(Data[i >> 2] >> ((i & 3) << 3));
- }
- return Result;
- }
- }
JS实现:
- /* xxtea.js
- *
- * Author: Ma Bingyao <andot@ujn.edu.cn>
- * Copyright: CoolCode.CN
- * Version: 1.2
- * LastModified: 2006-05-02
- * This library is free. You can redistribute it and/or modify it.
- * http://www.coolcode.cn/?p=128
- */
- function long2str(v, w) {
- var vl = v.length;
- var sl = v[vl - 1] & 0xffffffff;
- for (var i = 0; i < vl; i++)
- {
- v[i] = String.fromCharCode(v[i] & 0xff,
- v[i] >>> 8 & 0xff,
- v[i] >>> 16 & 0xff,
- v[i] >>> 24 & 0xff);
- }
- if (w) {
- return v.join('').substring(0, sl);
- }
- else {
- return v.join('');
- }
- }
- function str2long(s, w) {
- var len = s.length;
- var v = [];
- for (var i = 0; i < len; i += 4)
- {
- v[i >> 2] = s.charCodeAt(i)
- | s.charCodeAt(i + 1) << 8
- | s.charCodeAt(i + 2) << 16
- | s.charCodeAt(i + 3) << 24;
- }
- if (w) {
- v[v.length] = len;
- }
- return v;
- }
- function xxtea_encrypt(str, key) {
- if (str == "") {
- return "";
- }
- var v = str2long(str, true);
- var k = str2long(key, false);
- var n = v.length - 1;
- var z = v[n], y = v[0], delta = 0x9E3779B9;
- var mx, e, q = Math.floor(6 + 52 / (n + 1)), sum = 0;
- while (q-- > 0) {
- sum = sum + delta & 0xffffffff;
- e = sum >>> 2 & 3;
- for (var p = 0; p < n; p++) {
- y = v[p + 1];
- mx = (z >>> 5 ^ y << 2) + (y >>> 3 ^ z << 4) ^ (sum ^ y) + (k[p & 3 ^ e] ^ z);
- z = v[p] = v[p] + mx & 0xffffffff;
- }
- y = v[0];
- mx = (z >>> 5 ^ y << 2) + (y >>> 3 ^ z << 4) ^ (sum ^ y) + (k[p & 3 ^ e] ^ z);
- z = v[n] = v[n] + mx & 0xffffffff;
- }
- return long2str(v, false);
- }
- function xxtea_decrypt(str, key) {
- if (str == "") {
- return "";
- }
- var v = str2long(str, false);
- var k = str2long(key, false);
- var n = v.length - 1;
- var z = v[n - 1], y = v[0], delta = 0x9E3779B9;
- var mx, e, q = Math.floor(6 + 52 / (n + 1)), sum = q * delta & 0xffffffff;
- while (sum != 0) {
- e = sum >>> 2 & 3;
- for (var p = n; p > 0; p--) {
- z = v[p - 1];
- mx = (z >>> 5 ^ y << 2) + (y >>> 3 ^ z << 4) ^ (sum ^ y) + (k[p & 3 ^ e] ^ z);
- y = v[p] = v[p] - mx & 0xffffffff;
- }
- z = v[n];
- mx = (z >>> 5 ^ y << 2) + (y >>> 3 ^ z << 4) ^ (sum ^ y) + (k[p & 3 ^ e] ^ z);
- y = v[0] = v[0] - mx & 0xffffffff;
- sum = sum - delta & 0xffffffff;
- }
- return long2str(v, true);
- }
Java实现:
- /* xxtea.java
- *
- * Author: Ma Bingyao < andot@ujn.edu.cn >
- * Copyright: CoolCode.CN
- * Version: 1.0
- * LastModified: 2006-05-11
- * This library is free. You can redistribute it and/or modify it.
- * http://www.coolcode.cn/?p=169
- */
- public class xxtea {
- /**
- * Encrypt data with key.
- *
- * @param data
- * @param key
- * @return
- */
- public static byte [] encrypt ( byte [] data , byte [] key ) {
- if ( data . length == 0 ) {
- return data ;
- }
- return toByteArray ( encrypt ( toIntArray ( data , true ) , toIntArray ( key , false )) , false ) ;
- }
- /**
- * Decrypt data with key.
- *
- * @param data
- * @param key
- * @return
- */
- public static byte [] decrypt ( byte [] data , byte [] key ) {
- if ( data . length == 0 ) {
- return data ;
- }
- return toByteArray ( decrypt ( toIntArray ( data , false ) , toIntArray ( key , false )) , true ) ;
- }
- /**
- * Encrypt data with key.
- *
- * @param v
- * @param k
- * @return
- */
- public static int [] encrypt ( int [] v , int [] k ) {
- int n = v . length - 1 ;
- if ( n < 1 ) {
- return v ;
- }
- if ( k . length < 4 ) {
- int [] key = new int [ 4 ] ;
- System . arraycopy ( k , 0 , key , 0 , k . length ) ;
- k = key ;
- }
- int z = v [ n ] , y = v [ 0 ] , delta = 0x9E3779B9 , sum = 0 , e ;
- int p , q = 6 + 52 / ( n + 1 ) ;
- while ( q -- > 0 ) {
- sum = sum + delta ;
- e = sum >>> 2 & 3 ;
- for ( p = 0 ; p < n ; p ++ ) {
- y = v [ p + 1 ] ;
- z = v [ p ] += ( z >>> 5 ^ y << 2 ) + ( y >>> 3 ^ z << 4 ) ^ ( sum ^ y ) + ( k [ p & 3 ^ e ] ^ z ) ;
- }
- y = v [ 0 ] ;
- z = v [ n ] += ( z >>> 5 ^ y << 2 ) + ( y >>> 3 ^ z << 4 ) ^ ( sum ^ y ) + ( k [ p & 3 ^ e ] ^ z ) ;
- }
- return v ;
- }
- /**
- * Decrypt data with key.
- *
- * @param v
- * @param k
- * @return
- */
- public static int [] decrypt ( int [] v , int [] k ) {
- int n = v . length - 1 ;
- if ( n < 1 ) {
- return v ;
- }
- if ( k . length < 4 ) {
- int [] key = new int [ 4 ] ;
- System . arraycopy ( k , 0 , key , 0 , k . length ) ;
- k = key ;
- }
- int z = v [ n ] , y = v [ 0 ] , delta = 0x9E3779B9 , sum , e ;
- int p , q = 6 + 52 / ( n + 1 ) ;
- sum = q * delta ;
- while ( sum != 0 ) {
- e = sum >>> 2 & 3 ;
- for ( p = n ; p > 0 ; p -- ) {
- z = v [ p - 1 ] ;
- y = v [ p ] -= ( z >>> 5 ^ y << 2 ) + ( y >>> 3 ^ z << 4 ) ^ ( sum ^ y ) + ( k [ p & 3 ^ e ] ^ z ) ;
- }
- z = v [ n ] ;
- y = v [ 0 ] -= ( z >>> 5 ^ y << 2 ) + ( y >>> 3 ^ z << 4 ) ^ ( sum ^ y ) + ( k [ p & 3 ^ e ] ^ z ) ;
- sum = sum - delta ;
- }
- return v ;
- }
- /**
- * Convert byte array to int array.
- *
- * @param data
- * @param includeLength
- * @return
- */
- private static int [] toIntArray ( byte [] data , boolean includeLength ) {
- int n = ((( data . length & 3 ) == 0 ) ? ( data . length >>> 2 )
- : (( data . length >>> 2 ) + 1 )) ;
- int [] result ;
- if ( includeLength ) {
- result = new int [ n + 1 ] ;
- result [ n ] = data . length ;
- } else {
- result = new int [ n ] ;
- }
- n = data . length ;
- for ( int i = 0 ; i < n ; i ++ ) {
- result [ i >>> 2 ] |= ( 0x000000ff & data [ i ]) << (( i & 3 ) << 3 ) ;
- }
- return result ;
- }
- /**
- * Convert int array to byte array.
- *
- * @param data
- * @param includeLength
- * @return
- */
- private static byte [] toByteArray ( int [] data , boolean includeLength ) {
- int n ;
- if ( includeLength ) {
- n = data [ data . length - 1 ] ;
- } else {
- n = data . length << 2 ;
- }
- byte [] result = new byte [ n ] ;
- for ( int i = 0 ; i < n ; i ++ ) {
- result [ i ] = ( byte ) ( data [ i >>> 2 ] >>> (( i & 3 ) << 3 )) ;
- }
- return result ;
- }
- }
AS3实现:
package com.klstudio.crypto{
import com.klstudio.util.StringUtil;
public class XXTEA{
public function XXTEA(){
throw new Error("XXTEA class is static container only");
}
private static function long2str(v:Array,w:Boolean):String {
var vl:uint = v.length;
var sl = v[vl - 1] & 0xffffffff;
for (var i:uint = 0; i < vl; i++){
v[i] = String.fromCharCode(v[i] & 0xff,
v[i] >>> 8 & 0xff,
v[i] >>> 16 & 0xff,
v[i] >>> 24 & 0xff);
}
if(w){
return v.join('').substring(0, sl);
}
else {
return v.join('');
}
}
private static function str2long(s:String,w:Boolean):Array {
var len:uint = s.length;
var v:Array = new Array();
for (var i:uint = 0; i < len; i += 4){
v[i >> 2] = s.charCodeAt(i)
| s.charCodeAt(i + 1) << 8
| s.charCodeAt(i + 2) << 16
| s.charCodeAt(i + 3) << 24;
}
if (w) {
v[v.length] = len;
}
return v;
}
public static function encrypt(char:String,key:String):String{
if(char == ""){
return "";
}
var v:Array = str2long(StringUtil.utf16to8(char), true);
var k:Array = str2long(key, false);
var n:uint = v.length - 1;
var z:Number = v[n];
var y:Number = v[0];
var delta:Number = 0x9E3779B9;
var mx:Number;
var q:Number = Math.floor(6 + 52 / (n + 1))
var sum:Number = 0;
while (q-- > 0) {
sum = sum + delta & 0xffffffff;
var e:Number = sum >>> 2 & 3;
for (var p:uint = 0; p < n; p++) {
y = v[p + 1];
mx = (z >>> 5 ^ y << 2) + (y >>> 3 ^ z << 4) ^ (sum ^ y) + (k[p & 3 ^ e] ^ z);
z = v[p] = v[p] + mx & 0xffffffff;
}
y = v[0];
mx = (z >>> 5 ^ y << 2) + (y >>> 3 ^ z << 4) ^ (sum ^ y) + (k[p & 3 ^ e] ^ z);
z = v[n] = v[n] + mx & 0xffffffff;
}
return long2str(v, false);
}
public static function decrypt(char:String,key:String):String{
if (char == "") {
return "";
}
var v:Array = str2long(char, false);
var k:Array = str2long(key, false);
var n:uint = v.length - 1;
var z:Number = v[n - 1];
var y:Number = v[0];
var delta:Number = 0x9E3779B9;
var mx:Number;
var q:Number = Math.floor(6 + 52 / (n + 1));
var sum:Number = q * delta & 0xffffffff;
while (sum != 0) {
var e:Number = sum >>> 2 & 3;
for (var p:uint = n; p > 0; p--) {
z = v[p - 1];
mx = (z >>> 5 ^ y << 2) + (y >>> 3 ^ z << 4) ^ (sum ^ y) + (k[p & 3 ^ e] ^ z);
y = v[p] = v[p] - mx & 0xffffffff;
}
z = v[n];
mx = (z >>> 5 ^ y << 2) + (y >>> 3 ^ z << 4) ^ (sum ^ y) + (k[p & 3 ^ e] ^ z);
y = v[0] = v[0] - mx & 0xffffffff;
sum = sum - delta & 0xffffffff;
}
return StringUtil.utf8to16(long2str(v, true));
}
}
}
以C#实现为例,调用加解密类操作时:
1)加密:
- .........
- //欲加密字符串
- String str = "我要加密";
- //密码本
- String encryptionStr = "你真的要加密吗?";
- //得到encoder对象
- System.Text.Encoding encoder = System.Text.Encoding.UTF8;
- //使用XXTEA加密类对输入字符串进行加密,得到加密后的字节数组(字节数组,字节数组)
- Byte[] data = XXTEA.Encrypt(encoder.GetBytes(str), encoder.GetBytes(encryptionStr;
- //将加密后的字节数组转换为等效字符串
- String decryptStr = System.Convert.ToBase64String(data);
- .........
2)解密:
- .........
- //得到encoder对象
- System.Text.Encoding encoder = System.Text.Encoding.UTF8;
- //欲解密字符串
- String decryptStr = "这里是加密得到的decryptStr字符串";
- //密码本
- String encryptionStr = "你真的要加密吗?";
- //解密后的字符串
- String str = "";
- try
- {
- //通过XXTEA解密类将加密字符串解密
- str = encoder.GetString(XXTEA.Decrypt(System.Convert.FromBase64String(decryptStr), encoder.GetBytes(encryptionStr)));
- }
- catch (Exception e)
- {
- throw new Exception("这个字符不可解密!");
- }
- .........