Files
SuperVPN/output/Libraries/BouncyCastle.Crypto/Org/BouncyCastle/Crypto/Engines/Rfc3394WrapEngine.cs
2025-10-09 09:57:24 +09:00

140 lines
3.6 KiB
C#

using System;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Utilities;
namespace Org.BouncyCastle.Crypto.Engines;
public class Rfc3394WrapEngine : IWrapper
{
private readonly IBlockCipher engine;
private KeyParameter param;
private bool forWrapping;
private byte[] iv = new byte[8] { 166, 166, 166, 166, 166, 166, 166, 166 };
public virtual string AlgorithmName => engine.AlgorithmName;
public Rfc3394WrapEngine(IBlockCipher engine)
{
this.engine = engine;
}
public virtual void Init(bool forWrapping, ICipherParameters parameters)
{
this.forWrapping = forWrapping;
if (parameters is ParametersWithRandom)
{
parameters = ((ParametersWithRandom)parameters).Parameters;
}
if (parameters is KeyParameter)
{
param = (KeyParameter)parameters;
}
else if (parameters is ParametersWithIV)
{
ParametersWithIV parametersWithIV = (ParametersWithIV)parameters;
byte[] iV = parametersWithIV.GetIV();
if (iV.Length != 8)
{
throw new ArgumentException("IV length not equal to 8", "parameters");
}
iv = iV;
param = (KeyParameter)parametersWithIV.Parameters;
}
}
public virtual byte[] Wrap(byte[] input, int inOff, int inLen)
{
if (!forWrapping)
{
throw new InvalidOperationException("not set for wrapping");
}
int num = inLen / 8;
if (num * 8 != inLen)
{
throw new DataLengthException("wrap data must be a multiple of 8 bytes");
}
byte[] array = new byte[inLen + iv.Length];
byte[] array2 = new byte[8 + iv.Length];
Array.Copy(iv, 0, array, 0, iv.Length);
Array.Copy(input, inOff, array, iv.Length, inLen);
engine.Init(forEncryption: true, param);
for (int i = 0; i != 6; i++)
{
for (int j = 1; j <= num; j++)
{
Array.Copy(array, 0, array2, 0, iv.Length);
Array.Copy(array, 8 * j, array2, iv.Length, 8);
engine.ProcessBlock(array2, 0, array2, 0);
int num2 = num * i + j;
int num3 = 1;
while (num2 != 0)
{
byte b = (byte)num2;
byte[] array4;
byte[] array3 = (array4 = array2);
int num4 = iv.Length - num3;
nint num5 = num4;
array3[num4] = (byte)(array4[num5] ^ b);
num2 >>>= 8;
num3++;
}
Array.Copy(array2, 0, array, 0, 8);
Array.Copy(array2, 8, array, 8 * j, 8);
}
}
return array;
}
public virtual byte[] Unwrap(byte[] input, int inOff, int inLen)
{
if (forWrapping)
{
throw new InvalidOperationException("not set for unwrapping");
}
int num = inLen / 8;
if (num * 8 != inLen)
{
throw new InvalidCipherTextException("unwrap data must be a multiple of 8 bytes");
}
byte[] array = new byte[inLen - iv.Length];
byte[] array2 = new byte[iv.Length];
byte[] array3 = new byte[8 + iv.Length];
Array.Copy(input, inOff, array2, 0, iv.Length);
Array.Copy(input, inOff + iv.Length, array, 0, inLen - iv.Length);
engine.Init(forEncryption: false, param);
num--;
for (int num2 = 5; num2 >= 0; num2--)
{
for (int num3 = num; num3 >= 1; num3--)
{
Array.Copy(array2, 0, array3, 0, iv.Length);
Array.Copy(array, 8 * (num3 - 1), array3, iv.Length, 8);
int num4 = num * num2 + num3;
int num5 = 1;
while (num4 != 0)
{
byte b = (byte)num4;
byte[] array5;
byte[] array4 = (array5 = array3);
int num6 = iv.Length - num5;
nint num7 = num6;
array4[num6] = (byte)(array5[num7] ^ b);
num4 >>>= 8;
num5++;
}
engine.ProcessBlock(array3, 0, array3, 0);
Array.Copy(array3, 0, array2, 0, 8);
Array.Copy(array3, 8, array, 8 * (num3 - 1), 8);
}
}
if (!Arrays.ConstantTimeAreEqual(array2, iv))
{
throw new InvalidCipherTextException("checksum failed");
}
return array;
}
}