<PackageReference Include="BouncyCastle.Cryptography" Version="2.3.1" />

TeaEngine

public class TeaEngine : IBlockCipher
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; } } }