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

NoekeonEngine

public class NoekeonEngine : IBlockCipher
using Org.BouncyCastle.Crypto.Parameters; using Org.BouncyCastle.Crypto.Utilities; using Org.BouncyCastle.Utilities; using System; namespace Org.BouncyCastle.Crypto.Engines { public class NoekeonEngine : IBlockCipher { private const int Size = 16; private static readonly byte[] RoundConstants = new byte[17] { 128, 27, 54, 108, 216, 171, 77, 154, 47, 94, 188, 99, 198, 151, 53, 106, 212 }; private readonly uint[] k = new uint[4]; private bool _initialised; private bool _forEncryption; public virtual string AlgorithmName => "Noekeon"; public NoekeonEngine() { _initialised = false; } public virtual int GetBlockSize() { return 16; } public virtual void Init(bool forEncryption, ICipherParameters parameters) { if (!(parameters is KeyParameter)) throw new ArgumentException("Invalid parameters passed to Noekeon init - " + Platform.GetTypeName(parameters), "parameters"); byte[] key = ((KeyParameter)parameters).GetKey(); if (key.Length != 16) throw new ArgumentException("Key length not 128 bits."); Pack.BE_To_UInt32(key, 0, k, 0, 4); if (!forEncryption) { uint num = k[0]; uint num2 = k[1]; uint num3 = k[2]; uint num4 = k[3]; uint num5 = num ^ num3; num5 ^= (Integers.RotateLeft(num5, 8) ^ Integers.RotateLeft(num5, 24)); uint num6 = num2 ^ num4; num6 ^= (Integers.RotateLeft(num6, 8) ^ Integers.RotateLeft(num6, 24)); num ^= num6; num2 ^= num5; num3 ^= num6; num4 ^= num5; k[0] = num; k[1] = num2; k[2] = num3; k[3] = num4; } _forEncryption = forEncryption; _initialised = true; } public virtual int ProcessBlock(byte[] input, int inOff, byte[] output, int outOff) { if (!_initialised) throw new InvalidOperationException(AlgorithmName + " not initialised"); Check.DataLength(input, inOff, 16, "input buffer too short"); Check.OutputLength(output, outOff, 16, "output buffer too short"); if (!_forEncryption) return DecryptBlock(input.AsSpan(inOff), output.AsSpan(outOff)); return EncryptBlock(input.AsSpan(inOff), output.AsSpan(outOff)); } public virtual int ProcessBlock(ReadOnlySpan<byte> input, Span<byte> output) { if (!_initialised) throw new InvalidOperationException(AlgorithmName + " not initialised"); Check.DataLength(input, 16, "input buffer too short"); Check.OutputLength(output, 16, "output buffer too short"); if (!_forEncryption) return DecryptBlock(input, output); return EncryptBlock(input, output); } 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 = Pack.BE_To_UInt32(input.Slice(8, input.Length - 8)); uint num4 = Pack.BE_To_UInt32(input.Slice(12, input.Length - 12)); uint num5 = k[0]; uint num6 = k[1]; uint num7 = k[2]; uint num8 = k[3]; int num9 = 0; while (true) { num ^= RoundConstants[num9]; uint num10 = num ^ num3; num10 ^= (Integers.RotateLeft(num10, 8) ^ Integers.RotateLeft(num10, 24)); num ^= num5; num2 ^= num6; num3 ^= num7; num4 ^= num8; uint num11 = num2 ^ num4; num11 ^= (Integers.RotateLeft(num11, 8) ^ Integers.RotateLeft(num11, 24)); num ^= num11; num2 ^= num10; num3 ^= num11; num4 ^= num10; if (++num9 > 16) break; num2 = Integers.RotateLeft(num2, 1); num3 = Integers.RotateLeft(num3, 5); num4 = Integers.RotateLeft(num4, 2); uint num12 = num4; num2 ^= (num4 | num3); num4 = (num ^ (num3 & ~num2)); num3 = (num12 ^ ~num2 ^ num3 ^ num4); num2 ^= (num4 | num3); num = (num12 ^ (num3 & num2)); num2 = Integers.RotateLeft(num2, 31); num3 = Integers.RotateLeft(num3, 27); num4 = Integers.RotateLeft(num4, 30); } Pack.UInt32_To_BE(num, output); Pack.UInt32_To_BE(num2, output.Slice(4, output.Length - 4)); Pack.UInt32_To_BE(num3, output.Slice(8, output.Length - 8)); Pack.UInt32_To_BE(num4, output.Slice(12, output.Length - 12)); return 16; } 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 = Pack.BE_To_UInt32(input.Slice(8, input.Length - 8)); uint num4 = Pack.BE_To_UInt32(input.Slice(12, input.Length - 12)); uint num5 = k[0]; uint num6 = k[1]; uint num7 = k[2]; uint num8 = k[3]; int num9 = 16; while (true) { uint num10 = num ^ num3; num10 ^= (Integers.RotateLeft(num10, 8) ^ Integers.RotateLeft(num10, 24)); num ^= num5; num2 ^= num6; num3 ^= num7; num4 ^= num8; uint num11 = num2 ^ num4; num11 ^= (Integers.RotateLeft(num11, 8) ^ Integers.RotateLeft(num11, 24)); num ^= num11; num2 ^= num10; num3 ^= num11; num4 ^= num10; num ^= RoundConstants[num9]; if (--num9 < 0) break; num2 = Integers.RotateLeft(num2, 1); num3 = Integers.RotateLeft(num3, 5); num4 = Integers.RotateLeft(num4, 2); uint num12 = num4; num2 ^= (num4 | num3); num4 = (num ^ (num3 & ~num2)); num3 = (num12 ^ ~num2 ^ num3 ^ num4); num2 ^= (num4 | num3); num = (num12 ^ (num3 & num2)); num2 = Integers.RotateLeft(num2, 31); num3 = Integers.RotateLeft(num3, 27); num4 = Integers.RotateLeft(num4, 30); } Pack.UInt32_To_BE(num, output); Pack.UInt32_To_BE(num2, output.Slice(4, output.Length - 4)); Pack.UInt32_To_BE(num3, output.Slice(8, output.Length - 8)); Pack.UInt32_To_BE(num4, output.Slice(12, output.Length - 12)); return 16; } } }