init commit
This commit is contained in:
@@ -0,0 +1,178 @@
|
||||
using System;
|
||||
using Org.BouncyCastle.Crypto.Modes;
|
||||
using Org.BouncyCastle.Crypto.Paddings;
|
||||
using Org.BouncyCastle.Crypto.Parameters;
|
||||
|
||||
namespace Org.BouncyCastle.Crypto.Macs;
|
||||
|
||||
public class CMac : IMac
|
||||
{
|
||||
private const byte CONSTANT_128 = 135;
|
||||
|
||||
private const byte CONSTANT_64 = 27;
|
||||
|
||||
private byte[] ZEROES;
|
||||
|
||||
private byte[] mac;
|
||||
|
||||
private byte[] buf;
|
||||
|
||||
private int bufOff;
|
||||
|
||||
private IBlockCipher cipher;
|
||||
|
||||
private int macSize;
|
||||
|
||||
private byte[] L;
|
||||
|
||||
private byte[] Lu;
|
||||
|
||||
private byte[] Lu2;
|
||||
|
||||
public string AlgorithmName => cipher.AlgorithmName;
|
||||
|
||||
public CMac(IBlockCipher cipher)
|
||||
: this(cipher, cipher.GetBlockSize() * 8)
|
||||
{
|
||||
}
|
||||
|
||||
public CMac(IBlockCipher cipher, int macSizeInBits)
|
||||
{
|
||||
if (macSizeInBits % 8 != 0)
|
||||
{
|
||||
throw new ArgumentException("MAC size must be multiple of 8");
|
||||
}
|
||||
if (macSizeInBits > cipher.GetBlockSize() * 8)
|
||||
{
|
||||
throw new ArgumentException("MAC size must be less or equal to " + cipher.GetBlockSize() * 8);
|
||||
}
|
||||
if (cipher.GetBlockSize() != 8 && cipher.GetBlockSize() != 16)
|
||||
{
|
||||
throw new ArgumentException("Block size must be either 64 or 128 bits");
|
||||
}
|
||||
this.cipher = new CbcBlockCipher(cipher);
|
||||
macSize = macSizeInBits / 8;
|
||||
mac = new byte[cipher.GetBlockSize()];
|
||||
buf = new byte[cipher.GetBlockSize()];
|
||||
ZEROES = new byte[cipher.GetBlockSize()];
|
||||
bufOff = 0;
|
||||
}
|
||||
|
||||
private static int ShiftLeft(byte[] block, byte[] output)
|
||||
{
|
||||
int num = block.Length;
|
||||
uint num2 = 0u;
|
||||
while (--num >= 0)
|
||||
{
|
||||
uint num3 = block[num];
|
||||
output[num] = (byte)((num3 << 1) | num2);
|
||||
num2 = (num3 >> 7) & 1;
|
||||
}
|
||||
return (int)num2;
|
||||
}
|
||||
|
||||
private static byte[] DoubleLu(byte[] input)
|
||||
{
|
||||
byte[] array = new byte[input.Length];
|
||||
int num = ShiftLeft(input, array);
|
||||
int num2 = ((input.Length == 16) ? 135 : 27);
|
||||
byte[] array3;
|
||||
byte[] array2 = (array3 = array);
|
||||
int num3 = input.Length - 1;
|
||||
nint num4 = num3;
|
||||
array2[num3] = (byte)(array3[num4] ^ (byte)(num2 >> (1 - num << 3)));
|
||||
return array;
|
||||
}
|
||||
|
||||
public void Init(ICipherParameters parameters)
|
||||
{
|
||||
if (parameters is KeyParameter)
|
||||
{
|
||||
cipher.Init(forEncryption: true, parameters);
|
||||
L = new byte[ZEROES.Length];
|
||||
cipher.ProcessBlock(ZEROES, 0, L, 0);
|
||||
Lu = DoubleLu(L);
|
||||
Lu2 = DoubleLu(Lu);
|
||||
}
|
||||
else if (parameters != null)
|
||||
{
|
||||
throw new ArgumentException("CMac mode only permits key to be set.", "parameters");
|
||||
}
|
||||
Reset();
|
||||
}
|
||||
|
||||
public int GetMacSize()
|
||||
{
|
||||
return macSize;
|
||||
}
|
||||
|
||||
public void Update(byte input)
|
||||
{
|
||||
if (bufOff == buf.Length)
|
||||
{
|
||||
cipher.ProcessBlock(buf, 0, mac, 0);
|
||||
bufOff = 0;
|
||||
}
|
||||
buf[bufOff++] = input;
|
||||
}
|
||||
|
||||
public void BlockUpdate(byte[] inBytes, int inOff, int len)
|
||||
{
|
||||
if (len < 0)
|
||||
{
|
||||
throw new ArgumentException("Can't have a negative input length!");
|
||||
}
|
||||
int blockSize = cipher.GetBlockSize();
|
||||
int num = blockSize - bufOff;
|
||||
if (len > num)
|
||||
{
|
||||
Array.Copy(inBytes, inOff, buf, bufOff, num);
|
||||
cipher.ProcessBlock(buf, 0, mac, 0);
|
||||
bufOff = 0;
|
||||
len -= num;
|
||||
inOff += num;
|
||||
while (len > blockSize)
|
||||
{
|
||||
cipher.ProcessBlock(inBytes, inOff, mac, 0);
|
||||
len -= blockSize;
|
||||
inOff += blockSize;
|
||||
}
|
||||
}
|
||||
Array.Copy(inBytes, inOff, buf, bufOff, len);
|
||||
bufOff += len;
|
||||
}
|
||||
|
||||
public int DoFinal(byte[] outBytes, int outOff)
|
||||
{
|
||||
int blockSize = cipher.GetBlockSize();
|
||||
byte[] array;
|
||||
if (bufOff == blockSize)
|
||||
{
|
||||
array = Lu;
|
||||
}
|
||||
else
|
||||
{
|
||||
new ISO7816d4Padding().AddPadding(buf, bufOff);
|
||||
array = Lu2;
|
||||
}
|
||||
for (int i = 0; i < mac.Length; i++)
|
||||
{
|
||||
byte[] array3;
|
||||
byte[] array2 = (array3 = buf);
|
||||
int num = i;
|
||||
nint num2 = num;
|
||||
array2[num] = (byte)(array3[num2] ^ array[i]);
|
||||
}
|
||||
cipher.ProcessBlock(buf, 0, mac, 0);
|
||||
Array.Copy(mac, 0, outBytes, outOff, macSize);
|
||||
Reset();
|
||||
return macSize;
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
Array.Clear(buf, 0, buf.Length);
|
||||
bufOff = 0;
|
||||
cipher.Reset();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
using System;
|
||||
using Org.BouncyCastle.Crypto.Modes;
|
||||
using Org.BouncyCastle.Crypto.Paddings;
|
||||
|
||||
namespace Org.BouncyCastle.Crypto.Macs;
|
||||
|
||||
public class CbcBlockCipherMac : IMac
|
||||
{
|
||||
private byte[] buf;
|
||||
|
||||
private int bufOff;
|
||||
|
||||
private IBlockCipher cipher;
|
||||
|
||||
private IBlockCipherPadding padding;
|
||||
|
||||
private int macSize;
|
||||
|
||||
public string AlgorithmName => cipher.AlgorithmName;
|
||||
|
||||
public CbcBlockCipherMac(IBlockCipher cipher)
|
||||
: this(cipher, cipher.GetBlockSize() * 8 / 2, null)
|
||||
{
|
||||
}
|
||||
|
||||
public CbcBlockCipherMac(IBlockCipher cipher, IBlockCipherPadding padding)
|
||||
: this(cipher, cipher.GetBlockSize() * 8 / 2, padding)
|
||||
{
|
||||
}
|
||||
|
||||
public CbcBlockCipherMac(IBlockCipher cipher, int macSizeInBits)
|
||||
: this(cipher, macSizeInBits, null)
|
||||
{
|
||||
}
|
||||
|
||||
public CbcBlockCipherMac(IBlockCipher cipher, int macSizeInBits, IBlockCipherPadding padding)
|
||||
{
|
||||
if (macSizeInBits % 8 != 0)
|
||||
{
|
||||
throw new ArgumentException("MAC size must be multiple of 8");
|
||||
}
|
||||
this.cipher = new CbcBlockCipher(cipher);
|
||||
this.padding = padding;
|
||||
macSize = macSizeInBits / 8;
|
||||
buf = new byte[cipher.GetBlockSize()];
|
||||
bufOff = 0;
|
||||
}
|
||||
|
||||
public void Init(ICipherParameters parameters)
|
||||
{
|
||||
Reset();
|
||||
cipher.Init(forEncryption: true, parameters);
|
||||
}
|
||||
|
||||
public int GetMacSize()
|
||||
{
|
||||
return macSize;
|
||||
}
|
||||
|
||||
public void Update(byte input)
|
||||
{
|
||||
if (bufOff == buf.Length)
|
||||
{
|
||||
cipher.ProcessBlock(buf, 0, buf, 0);
|
||||
bufOff = 0;
|
||||
}
|
||||
buf[bufOff++] = input;
|
||||
}
|
||||
|
||||
public void BlockUpdate(byte[] input, int inOff, int len)
|
||||
{
|
||||
if (len < 0)
|
||||
{
|
||||
throw new ArgumentException("Can't have a negative input length!");
|
||||
}
|
||||
int blockSize = cipher.GetBlockSize();
|
||||
int num = blockSize - bufOff;
|
||||
if (len > num)
|
||||
{
|
||||
Array.Copy(input, inOff, buf, bufOff, num);
|
||||
cipher.ProcessBlock(buf, 0, buf, 0);
|
||||
bufOff = 0;
|
||||
len -= num;
|
||||
inOff += num;
|
||||
while (len > blockSize)
|
||||
{
|
||||
cipher.ProcessBlock(input, inOff, buf, 0);
|
||||
len -= blockSize;
|
||||
inOff += blockSize;
|
||||
}
|
||||
}
|
||||
Array.Copy(input, inOff, buf, bufOff, len);
|
||||
bufOff += len;
|
||||
}
|
||||
|
||||
public int DoFinal(byte[] output, int outOff)
|
||||
{
|
||||
int blockSize = cipher.GetBlockSize();
|
||||
if (padding == null)
|
||||
{
|
||||
while (bufOff < blockSize)
|
||||
{
|
||||
buf[bufOff++] = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (bufOff == blockSize)
|
||||
{
|
||||
cipher.ProcessBlock(buf, 0, buf, 0);
|
||||
bufOff = 0;
|
||||
}
|
||||
padding.AddPadding(buf, bufOff);
|
||||
}
|
||||
cipher.ProcessBlock(buf, 0, buf, 0);
|
||||
Array.Copy(buf, 0, output, outOff, macSize);
|
||||
Reset();
|
||||
return macSize;
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
Array.Clear(buf, 0, buf.Length);
|
||||
bufOff = 0;
|
||||
cipher.Reset();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,126 @@
|
||||
using System;
|
||||
using Org.BouncyCastle.Crypto.Paddings;
|
||||
|
||||
namespace Org.BouncyCastle.Crypto.Macs;
|
||||
|
||||
public class CfbBlockCipherMac : IMac
|
||||
{
|
||||
private byte[] mac;
|
||||
|
||||
private byte[] Buffer;
|
||||
|
||||
private int bufOff;
|
||||
|
||||
private MacCFBBlockCipher cipher;
|
||||
|
||||
private IBlockCipherPadding padding;
|
||||
|
||||
private int macSize;
|
||||
|
||||
public string AlgorithmName => cipher.AlgorithmName;
|
||||
|
||||
public CfbBlockCipherMac(IBlockCipher cipher)
|
||||
: this(cipher, 8, cipher.GetBlockSize() * 8 / 2, null)
|
||||
{
|
||||
}
|
||||
|
||||
public CfbBlockCipherMac(IBlockCipher cipher, IBlockCipherPadding padding)
|
||||
: this(cipher, 8, cipher.GetBlockSize() * 8 / 2, padding)
|
||||
{
|
||||
}
|
||||
|
||||
public CfbBlockCipherMac(IBlockCipher cipher, int cfbBitSize, int macSizeInBits)
|
||||
: this(cipher, cfbBitSize, macSizeInBits, null)
|
||||
{
|
||||
}
|
||||
|
||||
public CfbBlockCipherMac(IBlockCipher cipher, int cfbBitSize, int macSizeInBits, IBlockCipherPadding padding)
|
||||
{
|
||||
if (macSizeInBits % 8 != 0)
|
||||
{
|
||||
throw new ArgumentException("MAC size must be multiple of 8");
|
||||
}
|
||||
mac = new byte[cipher.GetBlockSize()];
|
||||
this.cipher = new MacCFBBlockCipher(cipher, cfbBitSize);
|
||||
this.padding = padding;
|
||||
macSize = macSizeInBits / 8;
|
||||
Buffer = new byte[this.cipher.GetBlockSize()];
|
||||
bufOff = 0;
|
||||
}
|
||||
|
||||
public void Init(ICipherParameters parameters)
|
||||
{
|
||||
Reset();
|
||||
cipher.Init(forEncryption: true, parameters);
|
||||
}
|
||||
|
||||
public int GetMacSize()
|
||||
{
|
||||
return macSize;
|
||||
}
|
||||
|
||||
public void Update(byte input)
|
||||
{
|
||||
if (bufOff == Buffer.Length)
|
||||
{
|
||||
cipher.ProcessBlock(Buffer, 0, mac, 0);
|
||||
bufOff = 0;
|
||||
}
|
||||
Buffer[bufOff++] = input;
|
||||
}
|
||||
|
||||
public void BlockUpdate(byte[] input, int inOff, int len)
|
||||
{
|
||||
if (len < 0)
|
||||
{
|
||||
throw new ArgumentException("Can't have a negative input length!");
|
||||
}
|
||||
int blockSize = cipher.GetBlockSize();
|
||||
int num = 0;
|
||||
int num2 = blockSize - bufOff;
|
||||
if (len > num2)
|
||||
{
|
||||
Array.Copy(input, inOff, Buffer, bufOff, num2);
|
||||
num += cipher.ProcessBlock(Buffer, 0, mac, 0);
|
||||
bufOff = 0;
|
||||
len -= num2;
|
||||
inOff += num2;
|
||||
while (len > blockSize)
|
||||
{
|
||||
num += cipher.ProcessBlock(input, inOff, mac, 0);
|
||||
len -= blockSize;
|
||||
inOff += blockSize;
|
||||
}
|
||||
}
|
||||
Array.Copy(input, inOff, Buffer, bufOff, len);
|
||||
bufOff += len;
|
||||
}
|
||||
|
||||
public int DoFinal(byte[] output, int outOff)
|
||||
{
|
||||
int blockSize = cipher.GetBlockSize();
|
||||
if (padding == null)
|
||||
{
|
||||
while (bufOff < blockSize)
|
||||
{
|
||||
Buffer[bufOff++] = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
padding.AddPadding(Buffer, bufOff);
|
||||
}
|
||||
cipher.ProcessBlock(Buffer, 0, mac, 0);
|
||||
cipher.GetMacBlock(mac);
|
||||
Array.Copy(mac, 0, output, outOff, macSize);
|
||||
Reset();
|
||||
return macSize;
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
Array.Clear(Buffer, 0, Buffer.Length);
|
||||
bufOff = 0;
|
||||
cipher.Reset();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
using System;
|
||||
using Org.BouncyCastle.Crypto.Digests;
|
||||
using Org.BouncyCastle.Crypto.Parameters;
|
||||
using Org.BouncyCastle.Crypto.Utilities;
|
||||
|
||||
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)
|
||||
{
|
||||
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] ^ 0xFF);
|
||||
}
|
||||
engine.BlockUpdate(paddedKey, 0, paddedKey.Length);
|
||||
return;
|
||||
}
|
||||
throw new ArgumentException("Bad parameter passed");
|
||||
}
|
||||
|
||||
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 = 0uL;
|
||||
return engine.DoFinal(output, outOff);
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
inputLength = 0uL;
|
||||
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();
|
||||
int num2 = engine.GetByteLength() - input.Length % engine.GetByteLength();
|
||||
if (num2 < 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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,132 @@
|
||||
using System;
|
||||
using Org.BouncyCastle.Crypto.Engines;
|
||||
using Org.BouncyCastle.Crypto.Parameters;
|
||||
using Org.BouncyCastle.Utilities;
|
||||
|
||||
namespace Org.BouncyCastle.Crypto.Macs;
|
||||
|
||||
public class Dstu7624Mac : IMac
|
||||
{
|
||||
private int macSize;
|
||||
|
||||
private Dstu7624Engine engine;
|
||||
|
||||
private int blockSize;
|
||||
|
||||
private byte[] c;
|
||||
|
||||
private byte[] cTemp;
|
||||
|
||||
private byte[] kDelta;
|
||||
|
||||
private byte[] buf;
|
||||
|
||||
private int bufOff;
|
||||
|
||||
public string AlgorithmName => "Dstu7624Mac";
|
||||
|
||||
public Dstu7624Mac(int blockSizeBits, int q)
|
||||
{
|
||||
engine = new Dstu7624Engine(blockSizeBits);
|
||||
blockSize = blockSizeBits / 8;
|
||||
macSize = q / 8;
|
||||
c = new byte[blockSize];
|
||||
cTemp = new byte[blockSize];
|
||||
kDelta = new byte[blockSize];
|
||||
buf = new byte[blockSize];
|
||||
}
|
||||
|
||||
public void Init(ICipherParameters parameters)
|
||||
{
|
||||
if (parameters is KeyParameter)
|
||||
{
|
||||
engine.Init(forEncryption: true, (KeyParameter)parameters);
|
||||
engine.ProcessBlock(kDelta, 0, kDelta, 0);
|
||||
return;
|
||||
}
|
||||
throw new ArgumentException("invalid parameter passed to Dstu7624Mac init - " + Platform.GetTypeName(parameters));
|
||||
}
|
||||
|
||||
public int GetMacSize()
|
||||
{
|
||||
return macSize;
|
||||
}
|
||||
|
||||
public void Update(byte input)
|
||||
{
|
||||
if (bufOff == buf.Length)
|
||||
{
|
||||
processBlock(buf, 0);
|
||||
bufOff = 0;
|
||||
}
|
||||
buf[bufOff++] = input;
|
||||
}
|
||||
|
||||
public void BlockUpdate(byte[] input, int inOff, int len)
|
||||
{
|
||||
if (len < 0)
|
||||
{
|
||||
throw new ArgumentException("Can't have a negative input length!");
|
||||
}
|
||||
int num = engine.GetBlockSize();
|
||||
int num2 = num - bufOff;
|
||||
if (len > num2)
|
||||
{
|
||||
Array.Copy(input, inOff, buf, bufOff, num2);
|
||||
processBlock(buf, 0);
|
||||
bufOff = 0;
|
||||
len -= num2;
|
||||
inOff += num2;
|
||||
while (len > num)
|
||||
{
|
||||
processBlock(input, inOff);
|
||||
len -= num;
|
||||
inOff += num;
|
||||
}
|
||||
}
|
||||
Array.Copy(input, inOff, buf, bufOff, len);
|
||||
bufOff += len;
|
||||
}
|
||||
|
||||
private void processBlock(byte[] input, int inOff)
|
||||
{
|
||||
Xor(c, 0, input, inOff, cTemp);
|
||||
engine.ProcessBlock(cTemp, 0, c, 0);
|
||||
}
|
||||
|
||||
private void Xor(byte[] c, int cOff, byte[] input, int inOff, byte[] xorResult)
|
||||
{
|
||||
for (int i = 0; i < blockSize; i++)
|
||||
{
|
||||
xorResult[i] = (byte)(c[i + cOff] ^ input[i + inOff]);
|
||||
}
|
||||
}
|
||||
|
||||
public int DoFinal(byte[] output, int outOff)
|
||||
{
|
||||
if (bufOff % buf.Length != 0)
|
||||
{
|
||||
throw new DataLengthException("Input must be a multiple of blocksize");
|
||||
}
|
||||
Xor(c, 0, buf, 0, cTemp);
|
||||
Xor(cTemp, 0, kDelta, 0, c);
|
||||
engine.ProcessBlock(c, 0, c, 0);
|
||||
if (macSize + outOff > output.Length)
|
||||
{
|
||||
throw new DataLengthException("Output buffer too short");
|
||||
}
|
||||
Array.Copy(c, 0, output, outOff, macSize);
|
||||
return macSize;
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
Arrays.Fill(c, 0);
|
||||
Arrays.Fill(cTemp, 0);
|
||||
Arrays.Fill(kDelta, 0);
|
||||
Arrays.Fill(buf, 0);
|
||||
engine.Reset();
|
||||
engine.ProcessBlock(kDelta, 0, kDelta, 0);
|
||||
bufOff = 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
using System;
|
||||
using Org.BouncyCastle.Crypto.Modes;
|
||||
using Org.BouncyCastle.Crypto.Parameters;
|
||||
|
||||
namespace Org.BouncyCastle.Crypto.Macs;
|
||||
|
||||
public class GMac : IMac
|
||||
{
|
||||
private readonly GcmBlockCipher cipher;
|
||||
|
||||
private readonly int macSizeBits;
|
||||
|
||||
public string AlgorithmName => cipher.GetUnderlyingCipher().AlgorithmName + "-GMAC";
|
||||
|
||||
public GMac(GcmBlockCipher cipher)
|
||||
: this(cipher, 128)
|
||||
{
|
||||
}
|
||||
|
||||
public GMac(GcmBlockCipher cipher, int macSizeBits)
|
||||
{
|
||||
this.cipher = cipher;
|
||||
this.macSizeBits = macSizeBits;
|
||||
}
|
||||
|
||||
public void Init(ICipherParameters parameters)
|
||||
{
|
||||
if (parameters is ParametersWithIV)
|
||||
{
|
||||
ParametersWithIV parametersWithIV = (ParametersWithIV)parameters;
|
||||
byte[] iV = parametersWithIV.GetIV();
|
||||
KeyParameter key = (KeyParameter)parametersWithIV.Parameters;
|
||||
cipher.Init(forEncryption: true, new AeadParameters(key, macSizeBits, iV));
|
||||
return;
|
||||
}
|
||||
throw new ArgumentException("GMAC requires ParametersWithIV");
|
||||
}
|
||||
|
||||
public int GetMacSize()
|
||||
{
|
||||
return macSizeBits / 8;
|
||||
}
|
||||
|
||||
public void Update(byte input)
|
||||
{
|
||||
cipher.ProcessAadByte(input);
|
||||
}
|
||||
|
||||
public void BlockUpdate(byte[] input, int inOff, int len)
|
||||
{
|
||||
cipher.ProcessAadBytes(input, inOff, len);
|
||||
}
|
||||
|
||||
public int DoFinal(byte[] output, int outOff)
|
||||
{
|
||||
try
|
||||
{
|
||||
return cipher.DoFinal(output, outOff);
|
||||
}
|
||||
catch (InvalidCipherTextException ex)
|
||||
{
|
||||
throw new InvalidOperationException(ex.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
cipher.Reset();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,250 @@
|
||||
using System;
|
||||
using Org.BouncyCastle.Crypto.Parameters;
|
||||
using Org.BouncyCastle.Utilities;
|
||||
|
||||
namespace Org.BouncyCastle.Crypto.Macs;
|
||||
|
||||
public class Gost28147Mac : IMac
|
||||
{
|
||||
private const int blockSize = 8;
|
||||
|
||||
private const int macSize = 4;
|
||||
|
||||
private int bufOff;
|
||||
|
||||
private byte[] buf;
|
||||
|
||||
private byte[] mac;
|
||||
|
||||
private bool firstStep = true;
|
||||
|
||||
private int[] workingKey;
|
||||
|
||||
private byte[] macIV = null;
|
||||
|
||||
private byte[] S = new byte[128]
|
||||
{
|
||||
9, 6, 3, 2, 8, 11, 1, 7, 10, 4,
|
||||
14, 15, 12, 0, 13, 5, 3, 7, 14, 9,
|
||||
8, 10, 15, 0, 5, 2, 6, 12, 11, 4,
|
||||
13, 1, 14, 4, 6, 2, 11, 3, 13, 8,
|
||||
12, 15, 5, 10, 0, 7, 1, 9, 14, 7,
|
||||
10, 12, 13, 1, 3, 9, 0, 2, 11, 4,
|
||||
15, 8, 5, 6, 11, 5, 1, 9, 8, 13,
|
||||
15, 0, 14, 4, 2, 3, 12, 7, 10, 6,
|
||||
3, 10, 13, 12, 1, 2, 0, 11, 7, 5,
|
||||
9, 4, 8, 15, 14, 6, 1, 13, 2, 9,
|
||||
7, 10, 6, 0, 8, 12, 4, 5, 15, 3,
|
||||
11, 14, 11, 10, 15, 5, 0, 12, 14, 8,
|
||||
6, 2, 3, 9, 1, 7, 13, 4
|
||||
};
|
||||
|
||||
public string AlgorithmName => "Gost28147Mac";
|
||||
|
||||
public Gost28147Mac()
|
||||
{
|
||||
mac = new byte[8];
|
||||
buf = new byte[8];
|
||||
bufOff = 0;
|
||||
}
|
||||
|
||||
private static int[] GenerateWorkingKey(byte[] userKey)
|
||||
{
|
||||
if (userKey.Length != 32)
|
||||
{
|
||||
throw new ArgumentException("Key length invalid. Key needs to be 32 byte - 256 bit!!!");
|
||||
}
|
||||
int[] array = new int[8];
|
||||
for (int i = 0; i != 8; i++)
|
||||
{
|
||||
array[i] = bytesToint(userKey, i * 4);
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
public void Init(ICipherParameters parameters)
|
||||
{
|
||||
Reset();
|
||||
buf = new byte[8];
|
||||
macIV = null;
|
||||
if (parameters is ParametersWithSBox)
|
||||
{
|
||||
ParametersWithSBox parametersWithSBox = (ParametersWithSBox)parameters;
|
||||
parametersWithSBox.GetSBox().CopyTo(S, 0);
|
||||
if (parametersWithSBox.Parameters != null)
|
||||
{
|
||||
workingKey = GenerateWorkingKey(((KeyParameter)parametersWithSBox.Parameters).GetKey());
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (parameters is KeyParameter)
|
||||
{
|
||||
workingKey = GenerateWorkingKey(((KeyParameter)parameters).GetKey());
|
||||
return;
|
||||
}
|
||||
if (parameters is ParametersWithIV)
|
||||
{
|
||||
ParametersWithIV parametersWithIV = (ParametersWithIV)parameters;
|
||||
workingKey = GenerateWorkingKey(((KeyParameter)parametersWithIV.Parameters).GetKey());
|
||||
Array.Copy(parametersWithIV.GetIV(), 0, mac, 0, mac.Length);
|
||||
macIV = parametersWithIV.GetIV();
|
||||
return;
|
||||
}
|
||||
throw new ArgumentException("invalid parameter passed to Gost28147 init - " + Platform.GetTypeName(parameters));
|
||||
}
|
||||
|
||||
public int GetMacSize()
|
||||
{
|
||||
return 4;
|
||||
}
|
||||
|
||||
private int gost28147_mainStep(int n1, int key)
|
||||
{
|
||||
int num = key + n1;
|
||||
int num2 = S[num & 0xF];
|
||||
num2 += S[16 + ((num >> 4) & 0xF)] << 4;
|
||||
num2 += S[32 + ((num >> 8) & 0xF)] << 8;
|
||||
num2 += S[48 + ((num >> 12) & 0xF)] << 12;
|
||||
num2 += S[64 + ((num >> 16) & 0xF)] << 16;
|
||||
num2 += S[80 + ((num >> 20) & 0xF)] << 20;
|
||||
num2 += S[96 + ((num >> 24) & 0xF)] << 24;
|
||||
num2 += S[112 + ((num >> 28) & 0xF)] << 28;
|
||||
int num3 = num2 << 11;
|
||||
int num4 = num2 >>> 21;
|
||||
return num3 | num4;
|
||||
}
|
||||
|
||||
private void gost28147MacFunc(int[] workingKey, byte[] input, int inOff, byte[] output, int outOff)
|
||||
{
|
||||
int num = bytesToint(input, inOff);
|
||||
int num2 = bytesToint(input, inOff + 4);
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
for (int j = 0; j < 8; j++)
|
||||
{
|
||||
int num3 = num;
|
||||
num = num2 ^ gost28147_mainStep(num, workingKey[j]);
|
||||
num2 = num3;
|
||||
}
|
||||
}
|
||||
intTobytes(num, output, outOff);
|
||||
intTobytes(num2, output, outOff + 4);
|
||||
}
|
||||
|
||||
private static int bytesToint(byte[] input, int inOff)
|
||||
{
|
||||
return (int)((input[inOff + 3] << 24) & 0xFF000000u) + ((input[inOff + 2] << 16) & 0xFF0000) + ((input[inOff + 1] << 8) & 0xFF00) + (input[inOff] & 0xFF);
|
||||
}
|
||||
|
||||
private static void intTobytes(int num, byte[] output, int outOff)
|
||||
{
|
||||
output[outOff + 3] = (byte)(num >> 24);
|
||||
output[outOff + 2] = (byte)(num >> 16);
|
||||
output[outOff + 1] = (byte)(num >> 8);
|
||||
output[outOff] = (byte)num;
|
||||
}
|
||||
|
||||
private static byte[] CM5func(byte[] buf, int bufOff, byte[] mac)
|
||||
{
|
||||
byte[] array = new byte[buf.Length - bufOff];
|
||||
Array.Copy(buf, bufOff, array, 0, mac.Length);
|
||||
for (int i = 0; i != mac.Length; i++)
|
||||
{
|
||||
array[i] ^= mac[i];
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
public void Update(byte input)
|
||||
{
|
||||
if (bufOff == buf.Length)
|
||||
{
|
||||
byte[] array = new byte[buf.Length];
|
||||
Array.Copy(buf, 0, array, 0, mac.Length);
|
||||
if (firstStep)
|
||||
{
|
||||
firstStep = false;
|
||||
if (macIV != null)
|
||||
{
|
||||
array = CM5func(buf, 0, macIV);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
array = CM5func(buf, 0, mac);
|
||||
}
|
||||
gost28147MacFunc(workingKey, array, 0, mac, 0);
|
||||
bufOff = 0;
|
||||
}
|
||||
buf[bufOff++] = input;
|
||||
}
|
||||
|
||||
public void BlockUpdate(byte[] input, int inOff, int len)
|
||||
{
|
||||
if (len < 0)
|
||||
{
|
||||
throw new ArgumentException("Can't have a negative input length!");
|
||||
}
|
||||
int num = 8 - bufOff;
|
||||
if (len > num)
|
||||
{
|
||||
Array.Copy(input, inOff, buf, bufOff, num);
|
||||
byte[] array = new byte[buf.Length];
|
||||
Array.Copy(buf, 0, array, 0, mac.Length);
|
||||
if (firstStep)
|
||||
{
|
||||
firstStep = false;
|
||||
if (macIV != null)
|
||||
{
|
||||
array = CM5func(buf, 0, macIV);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
array = CM5func(buf, 0, mac);
|
||||
}
|
||||
gost28147MacFunc(workingKey, array, 0, mac, 0);
|
||||
bufOff = 0;
|
||||
len -= num;
|
||||
inOff += num;
|
||||
while (len > 8)
|
||||
{
|
||||
array = CM5func(input, inOff, mac);
|
||||
gost28147MacFunc(workingKey, array, 0, mac, 0);
|
||||
len -= 8;
|
||||
inOff += 8;
|
||||
}
|
||||
}
|
||||
Array.Copy(input, inOff, buf, bufOff, len);
|
||||
bufOff += len;
|
||||
}
|
||||
|
||||
public int DoFinal(byte[] output, int outOff)
|
||||
{
|
||||
while (bufOff < 8)
|
||||
{
|
||||
buf[bufOff++] = 0;
|
||||
}
|
||||
byte[] array = new byte[buf.Length];
|
||||
Array.Copy(buf, 0, array, 0, mac.Length);
|
||||
if (firstStep)
|
||||
{
|
||||
firstStep = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
array = CM5func(buf, 0, mac);
|
||||
}
|
||||
gost28147MacFunc(workingKey, array, 0, mac, 0);
|
||||
Array.Copy(mac, mac.Length / 2 - 4, output, outOff, 4);
|
||||
Reset();
|
||||
return 4;
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
Array.Clear(buf, 0, buf.Length);
|
||||
bufOff = 0;
|
||||
firstStep = true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,131 @@
|
||||
using System;
|
||||
using Org.BouncyCastle.Crypto.Parameters;
|
||||
using Org.BouncyCastle.Utilities;
|
||||
|
||||
namespace Org.BouncyCastle.Crypto.Macs;
|
||||
|
||||
public class HMac : IMac
|
||||
{
|
||||
private const byte IPAD = 54;
|
||||
|
||||
private const byte OPAD = 92;
|
||||
|
||||
private readonly IDigest digest;
|
||||
|
||||
private readonly int digestSize;
|
||||
|
||||
private readonly int blockLength;
|
||||
|
||||
private IMemoable ipadState;
|
||||
|
||||
private IMemoable opadState;
|
||||
|
||||
private readonly byte[] inputPad;
|
||||
|
||||
private readonly byte[] outputBuf;
|
||||
|
||||
public virtual string AlgorithmName => digest.AlgorithmName + "/HMAC";
|
||||
|
||||
public HMac(IDigest digest)
|
||||
{
|
||||
this.digest = digest;
|
||||
digestSize = digest.GetDigestSize();
|
||||
blockLength = digest.GetByteLength();
|
||||
inputPad = new byte[blockLength];
|
||||
outputBuf = new byte[blockLength + digestSize];
|
||||
}
|
||||
|
||||
public virtual IDigest GetUnderlyingDigest()
|
||||
{
|
||||
return digest;
|
||||
}
|
||||
|
||||
public virtual void Init(ICipherParameters parameters)
|
||||
{
|
||||
digest.Reset();
|
||||
byte[] key = ((KeyParameter)parameters).GetKey();
|
||||
int num = key.Length;
|
||||
if (num > blockLength)
|
||||
{
|
||||
digest.BlockUpdate(key, 0, num);
|
||||
digest.DoFinal(inputPad, 0);
|
||||
num = digestSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
Array.Copy(key, 0, inputPad, 0, num);
|
||||
}
|
||||
Array.Clear(inputPad, num, blockLength - num);
|
||||
Array.Copy(inputPad, 0, outputBuf, 0, blockLength);
|
||||
XorPad(inputPad, blockLength, 54);
|
||||
XorPad(outputBuf, blockLength, 92);
|
||||
if (digest is IMemoable)
|
||||
{
|
||||
opadState = ((IMemoable)digest).Copy();
|
||||
((IDigest)opadState).BlockUpdate(outputBuf, 0, blockLength);
|
||||
}
|
||||
digest.BlockUpdate(inputPad, 0, inputPad.Length);
|
||||
if (digest is IMemoable)
|
||||
{
|
||||
ipadState = ((IMemoable)digest).Copy();
|
||||
}
|
||||
}
|
||||
|
||||
public virtual int GetMacSize()
|
||||
{
|
||||
return digestSize;
|
||||
}
|
||||
|
||||
public virtual void Update(byte input)
|
||||
{
|
||||
digest.Update(input);
|
||||
}
|
||||
|
||||
public virtual void BlockUpdate(byte[] input, int inOff, int len)
|
||||
{
|
||||
digest.BlockUpdate(input, inOff, len);
|
||||
}
|
||||
|
||||
public virtual int DoFinal(byte[] output, int outOff)
|
||||
{
|
||||
digest.DoFinal(outputBuf, blockLength);
|
||||
if (opadState != null)
|
||||
{
|
||||
((IMemoable)digest).Reset(opadState);
|
||||
digest.BlockUpdate(outputBuf, blockLength, digest.GetDigestSize());
|
||||
}
|
||||
else
|
||||
{
|
||||
digest.BlockUpdate(outputBuf, 0, outputBuf.Length);
|
||||
}
|
||||
int result = digest.DoFinal(output, outOff);
|
||||
Array.Clear(outputBuf, blockLength, digestSize);
|
||||
if (ipadState != null)
|
||||
{
|
||||
((IMemoable)digest).Reset(ipadState);
|
||||
}
|
||||
else
|
||||
{
|
||||
digest.BlockUpdate(inputPad, 0, inputPad.Length);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public virtual void Reset()
|
||||
{
|
||||
digest.Reset();
|
||||
digest.BlockUpdate(inputPad, 0, inputPad.Length);
|
||||
}
|
||||
|
||||
private static void XorPad(byte[] pad, int len, byte n)
|
||||
{
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
byte[] array2;
|
||||
byte[] array = (array2 = pad);
|
||||
int num = i;
|
||||
nint num2 = num;
|
||||
array[num] = (byte)(array2[num2] ^ n);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,176 @@
|
||||
using System;
|
||||
using Org.BouncyCastle.Crypto.Engines;
|
||||
using Org.BouncyCastle.Crypto.Modes;
|
||||
using Org.BouncyCastle.Crypto.Paddings;
|
||||
using Org.BouncyCastle.Crypto.Parameters;
|
||||
|
||||
namespace Org.BouncyCastle.Crypto.Macs;
|
||||
|
||||
public class ISO9797Alg3Mac : IMac
|
||||
{
|
||||
private byte[] mac;
|
||||
|
||||
private byte[] buf;
|
||||
|
||||
private int bufOff;
|
||||
|
||||
private IBlockCipher cipher;
|
||||
|
||||
private IBlockCipherPadding padding;
|
||||
|
||||
private int macSize;
|
||||
|
||||
private KeyParameter lastKey2;
|
||||
|
||||
private KeyParameter lastKey3;
|
||||
|
||||
public string AlgorithmName => "ISO9797Alg3";
|
||||
|
||||
public ISO9797Alg3Mac(IBlockCipher cipher)
|
||||
: this(cipher, cipher.GetBlockSize() * 8, null)
|
||||
{
|
||||
}
|
||||
|
||||
public ISO9797Alg3Mac(IBlockCipher cipher, IBlockCipherPadding padding)
|
||||
: this(cipher, cipher.GetBlockSize() * 8, padding)
|
||||
{
|
||||
}
|
||||
|
||||
public ISO9797Alg3Mac(IBlockCipher cipher, int macSizeInBits)
|
||||
: this(cipher, macSizeInBits, null)
|
||||
{
|
||||
}
|
||||
|
||||
public ISO9797Alg3Mac(IBlockCipher cipher, int macSizeInBits, IBlockCipherPadding padding)
|
||||
{
|
||||
if (macSizeInBits % 8 != 0)
|
||||
{
|
||||
throw new ArgumentException("MAC size must be multiple of 8");
|
||||
}
|
||||
if (!(cipher is DesEngine))
|
||||
{
|
||||
throw new ArgumentException("cipher must be instance of DesEngine");
|
||||
}
|
||||
this.cipher = new CbcBlockCipher(cipher);
|
||||
this.padding = padding;
|
||||
macSize = macSizeInBits / 8;
|
||||
mac = new byte[cipher.GetBlockSize()];
|
||||
buf = new byte[cipher.GetBlockSize()];
|
||||
bufOff = 0;
|
||||
}
|
||||
|
||||
public void Init(ICipherParameters parameters)
|
||||
{
|
||||
Reset();
|
||||
if (!(parameters is KeyParameter) && !(parameters is ParametersWithIV))
|
||||
{
|
||||
throw new ArgumentException("parameters must be an instance of KeyParameter or ParametersWithIV");
|
||||
}
|
||||
KeyParameter keyParameter = ((!(parameters is KeyParameter)) ? ((KeyParameter)((ParametersWithIV)parameters).Parameters) : ((KeyParameter)parameters));
|
||||
byte[] key = keyParameter.GetKey();
|
||||
KeyParameter parameters2;
|
||||
if (key.Length == 16)
|
||||
{
|
||||
parameters2 = new KeyParameter(key, 0, 8);
|
||||
lastKey2 = new KeyParameter(key, 8, 8);
|
||||
lastKey3 = parameters2;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (key.Length != 24)
|
||||
{
|
||||
throw new ArgumentException("Key must be either 112 or 168 bit long");
|
||||
}
|
||||
parameters2 = new KeyParameter(key, 0, 8);
|
||||
lastKey2 = new KeyParameter(key, 8, 8);
|
||||
lastKey3 = new KeyParameter(key, 16, 8);
|
||||
}
|
||||
if (parameters is ParametersWithIV)
|
||||
{
|
||||
cipher.Init(forEncryption: true, new ParametersWithIV(parameters2, ((ParametersWithIV)parameters).GetIV()));
|
||||
}
|
||||
else
|
||||
{
|
||||
cipher.Init(forEncryption: true, parameters2);
|
||||
}
|
||||
}
|
||||
|
||||
public int GetMacSize()
|
||||
{
|
||||
return macSize;
|
||||
}
|
||||
|
||||
public void Update(byte input)
|
||||
{
|
||||
if (bufOff == buf.Length)
|
||||
{
|
||||
cipher.ProcessBlock(buf, 0, mac, 0);
|
||||
bufOff = 0;
|
||||
}
|
||||
buf[bufOff++] = input;
|
||||
}
|
||||
|
||||
public void BlockUpdate(byte[] input, int inOff, int len)
|
||||
{
|
||||
if (len < 0)
|
||||
{
|
||||
throw new ArgumentException("Can't have a negative input length!");
|
||||
}
|
||||
int blockSize = cipher.GetBlockSize();
|
||||
int num = 0;
|
||||
int num2 = blockSize - bufOff;
|
||||
if (len > num2)
|
||||
{
|
||||
Array.Copy(input, inOff, buf, bufOff, num2);
|
||||
num += cipher.ProcessBlock(buf, 0, mac, 0);
|
||||
bufOff = 0;
|
||||
len -= num2;
|
||||
inOff += num2;
|
||||
while (len > blockSize)
|
||||
{
|
||||
num += cipher.ProcessBlock(input, inOff, mac, 0);
|
||||
len -= blockSize;
|
||||
inOff += blockSize;
|
||||
}
|
||||
}
|
||||
Array.Copy(input, inOff, buf, bufOff, len);
|
||||
bufOff += len;
|
||||
}
|
||||
|
||||
public int DoFinal(byte[] output, int outOff)
|
||||
{
|
||||
int blockSize = cipher.GetBlockSize();
|
||||
if (padding == null)
|
||||
{
|
||||
while (bufOff < blockSize)
|
||||
{
|
||||
buf[bufOff++] = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (bufOff == blockSize)
|
||||
{
|
||||
cipher.ProcessBlock(buf, 0, mac, 0);
|
||||
bufOff = 0;
|
||||
}
|
||||
padding.AddPadding(buf, bufOff);
|
||||
}
|
||||
cipher.ProcessBlock(buf, 0, mac, 0);
|
||||
DesEngine desEngine = new DesEngine();
|
||||
desEngine.Init(forEncryption: false, lastKey2);
|
||||
desEngine.ProcessBlock(mac, 0, mac, 0);
|
||||
desEngine.Init(forEncryption: true, lastKey3);
|
||||
desEngine.ProcessBlock(mac, 0, mac, 0);
|
||||
Array.Copy(mac, 0, output, outOff, macSize);
|
||||
Reset();
|
||||
return macSize;
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
Array.Clear(buf, 0, buf.Length);
|
||||
bufOff = 0;
|
||||
cipher.Reset();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
using System;
|
||||
using Org.BouncyCastle.Crypto.Parameters;
|
||||
|
||||
namespace Org.BouncyCastle.Crypto.Macs;
|
||||
|
||||
internal class MacCFBBlockCipher : IBlockCipher
|
||||
{
|
||||
private byte[] IV;
|
||||
|
||||
private byte[] cfbV;
|
||||
|
||||
private byte[] cfbOutV;
|
||||
|
||||
private readonly int blockSize;
|
||||
|
||||
private readonly IBlockCipher cipher;
|
||||
|
||||
public string AlgorithmName => cipher.AlgorithmName + "/CFB" + blockSize * 8;
|
||||
|
||||
public bool IsPartialBlockOkay => true;
|
||||
|
||||
public MacCFBBlockCipher(IBlockCipher cipher, int bitBlockSize)
|
||||
{
|
||||
this.cipher = cipher;
|
||||
blockSize = bitBlockSize / 8;
|
||||
IV = new byte[cipher.GetBlockSize()];
|
||||
cfbV = new byte[cipher.GetBlockSize()];
|
||||
cfbOutV = new byte[cipher.GetBlockSize()];
|
||||
}
|
||||
|
||||
public void Init(bool forEncryption, ICipherParameters parameters)
|
||||
{
|
||||
if (parameters is ParametersWithIV)
|
||||
{
|
||||
ParametersWithIV parametersWithIV = (ParametersWithIV)parameters;
|
||||
byte[] iV = parametersWithIV.GetIV();
|
||||
if (iV.Length < IV.Length)
|
||||
{
|
||||
Array.Copy(iV, 0, IV, IV.Length - iV.Length, iV.Length);
|
||||
}
|
||||
else
|
||||
{
|
||||
Array.Copy(iV, 0, IV, 0, IV.Length);
|
||||
}
|
||||
parameters = parametersWithIV.Parameters;
|
||||
}
|
||||
Reset();
|
||||
cipher.Init(forEncryption: true, parameters);
|
||||
}
|
||||
|
||||
public int GetBlockSize()
|
||||
{
|
||||
return blockSize;
|
||||
}
|
||||
|
||||
public int ProcessBlock(byte[] input, int inOff, byte[] outBytes, int outOff)
|
||||
{
|
||||
if (inOff + blockSize > input.Length)
|
||||
{
|
||||
throw new DataLengthException("input buffer too short");
|
||||
}
|
||||
if (outOff + blockSize > outBytes.Length)
|
||||
{
|
||||
throw new DataLengthException("output buffer too short");
|
||||
}
|
||||
cipher.ProcessBlock(cfbV, 0, cfbOutV, 0);
|
||||
for (int i = 0; i < blockSize; i++)
|
||||
{
|
||||
outBytes[outOff + i] = (byte)(cfbOutV[i] ^ input[inOff + i]);
|
||||
}
|
||||
Array.Copy(cfbV, blockSize, cfbV, 0, cfbV.Length - blockSize);
|
||||
Array.Copy(outBytes, outOff, cfbV, cfbV.Length - blockSize, blockSize);
|
||||
return blockSize;
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
IV.CopyTo(cfbV, 0);
|
||||
cipher.Reset();
|
||||
}
|
||||
|
||||
public void GetMacBlock(byte[] mac)
|
||||
{
|
||||
cipher.ProcessBlock(cfbV, 0, mac, 0);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,280 @@
|
||||
using System;
|
||||
using Org.BouncyCastle.Crypto.Parameters;
|
||||
using Org.BouncyCastle.Crypto.Utilities;
|
||||
|
||||
namespace Org.BouncyCastle.Crypto.Macs;
|
||||
|
||||
public class Poly1305 : IMac
|
||||
{
|
||||
private const int BlockSize = 16;
|
||||
|
||||
private readonly IBlockCipher cipher;
|
||||
|
||||
private readonly byte[] singleByte = new byte[1];
|
||||
|
||||
private uint r0;
|
||||
|
||||
private uint r1;
|
||||
|
||||
private uint r2;
|
||||
|
||||
private uint r3;
|
||||
|
||||
private uint r4;
|
||||
|
||||
private uint s1;
|
||||
|
||||
private uint s2;
|
||||
|
||||
private uint s3;
|
||||
|
||||
private uint s4;
|
||||
|
||||
private uint k0;
|
||||
|
||||
private uint k1;
|
||||
|
||||
private uint k2;
|
||||
|
||||
private uint k3;
|
||||
|
||||
private byte[] currentBlock = new byte[16];
|
||||
|
||||
private int currentBlockOffset = 0;
|
||||
|
||||
private uint h0;
|
||||
|
||||
private uint h1;
|
||||
|
||||
private uint h2;
|
||||
|
||||
private uint h3;
|
||||
|
||||
private uint h4;
|
||||
|
||||
public string AlgorithmName
|
||||
{
|
||||
get
|
||||
{
|
||||
if (cipher != null)
|
||||
{
|
||||
return "Poly1305-" + cipher.AlgorithmName;
|
||||
}
|
||||
return "Poly1305";
|
||||
}
|
||||
}
|
||||
|
||||
public Poly1305()
|
||||
{
|
||||
cipher = null;
|
||||
}
|
||||
|
||||
public Poly1305(IBlockCipher cipher)
|
||||
{
|
||||
if (cipher.GetBlockSize() != 16)
|
||||
{
|
||||
throw new ArgumentException("Poly1305 requires a 128 bit block cipher.");
|
||||
}
|
||||
this.cipher = cipher;
|
||||
}
|
||||
|
||||
public void Init(ICipherParameters parameters)
|
||||
{
|
||||
byte[] nonce = null;
|
||||
if (cipher != null)
|
||||
{
|
||||
if (!(parameters is ParametersWithIV))
|
||||
{
|
||||
throw new ArgumentException("Poly1305 requires an IV when used with a block cipher.", "parameters");
|
||||
}
|
||||
ParametersWithIV parametersWithIV = (ParametersWithIV)parameters;
|
||||
nonce = parametersWithIV.GetIV();
|
||||
parameters = parametersWithIV.Parameters;
|
||||
}
|
||||
if (!(parameters is KeyParameter))
|
||||
{
|
||||
throw new ArgumentException("Poly1305 requires a key.");
|
||||
}
|
||||
KeyParameter keyParameter = (KeyParameter)parameters;
|
||||
SetKey(keyParameter.GetKey(), nonce);
|
||||
Reset();
|
||||
}
|
||||
|
||||
private void SetKey(byte[] key, byte[] nonce)
|
||||
{
|
||||
if (key.Length != 32)
|
||||
{
|
||||
throw new ArgumentException("Poly1305 key must be 256 bits.");
|
||||
}
|
||||
if (cipher != null && (nonce == null || nonce.Length != 16))
|
||||
{
|
||||
throw new ArgumentException("Poly1305 requires a 128 bit IV.");
|
||||
}
|
||||
uint num = Pack.LE_To_UInt32(key, 0);
|
||||
uint num2 = Pack.LE_To_UInt32(key, 4);
|
||||
uint num3 = Pack.LE_To_UInt32(key, 8);
|
||||
uint num4 = Pack.LE_To_UInt32(key, 12);
|
||||
r0 = num & 0x3FFFFFF;
|
||||
r1 = ((num >> 26) | (num2 << 6)) & 0x3FFFF03;
|
||||
r2 = ((num2 >> 20) | (num3 << 12)) & 0x3FFC0FF;
|
||||
r3 = ((num3 >> 14) | (num4 << 18)) & 0x3F03FFF;
|
||||
r4 = (num4 >> 8) & 0xFFFFF;
|
||||
s1 = r1 * 5;
|
||||
s2 = r2 * 5;
|
||||
s3 = r3 * 5;
|
||||
s4 = r4 * 5;
|
||||
byte[] array;
|
||||
int num5;
|
||||
if (cipher == null)
|
||||
{
|
||||
array = key;
|
||||
num5 = 16;
|
||||
}
|
||||
else
|
||||
{
|
||||
array = new byte[16];
|
||||
num5 = 0;
|
||||
cipher.Init(forEncryption: true, new KeyParameter(key, 16, 16));
|
||||
cipher.ProcessBlock(nonce, 0, array, 0);
|
||||
}
|
||||
k0 = Pack.LE_To_UInt32(array, num5);
|
||||
k1 = Pack.LE_To_UInt32(array, num5 + 4);
|
||||
k2 = Pack.LE_To_UInt32(array, num5 + 8);
|
||||
k3 = Pack.LE_To_UInt32(array, num5 + 12);
|
||||
}
|
||||
|
||||
public int GetMacSize()
|
||||
{
|
||||
return 16;
|
||||
}
|
||||
|
||||
public void Update(byte input)
|
||||
{
|
||||
singleByte[0] = input;
|
||||
BlockUpdate(singleByte, 0, 1);
|
||||
}
|
||||
|
||||
public void BlockUpdate(byte[] input, int inOff, int len)
|
||||
{
|
||||
int num = 0;
|
||||
while (len > num)
|
||||
{
|
||||
if (currentBlockOffset == 16)
|
||||
{
|
||||
ProcessBlock();
|
||||
currentBlockOffset = 0;
|
||||
}
|
||||
int num2 = System.Math.Min(len - num, 16 - currentBlockOffset);
|
||||
Array.Copy(input, num + inOff, currentBlock, currentBlockOffset, num2);
|
||||
num += num2;
|
||||
currentBlockOffset += num2;
|
||||
}
|
||||
}
|
||||
|
||||
private void ProcessBlock()
|
||||
{
|
||||
if (currentBlockOffset < 16)
|
||||
{
|
||||
currentBlock[currentBlockOffset] = 1;
|
||||
for (int i = currentBlockOffset + 1; i < 16; i++)
|
||||
{
|
||||
currentBlock[i] = 0;
|
||||
}
|
||||
}
|
||||
ulong num = Pack.LE_To_UInt32(currentBlock, 0);
|
||||
ulong num2 = Pack.LE_To_UInt32(currentBlock, 4);
|
||||
ulong num3 = Pack.LE_To_UInt32(currentBlock, 8);
|
||||
ulong num4 = Pack.LE_To_UInt32(currentBlock, 12);
|
||||
h0 += (uint)(int)(num & 0x3FFFFFF);
|
||||
h1 += (uint)(int)((((num2 << 32) | num) >> 26) & 0x3FFFFFF);
|
||||
h2 += (uint)(int)((((num3 << 32) | num2) >> 20) & 0x3FFFFFF);
|
||||
h3 += (uint)(int)((((num4 << 32) | num3) >> 14) & 0x3FFFFFF);
|
||||
h4 += (uint)(int)(num4 >> 8);
|
||||
if (currentBlockOffset == 16)
|
||||
{
|
||||
h4 += 16777216u;
|
||||
}
|
||||
ulong num5 = mul32x32_64(h0, r0) + mul32x32_64(h1, s4) + mul32x32_64(h2, s3) + mul32x32_64(h3, s2) + mul32x32_64(h4, s1);
|
||||
ulong num6 = mul32x32_64(h0, r1) + mul32x32_64(h1, r0) + mul32x32_64(h2, s4) + mul32x32_64(h3, s3) + mul32x32_64(h4, s2);
|
||||
ulong num7 = mul32x32_64(h0, r2) + mul32x32_64(h1, r1) + mul32x32_64(h2, r0) + mul32x32_64(h3, s4) + mul32x32_64(h4, s3);
|
||||
ulong num8 = mul32x32_64(h0, r3) + mul32x32_64(h1, r2) + mul32x32_64(h2, r1) + mul32x32_64(h3, r0) + mul32x32_64(h4, s4);
|
||||
ulong num9 = mul32x32_64(h0, r4) + mul32x32_64(h1, r3) + mul32x32_64(h2, r2) + mul32x32_64(h3, r1) + mul32x32_64(h4, r0);
|
||||
h0 = (uint)((int)num5 & 0x3FFFFFF);
|
||||
num6 += num5 >> 26;
|
||||
h1 = (uint)((int)num6 & 0x3FFFFFF);
|
||||
num7 += num6 >> 26;
|
||||
h2 = (uint)((int)num7 & 0x3FFFFFF);
|
||||
num8 += num7 >> 26;
|
||||
h3 = (uint)((int)num8 & 0x3FFFFFF);
|
||||
num9 += num8 >> 26;
|
||||
h4 = (uint)((int)num9 & 0x3FFFFFF);
|
||||
h0 += (uint)((int)(num9 >> 26) * 5);
|
||||
h1 += h0 >> 26;
|
||||
h0 &= 67108863u;
|
||||
}
|
||||
|
||||
public int DoFinal(byte[] output, int outOff)
|
||||
{
|
||||
Check.DataLength(output, outOff, 16, "Output buffer is too short.");
|
||||
if (currentBlockOffset > 0)
|
||||
{
|
||||
ProcessBlock();
|
||||
}
|
||||
h1 += h0 >> 26;
|
||||
h0 &= 67108863u;
|
||||
h2 += h1 >> 26;
|
||||
h1 &= 67108863u;
|
||||
h3 += h2 >> 26;
|
||||
h2 &= 67108863u;
|
||||
h4 += h3 >> 26;
|
||||
h3 &= 67108863u;
|
||||
h0 += (h4 >> 26) * 5;
|
||||
h4 &= 67108863u;
|
||||
h1 += h0 >> 26;
|
||||
h0 &= 67108863u;
|
||||
uint num = h0 + 5;
|
||||
uint num2 = num >> 26;
|
||||
num &= 0x3FFFFFF;
|
||||
uint num3 = h1 + num2;
|
||||
num2 = num3 >> 26;
|
||||
num3 &= 0x3FFFFFF;
|
||||
uint num4 = h2 + num2;
|
||||
num2 = num4 >> 26;
|
||||
num4 &= 0x3FFFFFF;
|
||||
uint num5 = h3 + num2;
|
||||
num2 = num5 >> 26;
|
||||
num5 &= 0x3FFFFFF;
|
||||
uint num6 = h4 + num2 - 67108864;
|
||||
num2 = (num6 >> 31) - 1;
|
||||
uint num7 = ~num2;
|
||||
h0 = (h0 & num7) | (num & num2);
|
||||
h1 = (h1 & num7) | (num3 & num2);
|
||||
h2 = (h2 & num7) | (num4 & num2);
|
||||
h3 = (h3 & num7) | (num5 & num2);
|
||||
h4 = (h4 & num7) | (num6 & num2);
|
||||
ulong num8 = (ulong)(h0 | (h1 << 26)) + (ulong)k0;
|
||||
ulong num9 = (ulong)((h1 >> 6) | (h2 << 20)) + (ulong)k1;
|
||||
ulong num10 = (ulong)((h2 >> 12) | (h3 << 14)) + (ulong)k2;
|
||||
ulong num11 = (ulong)((h3 >> 18) | (h4 << 8)) + (ulong)k3;
|
||||
Pack.UInt32_To_LE((uint)num8, output, outOff);
|
||||
num9 += num8 >> 32;
|
||||
Pack.UInt32_To_LE((uint)num9, output, outOff + 4);
|
||||
num10 += num9 >> 32;
|
||||
Pack.UInt32_To_LE((uint)num10, output, outOff + 8);
|
||||
num11 += num10 >> 32;
|
||||
Pack.UInt32_To_LE((uint)num11, output, outOff + 12);
|
||||
Reset();
|
||||
return 16;
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
currentBlockOffset = 0;
|
||||
h0 = (h1 = (h2 = (h3 = (h4 = 0u))));
|
||||
}
|
||||
|
||||
private static ulong mul32x32_64(uint i1, uint i2)
|
||||
{
|
||||
return (ulong)i1 * (ulong)i2;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,184 @@
|
||||
using System;
|
||||
using Org.BouncyCastle.Crypto.Parameters;
|
||||
using Org.BouncyCastle.Crypto.Utilities;
|
||||
|
||||
namespace Org.BouncyCastle.Crypto.Macs;
|
||||
|
||||
public class SipHash : IMac
|
||||
{
|
||||
protected readonly int c;
|
||||
|
||||
protected readonly int d;
|
||||
|
||||
protected long k0;
|
||||
|
||||
protected long k1;
|
||||
|
||||
protected long v0;
|
||||
|
||||
protected long v1;
|
||||
|
||||
protected long v2;
|
||||
|
||||
protected long v3;
|
||||
|
||||
protected long m = 0L;
|
||||
|
||||
protected int wordPos = 0;
|
||||
|
||||
protected int wordCount = 0;
|
||||
|
||||
public virtual string AlgorithmName => "SipHash-" + c + "-" + d;
|
||||
|
||||
public SipHash()
|
||||
: this(2, 4)
|
||||
{
|
||||
}
|
||||
|
||||
public SipHash(int c, int d)
|
||||
{
|
||||
this.c = c;
|
||||
this.d = d;
|
||||
}
|
||||
|
||||
public virtual int GetMacSize()
|
||||
{
|
||||
return 8;
|
||||
}
|
||||
|
||||
public virtual void Init(ICipherParameters parameters)
|
||||
{
|
||||
if (!(parameters is KeyParameter keyParameter))
|
||||
{
|
||||
throw new ArgumentException("must be an instance of KeyParameter", "parameters");
|
||||
}
|
||||
byte[] key = keyParameter.GetKey();
|
||||
if (key.Length != 16)
|
||||
{
|
||||
throw new ArgumentException("must be a 128-bit key", "parameters");
|
||||
}
|
||||
k0 = (long)Pack.LE_To_UInt64(key, 0);
|
||||
k1 = (long)Pack.LE_To_UInt64(key, 8);
|
||||
Reset();
|
||||
}
|
||||
|
||||
public virtual void Update(byte input)
|
||||
{
|
||||
m = (m >>> 8) | (long)((ulong)input << 56);
|
||||
if (++wordPos == 8)
|
||||
{
|
||||
ProcessMessageWord();
|
||||
wordPos = 0;
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void BlockUpdate(byte[] input, int offset, int length)
|
||||
{
|
||||
int i = 0;
|
||||
int num = length & -8;
|
||||
if (wordPos == 0)
|
||||
{
|
||||
for (; i < num; i += 8)
|
||||
{
|
||||
m = (long)Pack.LE_To_UInt64(input, offset + i);
|
||||
ProcessMessageWord();
|
||||
}
|
||||
for (; i < length; i++)
|
||||
{
|
||||
m = (m >>> 8) | (long)((ulong)input[offset + i] << 56);
|
||||
}
|
||||
wordPos = length - num;
|
||||
return;
|
||||
}
|
||||
int num2 = wordPos << 3;
|
||||
for (; i < num; i += 8)
|
||||
{
|
||||
ulong num3 = Pack.LE_To_UInt64(input, offset + i);
|
||||
m = (long)(num3 << num2) | (m >>> -num2);
|
||||
ProcessMessageWord();
|
||||
m = (long)num3;
|
||||
}
|
||||
for (; i < length; i++)
|
||||
{
|
||||
m = (m >>> 8) | (long)((ulong)input[offset + i] << 56);
|
||||
if (++wordPos == 8)
|
||||
{
|
||||
ProcessMessageWord();
|
||||
wordPos = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public virtual long DoFinal()
|
||||
{
|
||||
m >>>= 7 - wordPos << 3;
|
||||
m >>>= 8;
|
||||
m |= (long)((wordCount << 3) + wordPos) << 56;
|
||||
ProcessMessageWord();
|
||||
v2 ^= 255L;
|
||||
ApplySipRounds(d);
|
||||
long result = v0 ^ v1 ^ v2 ^ v3;
|
||||
Reset();
|
||||
return result;
|
||||
}
|
||||
|
||||
public virtual int DoFinal(byte[] output, int outOff)
|
||||
{
|
||||
long n = DoFinal();
|
||||
Pack.UInt64_To_LE((ulong)n, output, outOff);
|
||||
return 8;
|
||||
}
|
||||
|
||||
public virtual void Reset()
|
||||
{
|
||||
v0 = k0 ^ 0x736F6D6570736575L;
|
||||
v1 = k1 ^ 0x646F72616E646F6DL;
|
||||
v2 = k0 ^ 0x6C7967656E657261L;
|
||||
v3 = k1 ^ 0x7465646279746573L;
|
||||
m = 0L;
|
||||
wordPos = 0;
|
||||
wordCount = 0;
|
||||
}
|
||||
|
||||
protected virtual void ProcessMessageWord()
|
||||
{
|
||||
wordCount++;
|
||||
v3 ^= m;
|
||||
ApplySipRounds(c);
|
||||
v0 ^= m;
|
||||
}
|
||||
|
||||
protected virtual void ApplySipRounds(int n)
|
||||
{
|
||||
long num = v0;
|
||||
long num2 = v1;
|
||||
long num3 = v2;
|
||||
long num4 = v3;
|
||||
for (int i = 0; i < n; i++)
|
||||
{
|
||||
num += num2;
|
||||
num3 += num4;
|
||||
num2 = RotateLeft(num2, 13);
|
||||
num4 = RotateLeft(num4, 16);
|
||||
num2 ^= num;
|
||||
num4 ^= num3;
|
||||
num = RotateLeft(num, 32);
|
||||
num3 += num2;
|
||||
num += num4;
|
||||
num2 = RotateLeft(num2, 17);
|
||||
num4 = RotateLeft(num4, 21);
|
||||
num2 ^= num3;
|
||||
num4 ^= num;
|
||||
num3 = RotateLeft(num3, 32);
|
||||
}
|
||||
v0 = num;
|
||||
v1 = num2;
|
||||
v2 = num3;
|
||||
v3 = num4;
|
||||
}
|
||||
|
||||
protected static long RotateLeft(long x, int n)
|
||||
{
|
||||
return (x << n) | (x >>> -n);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
using System;
|
||||
using Org.BouncyCastle.Crypto.Digests;
|
||||
using Org.BouncyCastle.Crypto.Parameters;
|
||||
using Org.BouncyCastle.Utilities;
|
||||
|
||||
namespace Org.BouncyCastle.Crypto.Macs;
|
||||
|
||||
public class SkeinMac : IMac
|
||||
{
|
||||
public const int SKEIN_256 = 256;
|
||||
|
||||
public const int SKEIN_512 = 512;
|
||||
|
||||
public const int SKEIN_1024 = 1024;
|
||||
|
||||
private readonly SkeinEngine engine;
|
||||
|
||||
public string AlgorithmName => "Skein-MAC-" + engine.BlockSize * 8 + "-" + engine.OutputSize * 8;
|
||||
|
||||
public SkeinMac(int stateSizeBits, int digestSizeBits)
|
||||
{
|
||||
engine = new SkeinEngine(stateSizeBits, digestSizeBits);
|
||||
}
|
||||
|
||||
public SkeinMac(SkeinMac mac)
|
||||
{
|
||||
engine = new SkeinEngine(mac.engine);
|
||||
}
|
||||
|
||||
public void Init(ICipherParameters parameters)
|
||||
{
|
||||
SkeinParameters skeinParameters;
|
||||
if (parameters is SkeinParameters)
|
||||
{
|
||||
skeinParameters = (SkeinParameters)parameters;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!(parameters is KeyParameter))
|
||||
{
|
||||
throw new ArgumentException("Invalid parameter passed to Skein MAC init - " + Platform.GetTypeName(parameters));
|
||||
}
|
||||
skeinParameters = new SkeinParameters.Builder().SetKey(((KeyParameter)parameters).GetKey()).Build();
|
||||
}
|
||||
if (skeinParameters.GetKey() == null)
|
||||
{
|
||||
throw new ArgumentException("Skein MAC requires a key parameter.");
|
||||
}
|
||||
engine.Init(skeinParameters);
|
||||
}
|
||||
|
||||
public int GetMacSize()
|
||||
{
|
||||
return engine.OutputSize;
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
engine.Reset();
|
||||
}
|
||||
|
||||
public void Update(byte inByte)
|
||||
{
|
||||
engine.Update(inByte);
|
||||
}
|
||||
|
||||
public void BlockUpdate(byte[] input, int inOff, int len)
|
||||
{
|
||||
engine.Update(input, inOff, len);
|
||||
}
|
||||
|
||||
public int DoFinal(byte[] output, int outOff)
|
||||
{
|
||||
return engine.DoFinal(output, outOff);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,164 @@
|
||||
using System;
|
||||
using Org.BouncyCastle.Crypto.Parameters;
|
||||
|
||||
namespace Org.BouncyCastle.Crypto.Macs;
|
||||
|
||||
public class VmpcMac : IMac
|
||||
{
|
||||
private byte g;
|
||||
|
||||
private byte n = 0;
|
||||
|
||||
private byte[] P = null;
|
||||
|
||||
private byte s = 0;
|
||||
|
||||
private byte[] T;
|
||||
|
||||
private byte[] workingIV;
|
||||
|
||||
private byte[] workingKey;
|
||||
|
||||
private byte x1;
|
||||
|
||||
private byte x2;
|
||||
|
||||
private byte x3;
|
||||
|
||||
private byte x4;
|
||||
|
||||
public virtual string AlgorithmName => "VMPC-MAC";
|
||||
|
||||
public virtual int DoFinal(byte[] output, int outOff)
|
||||
{
|
||||
for (int i = 1; i < 25; i++)
|
||||
{
|
||||
s = P[(s + P[n & 0xFF]) & 0xFF];
|
||||
x4 = P[(x4 + x3 + i) & 0xFF];
|
||||
x3 = P[(x3 + x2 + i) & 0xFF];
|
||||
x2 = P[(x2 + x1 + i) & 0xFF];
|
||||
x1 = P[(x1 + s + i) & 0xFF];
|
||||
T[g & 0x1F] = (byte)(T[g & 0x1F] ^ x1);
|
||||
T[(g + 1) & 0x1F] = (byte)(T[(g + 1) & 0x1F] ^ x2);
|
||||
T[(g + 2) & 0x1F] = (byte)(T[(g + 2) & 0x1F] ^ x3);
|
||||
T[(g + 3) & 0x1F] = (byte)(T[(g + 3) & 0x1F] ^ x4);
|
||||
g = (byte)((g + 4) & 0x1F);
|
||||
byte b = P[n & 0xFF];
|
||||
P[n & 0xFF] = P[s & 0xFF];
|
||||
P[s & 0xFF] = b;
|
||||
n = (byte)((n + 1) & 0xFF);
|
||||
}
|
||||
for (int j = 0; j < 768; j++)
|
||||
{
|
||||
s = P[(s + P[j & 0xFF] + T[j & 0x1F]) & 0xFF];
|
||||
byte b2 = P[j & 0xFF];
|
||||
P[j & 0xFF] = P[s & 0xFF];
|
||||
P[s & 0xFF] = b2;
|
||||
}
|
||||
byte[] array = new byte[20];
|
||||
for (int k = 0; k < 20; k++)
|
||||
{
|
||||
s = P[(s + P[k & 0xFF]) & 0xFF];
|
||||
array[k] = P[(P[P[s & 0xFF] & 0xFF] + 1) & 0xFF];
|
||||
byte b3 = P[k & 0xFF];
|
||||
P[k & 0xFF] = P[s & 0xFF];
|
||||
P[s & 0xFF] = b3;
|
||||
}
|
||||
Array.Copy(array, 0, output, outOff, array.Length);
|
||||
Reset();
|
||||
return array.Length;
|
||||
}
|
||||
|
||||
public virtual int GetMacSize()
|
||||
{
|
||||
return 20;
|
||||
}
|
||||
|
||||
public virtual void Init(ICipherParameters parameters)
|
||||
{
|
||||
if (!(parameters is ParametersWithIV))
|
||||
{
|
||||
throw new ArgumentException("VMPC-MAC Init parameters must include an IV", "parameters");
|
||||
}
|
||||
ParametersWithIV parametersWithIV = (ParametersWithIV)parameters;
|
||||
KeyParameter keyParameter = (KeyParameter)parametersWithIV.Parameters;
|
||||
if (!(parametersWithIV.Parameters is KeyParameter))
|
||||
{
|
||||
throw new ArgumentException("VMPC-MAC Init parameters must include a key", "parameters");
|
||||
}
|
||||
workingIV = parametersWithIV.GetIV();
|
||||
if (workingIV == null || workingIV.Length < 1 || workingIV.Length > 768)
|
||||
{
|
||||
throw new ArgumentException("VMPC-MAC requires 1 to 768 bytes of IV", "parameters");
|
||||
}
|
||||
workingKey = keyParameter.GetKey();
|
||||
Reset();
|
||||
}
|
||||
|
||||
private void initKey(byte[] keyBytes, byte[] ivBytes)
|
||||
{
|
||||
s = 0;
|
||||
P = new byte[256];
|
||||
for (int i = 0; i < 256; i++)
|
||||
{
|
||||
P[i] = (byte)i;
|
||||
}
|
||||
for (int j = 0; j < 768; j++)
|
||||
{
|
||||
s = P[(s + P[j & 0xFF] + keyBytes[j % keyBytes.Length]) & 0xFF];
|
||||
byte b = P[j & 0xFF];
|
||||
P[j & 0xFF] = P[s & 0xFF];
|
||||
P[s & 0xFF] = b;
|
||||
}
|
||||
for (int k = 0; k < 768; k++)
|
||||
{
|
||||
s = P[(s + P[k & 0xFF] + ivBytes[k % ivBytes.Length]) & 0xFF];
|
||||
byte b2 = P[k & 0xFF];
|
||||
P[k & 0xFF] = P[s & 0xFF];
|
||||
P[s & 0xFF] = b2;
|
||||
}
|
||||
n = 0;
|
||||
}
|
||||
|
||||
public virtual void Reset()
|
||||
{
|
||||
initKey(workingKey, workingIV);
|
||||
g = (x1 = (x2 = (x3 = (x4 = (n = 0)))));
|
||||
T = new byte[32];
|
||||
for (int i = 0; i < 32; i++)
|
||||
{
|
||||
T[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void Update(byte input)
|
||||
{
|
||||
s = P[(s + P[n & 0xFF]) & 0xFF];
|
||||
byte b = (byte)(input ^ P[(P[P[s & 0xFF] & 0xFF] + 1) & 0xFF]);
|
||||
x4 = P[(x4 + x3) & 0xFF];
|
||||
x3 = P[(x3 + x2) & 0xFF];
|
||||
x2 = P[(x2 + x1) & 0xFF];
|
||||
x1 = P[(x1 + s + b) & 0xFF];
|
||||
T[g & 0x1F] = (byte)(T[g & 0x1F] ^ x1);
|
||||
T[(g + 1) & 0x1F] = (byte)(T[(g + 1) & 0x1F] ^ x2);
|
||||
T[(g + 2) & 0x1F] = (byte)(T[(g + 2) & 0x1F] ^ x3);
|
||||
T[(g + 3) & 0x1F] = (byte)(T[(g + 3) & 0x1F] ^ x4);
|
||||
g = (byte)((g + 4) & 0x1F);
|
||||
byte b2 = P[n & 0xFF];
|
||||
P[n & 0xFF] = P[s & 0xFF];
|
||||
P[s & 0xFF] = b2;
|
||||
n = (byte)((n + 1) & 0xFF);
|
||||
}
|
||||
|
||||
public virtual void BlockUpdate(byte[] input, int inOff, int len)
|
||||
{
|
||||
if (inOff + len > input.Length)
|
||||
{
|
||||
throw new DataLengthException("input buffer too short");
|
||||
}
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
Update(input[inOff + i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user