You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
147 lines
4.1 KiB
147 lines
4.1 KiB
#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 |
|
{ |
|
/// <summary> |
|
/// Implementation of DSTU7564 mac mode |
|
/// </summary> |
|
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
|
|
|