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.
177 lines
4.6 KiB
177 lines
4.6 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.Utilities; |
|
|
|
namespace BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto.Macs |
|
{ |
|
public class KMac |
|
: IMac, IXof |
|
{ |
|
private static readonly byte[] padding = new byte[100]; |
|
|
|
private readonly CShakeDigest cshake; |
|
private readonly int bitLength; |
|
private readonly int outputLength; |
|
|
|
private byte[] key; |
|
private bool initialised; |
|
private bool firstOutput; |
|
|
|
public KMac(int bitLength, byte[] S) |
|
{ |
|
this.cshake = new CShakeDigest(bitLength, Strings.ToAsciiByteArray("KMAC"), S); |
|
this.bitLength = bitLength; |
|
this.outputLength = bitLength * 2 / 8; |
|
} |
|
|
|
public string AlgorithmName |
|
{ |
|
get { return "KMAC" + cshake.AlgorithmName.Substring(6); } |
|
} |
|
|
|
public void BlockUpdate(byte[] input, int inOff, int len) |
|
{ |
|
if (!initialised) |
|
throw new InvalidOperationException("KMAC not initialized"); |
|
|
|
cshake.BlockUpdate(input, inOff, len); |
|
} |
|
|
|
public int DoFinal(byte[] output, int outOff) |
|
{ |
|
if (firstOutput) |
|
{ |
|
if (!initialised) |
|
throw new InvalidOperationException("KMAC not initialized"); |
|
|
|
byte[] encOut = XofUtilities.RightEncode(GetMacSize() * 8); |
|
|
|
cshake.BlockUpdate(encOut, 0, encOut.Length); |
|
} |
|
|
|
int rv = cshake.DoFinal(output, outOff, GetMacSize()); |
|
|
|
Reset(); |
|
|
|
return rv; |
|
} |
|
|
|
public int DoFinal(byte[] output, int outOff, int outLen) |
|
{ |
|
if (firstOutput) |
|
{ |
|
if (!initialised) |
|
throw new InvalidOperationException("KMAC not initialized"); |
|
|
|
byte[] encOut = XofUtilities.RightEncode(outLen * 8); |
|
|
|
cshake.BlockUpdate(encOut, 0, encOut.Length); |
|
} |
|
|
|
int rv = cshake.DoFinal(output, outOff, outLen); |
|
|
|
Reset(); |
|
|
|
return rv; |
|
} |
|
|
|
public int DoOutput(byte[] output, int outOff, int outLen) |
|
{ |
|
if (firstOutput) |
|
{ |
|
if (!initialised) |
|
throw new InvalidOperationException("KMAC not initialized"); |
|
|
|
byte[] encOut = XofUtilities.RightEncode(0); |
|
|
|
cshake.BlockUpdate(encOut, 0, encOut.Length); |
|
|
|
firstOutput = false; |
|
} |
|
|
|
return cshake.DoOutput(output, outOff, outLen); |
|
} |
|
|
|
public int GetByteLength() |
|
{ |
|
return cshake.GetByteLength(); |
|
} |
|
|
|
public int GetDigestSize() |
|
{ |
|
return outputLength; |
|
} |
|
|
|
public int GetMacSize() |
|
{ |
|
return outputLength; |
|
} |
|
|
|
public void Init(ICipherParameters parameters) |
|
{ |
|
KeyParameter kParam = (KeyParameter)parameters; |
|
this.key = Arrays.Clone(kParam.GetKey()); |
|
this.initialised = true; |
|
Reset(); |
|
} |
|
|
|
public void Reset() |
|
{ |
|
cshake.Reset(); |
|
|
|
if (key != null) |
|
{ |
|
if (bitLength == 128) |
|
{ |
|
bytePad(key, 168); |
|
} |
|
else |
|
{ |
|
bytePad(key, 136); |
|
} |
|
} |
|
|
|
firstOutput = true; |
|
} |
|
|
|
private void bytePad(byte[] X, int w) |
|
{ |
|
byte[] bytes = XofUtilities.LeftEncode(w); |
|
BlockUpdate(bytes, 0, bytes.Length); |
|
byte[] encX = encode(X); |
|
BlockUpdate(encX, 0, encX.Length); |
|
|
|
int required = w - ((bytes.Length + encX.Length) % w); |
|
|
|
if (required > 0 && required != w) |
|
{ |
|
while (required > padding.Length) |
|
{ |
|
BlockUpdate(padding, 0, padding.Length); |
|
required -= padding.Length; |
|
} |
|
|
|
BlockUpdate(padding, 0, required); |
|
} |
|
} |
|
|
|
private static byte[] encode(byte[] X) |
|
{ |
|
return Arrays.Concatenate(XofUtilities.LeftEncode(X.Length * 8), X); |
|
} |
|
|
|
public void Update(byte input) |
|
{ |
|
if (!initialised) |
|
throw new InvalidOperationException("KMAC not initialized"); |
|
|
|
cshake.Update(input); |
|
} |
|
} |
|
} |
|
#pragma warning restore |
|
#endif
|
|
|