#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR) #pragma warning disable using System; using BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto.Digests; using BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto.Parameters; using BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto.Utilities; namespace BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto.Macs { /// /// Implementation of DSTU7564 mac mode /// public class Dstu7564Mac : IMac { private Dstu7564Digest engine; private int macSize; private ulong inputLength; byte[] paddedKey; byte[] invertedKey; public string AlgorithmName { get { return "DSTU7564Mac"; } } public Dstu7564Mac(int macSizeBits) { engine = new Dstu7564Digest(macSizeBits); macSize = macSizeBits / 8; } public void Init(ICipherParameters parameters) { if (parameters is KeyParameter) { byte[] key = ((KeyParameter)parameters).GetKey(); invertedKey = new byte[key.Length]; paddedKey = PadKey(key); for (int byteIndex = 0; byteIndex < invertedKey.Length; byteIndex++) { invertedKey[byteIndex] = (byte)(key[byteIndex] ^ (byte)0xFF); } } else { throw new ArgumentException("Bad parameter passed"); } 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) { Check.OutputLength(output, outOff, macSize, "Output buffer too short"); if (paddedKey == null) throw new InvalidOperationException(AlgorithmName + " not initialised"); 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 extra = engine.GetByteLength() - (int)(inputLength % (ulong)engine.GetByteLength()); if (extra < 13) // terminator byte + 96 bits of length { extra += engine.GetByteLength(); } byte[] padded = new byte[extra]; padded[0] = (byte)0x80; // Defined in standard; // Defined in standard; Pack.UInt64_To_LE(inputLength * 8, padded, padded.Length - 12); engine.BlockUpdate(padded, 0, padded.Length); } private byte[] PadKey(byte[] input) { int paddedLen = ((input.Length + engine.GetByteLength() - 1) / engine.GetByteLength()) * engine.GetByteLength(); int extra = engine.GetByteLength() - (int)(input.Length % engine.GetByteLength()); if (extra < 13) // terminator byte + 96 bits of length { paddedLen += engine.GetByteLength(); } byte[] padded = new byte[paddedLen]; Array.Copy(input, 0, padded, 0, input.Length); padded[input.Length] = (byte)0x80; // Defined in standard; Pack.UInt32_To_LE((uint)(input.Length * 8), padded, padded.Length - 12); // Defined in standard; return padded; } } } #pragma warning restore #endif