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

Dstu7564Mac

public class Dstu7564Mac : IMac
Implementation of DSTU7564 mac mode
using Org.BouncyCastle.Crypto.Digests; using Org.BouncyCastle.Crypto.Parameters; using Org.BouncyCastle.Crypto.Utilities; using System; namespace Org.BouncyCastle.Crypto.Macs { public class Dstu7564Mac : IMac { private Dstu7564Digest engine; private int macSize; private ulong inputLength; private byte[] paddedKey; private byte[] invertedKey; public string AlgorithmName => "DSTU7564Mac"; public Dstu7564Mac(int macSizeBits) { engine = new Dstu7564Digest(macSizeBits); macSize = macSizeBits / 8; } public void Init(ICipherParameters parameters) { if (!(parameters is KeyParameter)) throw new ArgumentException("Bad parameter passed"); byte[] key = ((KeyParameter)parameters).GetKey(); invertedKey = new byte[key.Length]; paddedKey = PadKey(key); for (int i = 0; i < invertedKey.Length; i++) { invertedKey[i] = (byte)(key[i] ^ 255); } engine.BlockUpdate(paddedKey, 0, paddedKey.Length); } public int GetMacSize() { return macSize; } public void BlockUpdate(byte[] input, int inOff, int len) { Check.DataLength(input, inOff, len, "input buffer too short"); if (paddedKey == null) throw new InvalidOperationException(AlgorithmName + " not initialised"); engine.BlockUpdate(input, inOff, len); inputLength += (ulong)len; } public void Update(byte input) { engine.Update(input); inputLength++; } public int DoFinal(byte[] output, int outOff) { if (paddedKey == null) throw new InvalidOperationException(AlgorithmName + " not initialised"); Check.OutputLength(output, outOff, macSize, "output buffer too short"); Pad(); engine.BlockUpdate(invertedKey, 0, invertedKey.Length); inputLength = 0; return engine.DoFinal(output, outOff); } public void Reset() { inputLength = 0; engine.Reset(); if (paddedKey != null) engine.BlockUpdate(paddedKey, 0, paddedKey.Length); } private void Pad() { int num = engine.GetByteLength() - (int)(inputLength % (ulong)engine.GetByteLength()); if (num < 13) num += engine.GetByteLength(); byte[] array = new byte[num]; array[0] = 128; Pack.UInt64_To_LE(inputLength * 8, array, array.Length - 12); engine.BlockUpdate(array, 0, array.Length); } private byte[] PadKey(byte[] input) { int num = (input.Length + engine.GetByteLength() - 1) / engine.GetByteLength() * engine.GetByteLength(); if (engine.GetByteLength() - input.Length % engine.GetByteLength() < 13) num += engine.GetByteLength(); byte[] array = new byte[num]; Array.Copy(input, 0, array, 0, input.Length); array[input.Length] = 128; Pack.UInt32_To_LE((uint)(input.Length * 8), array, array.Length - 12); return array; } } }