You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
155 lines
5.1 KiB
155 lines
5.1 KiB
/*
|
|
* 在安全学领域,TEA(Tiny Encryption Algorithm)是一种分组加密算法,它的实现非常简单,通常只需要很精短的几行代码。
|
|
* TEA 算法最初是由剑桥计算机实验室的 David Wheeler 和 Roger Needham 在 1994 年设计的。
|
|
* TEA算法使用64位的明文分组和128位的密钥,它使用Feistel分组加密框架,需要进行 64 轮迭代,尽管作者认为 32 轮已经足够了。
|
|
* 该算法使用了一个神秘常数δ作为倍数,它来源于黄金比率,以保证每一轮加密都不相同。但δ的精确值似乎并不重要,这里 TEA 把它定义为 δ=「(√5 - 1)231」(也就是程序中的 0×9E3779B9)
|
|
*
|
|
* 之后 TEA 算法被发现存在缺陷,作为回应,设计者提出了一个 TEA 的升级版本——XTEA(有时也被称为“tean”)。
|
|
* XTEA 跟 TEA 使用了相同的简单运算,但它采用了截然不同的顺序,为了阻止密钥表攻击,四个子密钥(在加密过程中,原 128 位的密钥被拆分为 4 个 32 位的子密钥)采用了一种不太正规的方式进行混合,但速度更慢了。
|
|
*
|
|
*/
|
|
|
|
|
|
using System;
|
|
|
|
|
|
namespace Sog.Crypto
|
|
{
|
|
|
|
/// <summary>
|
|
/// byte[] 和 int 互相转换,采用大字节序
|
|
/// </summary>
|
|
internal sealed class PackUtils
|
|
{
|
|
internal static uint BE_To_UInt32(byte[] bs, int off)
|
|
{
|
|
return (uint)bs[off] << 24
|
|
| (uint)bs[off + 1] << 16
|
|
| (uint)bs[off + 2] << 8
|
|
| (uint)bs[off + 3];
|
|
}
|
|
|
|
internal static void UInt32_To_BE(uint n, byte[] bs, int off)
|
|
{
|
|
bs[off] = (byte)(n >> 24);
|
|
bs[off + 1] = (byte)(n >> 16);
|
|
bs[off + 2] = (byte)(n >> 8);
|
|
bs[off + 3] = (byte)(n);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// SogFastXTEA的密钥,同时用于加密解密,根据byte[]类型的密钥生成计算所需要的int[]类型的Sum0,Sum1
|
|
/// 目的是提高算法的效率,不用每次加密,解密的时候都处理一遍byte[]的key
|
|
/// </summary>
|
|
public class SogFastXTEAKey
|
|
{
|
|
private const int delta = unchecked((int)0x9E3779B9);
|
|
|
|
private uint[] _S = new uint[4];
|
|
|
|
public byte[] Key { get; }
|
|
|
|
public uint[] Sum0 { get; }
|
|
public uint[] Sum1 { get; }
|
|
|
|
public SogFastXTEAKey(byte[] srcKey)
|
|
{
|
|
if(srcKey.Length != 16)
|
|
{
|
|
throw new Exception("SogXTEAKey key length must is 16");
|
|
}
|
|
|
|
Key = srcKey;
|
|
|
|
Sum0 = new uint[SogFastXTEA.Rounds];
|
|
Sum1 = new uint[SogFastXTEA.Rounds];
|
|
|
|
int i, j;
|
|
for (i = j = 0; i < 4; i++, j += 4)
|
|
{
|
|
_S[i] = PackUtils.BE_To_UInt32(srcKey, j);
|
|
}
|
|
|
|
for (i = j = 0; i < SogFastXTEA.Rounds; i++)
|
|
{
|
|
Sum0[i] = ((uint)j + _S[j & 3]);
|
|
j += delta;
|
|
Sum1[i] = ((uint)j + _S[j >> 11 & 3]);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// 快速XTEA算法,XTEA加密的变种,小于8个字节不加密,轮数量减少到8,提高效率
|
|
/// </summary>
|
|
public sealed class SogFastXTEA
|
|
{
|
|
public const int Rounds = 8;
|
|
|
|
private const int delta = unchecked((int)0x9E3779B9);
|
|
|
|
private SogFastXTEA()
|
|
{
|
|
|
|
}
|
|
|
|
|
|
public static void Encrypt(byte[] data, SogFastXTEAKey key)
|
|
{
|
|
Encrypt(data, data.Length, key);
|
|
}
|
|
|
|
public static void Encrypt(byte[] data, int length, SogFastXTEAKey key)
|
|
{
|
|
int iBlockCount = length / 8;
|
|
int offset = 0;
|
|
for (int block = 0; block < iBlockCount; block++)
|
|
{
|
|
uint v0 = PackUtils.BE_To_UInt32(data, offset);
|
|
uint v1 = PackUtils.BE_To_UInt32(data, offset + 4);
|
|
|
|
for (int i = 0; i < Rounds; i++)
|
|
{
|
|
v0 += ((v1 << 4 ^ v1 >> 5) + v1) ^ key.Sum0[i];
|
|
v1 += ((v0 << 4 ^ v0 >> 5) + v0) ^ key.Sum1[i];
|
|
}
|
|
|
|
PackUtils.UInt32_To_BE(v0, data, offset);
|
|
PackUtils.UInt32_To_BE(v1, data, offset + 4);
|
|
|
|
offset += 8;
|
|
}
|
|
}
|
|
|
|
public static void Decrypt(byte[] data, SogFastXTEAKey key)
|
|
{
|
|
Decrypt(data, data.Length, key);
|
|
}
|
|
|
|
public static void Decrypt(byte[] data, int length, SogFastXTEAKey key)
|
|
{
|
|
int iBlockCount = length / 8;
|
|
int offset = 0;
|
|
for (int block = 0; block < iBlockCount; block++)
|
|
{
|
|
uint v0 = PackUtils.BE_To_UInt32(data, offset);
|
|
uint v1 = PackUtils.BE_To_UInt32(data, offset + 4);
|
|
|
|
for (int i = Rounds - 1; i >= 0; i--)
|
|
{
|
|
v1 -= ((v0 << 4 ^ v0 >> 5) + v0) ^ key.Sum1[i];
|
|
v0 -= ((v1 << 4 ^ v1 >> 5) + v1) ^ key.Sum0[i];
|
|
}
|
|
|
|
PackUtils.UInt32_To_BE(v0, data, offset);
|
|
PackUtils.UInt32_To_BE(v1, data, offset + 4);
|
|
|
|
offset += 8;
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
}
|
|
|