You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
183 lines
4.0 KiB
183 lines
4.0 KiB
1 year ago
|
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||
|
#pragma warning disable
|
||
|
using System;
|
||
|
|
||
|
using BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto.Parameters;
|
||
|
using BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities;
|
||
|
|
||
|
namespace BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto.Engines
|
||
|
{
|
||
|
/// <remarks>
|
||
|
/// An implementation of the AES Key Wrapper from the NIST Key Wrap
|
||
|
/// Specification as described in RFC 3394.
|
||
|
/// <p/>
|
||
|
/// For further details see: <a href="http://www.ietf.org/rfc/rfc3394.txt">http://www.ietf.org/rfc/rfc3394.txt</a>
|
||
|
/// and <a href="http://csrc.nist.gov/encryption/kms/key-wrap.pdf">http://csrc.nist.gov/encryption/kms/key-wrap.pdf</a>.
|
||
|
/// </remarks>
|
||
|
public class Rfc3394WrapEngine
|
||
|
: IWrapper
|
||
|
{
|
||
|
private readonly IBlockCipher engine;
|
||
|
|
||
|
private KeyParameter param;
|
||
|
private bool forWrapping;
|
||
|
|
||
|
private byte[] iv =
|
||
|
{
|
||
|
0xa6, 0xa6, 0xa6, 0xa6,
|
||
|
0xa6, 0xa6, 0xa6, 0xa6
|
||
|
};
|
||
|
|
||
|
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)
|
||
|
{
|
||
|
this.param = (KeyParameter) parameters;
|
||
|
}
|
||
|
else if (parameters is ParametersWithIV)
|
||
|
{
|
||
|
ParametersWithIV pIV = (ParametersWithIV) parameters;
|
||
|
byte[] iv = pIV.GetIV();
|
||
|
|
||
|
if (iv.Length != 8)
|
||
|
throw new ArgumentException("IV length not equal to 8", "parameters");
|
||
|
|
||
|
this.iv = iv;
|
||
|
this.param = (KeyParameter) pIV.Parameters;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// TODO Throw an exception for bad parameters?
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public virtual string AlgorithmName
|
||
|
{
|
||
|
get { return engine.AlgorithmName; }
|
||
|
}
|
||
|
|
||
|
public virtual byte[] Wrap(
|
||
|
byte[] input,
|
||
|
int inOff,
|
||
|
int inLen)
|
||
|
{
|
||
|
if (!forWrapping)
|
||
|
{
|
||
|
throw new InvalidOperationException("not set for wrapping");
|
||
|
}
|
||
|
|
||
|
int n = inLen / 8;
|
||
|
|
||
|
if ((n * 8) != inLen)
|
||
|
{
|
||
|
throw new DataLengthException("wrap data must be a multiple of 8 bytes");
|
||
|
}
|
||
|
|
||
|
byte[] block = new byte[inLen + iv.Length];
|
||
|
byte[] buf = new byte[8 + iv.Length];
|
||
|
|
||
|
Array.Copy(iv, 0, block, 0, iv.Length);
|
||
|
Array.Copy(input, inOff, block, iv.Length, inLen);
|
||
|
|
||
|
engine.Init(true, param);
|
||
|
|
||
|
for (int j = 0; j != 6; j++)
|
||
|
{
|
||
|
for (int i = 1; i <= n; i++)
|
||
|
{
|
||
|
Array.Copy(block, 0, buf, 0, iv.Length);
|
||
|
Array.Copy(block, 8 * i, buf, iv.Length, 8);
|
||
|
engine.ProcessBlock(buf, 0, buf, 0);
|
||
|
|
||
|
int t = n * j + i;
|
||
|
for (int k = 1; t != 0; k++)
|
||
|
{
|
||
|
byte v = (byte)t;
|
||
|
|
||
|
buf[iv.Length - k] ^= v;
|
||
|
t = (int) ((uint)t >> 8);
|
||
|
}
|
||
|
|
||
|
Array.Copy(buf, 0, block, 0, 8);
|
||
|
Array.Copy(buf, 8, block, 8 * i, 8);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return block;
|
||
|
}
|
||
|
|
||
|
public virtual byte[] Unwrap(
|
||
|
byte[] input,
|
||
|
int inOff,
|
||
|
int inLen)
|
||
|
{
|
||
|
if (forWrapping)
|
||
|
{
|
||
|
throw new InvalidOperationException("not set for unwrapping");
|
||
|
}
|
||
|
|
||
|
int n = inLen / 8;
|
||
|
|
||
|
if ((n * 8) != inLen)
|
||
|
{
|
||
|
throw new InvalidCipherTextException("unwrap data must be a multiple of 8 bytes");
|
||
|
}
|
||
|
|
||
|
byte[] block = new byte[inLen - iv.Length];
|
||
|
byte[] a = new byte[iv.Length];
|
||
|
byte[] buf = new byte[8 + iv.Length];
|
||
|
|
||
|
Array.Copy(input, inOff, a, 0, iv.Length);
|
||
|
Array.Copy(input, inOff + iv.Length, block, 0, inLen - iv.Length);
|
||
|
|
||
|
engine.Init(false, param);
|
||
|
|
||
|
n = n - 1;
|
||
|
|
||
|
for (int j = 5; j >= 0; j--)
|
||
|
{
|
||
|
for (int i = n; i >= 1; i--)
|
||
|
{
|
||
|
Array.Copy(a, 0, buf, 0, iv.Length);
|
||
|
Array.Copy(block, 8 * (i - 1), buf, iv.Length, 8);
|
||
|
|
||
|
int t = n * j + i;
|
||
|
for (int k = 1; t != 0; k++)
|
||
|
{
|
||
|
byte v = (byte)t;
|
||
|
|
||
|
buf[iv.Length - k] ^= v;
|
||
|
t = (int) ((uint)t >> 8);
|
||
|
}
|
||
|
|
||
|
engine.ProcessBlock(buf, 0, buf, 0);
|
||
|
Array.Copy(buf, 0, a, 0, 8);
|
||
|
Array.Copy(buf, 8, block, 8 * (i - 1), 8);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (!Arrays.ConstantTimeAreEqual(a, iv))
|
||
|
throw new InvalidCipherTextException("checksum failed");
|
||
|
|
||
|
return block;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
#pragma warning restore
|
||
|
#endif
|