init commit

This commit is contained in:
2025-10-09 09:57:24 +09:00
commit 4d551bd74f
6636 changed files with 1218703 additions and 0 deletions

View File

@@ -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();
}
}

View File

@@ -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();
}
}

View File

@@ -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();
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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();
}
}

View File

@@ -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;
}
}

View File

@@ -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);
}
}
}

View File

@@ -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();
}
}

View File

@@ -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);
}
}

View File

@@ -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;
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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]);
}
}
}