TeaEngine
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Crypto.Utilities;
using Org.BouncyCastle.Utilities;
using System;
namespace Org.BouncyCastle.Crypto.Engines
{
public class TeaEngine : IBlockCipher
{
private const int rounds = 32;
private const int block_size = 8;
private const uint delta = 2654435769;
private const uint d_sum = 3337565984;
private uint _a;
private uint _b;
private uint _c;
private uint _d;
private bool _initialised;
private bool _forEncryption;
public virtual string AlgorithmName => "TEA";
public TeaEngine()
{
_initialised = false;
}
public virtual int GetBlockSize()
{
return 8;
}
public virtual void Init(bool forEncryption, ICipherParameters parameters)
{
KeyParameter keyParameter = parameters as KeyParameter;
if (keyParameter == null)
throw new ArgumentException("invalid parameter passed to TEA init - " + Platform.GetTypeName(parameters));
_forEncryption = forEncryption;
_initialised = true;
SetKey(keyParameter.GetKey());
}
public virtual int ProcessBlock(byte[] inBytes, int inOff, byte[] outBytes, int outOff)
{
if (!_initialised)
throw new InvalidOperationException(AlgorithmName + " not initialised");
Check.DataLength(inBytes, inOff, 8, "input buffer too short");
Check.OutputLength(outBytes, outOff, 8, "output buffer too short");
if (!_forEncryption)
return DecryptBlock(inBytes.AsSpan(inOff), outBytes.AsSpan(outOff));
return EncryptBlock(inBytes.AsSpan(inOff), outBytes.AsSpan(outOff));
}
public virtual int ProcessBlock(ReadOnlySpan<byte> input, Span<byte> output)
{
if (!_initialised)
throw new InvalidOperationException(AlgorithmName + " not initialised");
Check.DataLength(input, 8, "input buffer too short");
Check.OutputLength(output, 8, "output buffer too short");
if (!_forEncryption)
return DecryptBlock(input, output);
return EncryptBlock(input, output);
}
private void SetKey(byte[] key)
{
_a = Pack.BE_To_UInt32(key, 0);
_b = Pack.BE_To_UInt32(key, 4);
_c = Pack.BE_To_UInt32(key, 8);
_d = Pack.BE_To_UInt32(key, 12);
}
private int EncryptBlock(ReadOnlySpan<byte> input, Span<byte> output)
{
uint num = Pack.BE_To_UInt32(input);
uint num2 = Pack.BE_To_UInt32(input.Slice(4, input.Length - 4));
uint num3 = 0;
for (int i = 0; i != 32; i++) {
num3 = (uint)((int)num3 + -1640531527);
num += (((num2 << 4) + _a) ^ (num2 + num3) ^ ((num2 >> 5) + _b));
num2 += (((num << 4) + _c) ^ (num + num3) ^ ((num >> 5) + _d));
}
Pack.UInt32_To_BE(num, output);
Pack.UInt32_To_BE(num2, output.Slice(4, output.Length - 4));
return 8;
}
private int DecryptBlock(ReadOnlySpan<byte> input, Span<byte> output)
{
uint num = Pack.BE_To_UInt32(input);
uint num2 = Pack.BE_To_UInt32(input.Slice(4, input.Length - 4));
uint num3 = 3337565984;
for (int i = 0; i != 32; i++) {
num2 -= (((num << 4) + _c) ^ (num + num3) ^ ((num >> 5) + _d));
num -= (((num2 << 4) + _a) ^ (num2 + num3) ^ ((num2 >> 5) + _b));
num3 = (uint)((int)num3 - -1640531527);
}
Pack.UInt32_To_BE(num, output);
Pack.UInt32_To_BE(num2, output.Slice(4, output.Length - 4));
return 8;
}
}
}