培训考核三期,新版培训,网页版培训登录器
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.4 KiB

#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
#pragma warning disable
using System;
using BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto.Modes;
using BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto.Parameters;
using BestHTTP.SecureProtocol.Org.BouncyCastle.Security;
namespace BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto.Engines
{
/**
* an implementation of the RFC 3211 Key Wrap
* Specification.
*/
public class Rfc3211WrapEngine
: IWrapper
{
private CbcBlockCipher engine;
private ParametersWithIV param;
private bool forWrapping;
private SecureRandom rand;
public Rfc3211WrapEngine(
IBlockCipher engine)
{
this.engine = new CbcBlockCipher(engine);
}
public virtual void Init(
bool forWrapping,
ICipherParameters param)
{
this.forWrapping = forWrapping;
if (param is ParametersWithRandom)
{
ParametersWithRandom p = (ParametersWithRandom)param;
this.rand = p.Random;
this.param = p.Parameters as ParametersWithIV;
}
else
{
if (forWrapping)
{
rand = new SecureRandom();
}
this.param = param as ParametersWithIV;
}
if (null == this.param)
throw new ArgumentException("RFC3211Wrap requires an IV", "param");
}
public virtual string AlgorithmName
{
get { return engine.GetUnderlyingCipher().AlgorithmName + "/RFC3211Wrap"; }
}
public virtual byte[] Wrap(
byte[] inBytes,
int inOff,
int inLen)
{
if (!forWrapping)
throw new InvalidOperationException("not set for wrapping");
if (inLen > 255 || inLen < 0)
throw new ArgumentException("input must be from 0 to 255 bytes", "inLen");
engine.Init(true, param);
int blockSize = engine.GetBlockSize();
byte[] cekBlock;
if (inLen + 4 < blockSize * 2)
{
cekBlock = new byte[blockSize * 2];
}
else
{
cekBlock = new byte[(inLen + 4) % blockSize == 0 ? inLen + 4 : ((inLen + 4) / blockSize + 1) * blockSize];
}
cekBlock[0] = (byte)inLen;
Array.Copy(inBytes, inOff, cekBlock, 4, inLen);
rand.NextBytes(cekBlock, inLen + 4, cekBlock.Length - inLen - 4);
cekBlock[1] = (byte)~cekBlock[4];
cekBlock[2] = (byte)~cekBlock[4 + 1];
cekBlock[3] = (byte)~cekBlock[4 + 2];
for (int i = 0; i < cekBlock.Length; i += blockSize)
{
engine.ProcessBlock(cekBlock, i, cekBlock, i);
}
for (int i = 0; i < cekBlock.Length; i += blockSize)
{
engine.ProcessBlock(cekBlock, i, cekBlock, i);
}
return cekBlock;
}
public virtual byte[] Unwrap(
byte[] inBytes,
int inOff,
int inLen)
{
if (forWrapping)
{
throw new InvalidOperationException("not set for unwrapping");
}
int blockSize = engine.GetBlockSize();
if (inLen < 2 * blockSize)
{
throw new InvalidCipherTextException("input too short");
}
byte[] cekBlock = new byte[inLen];
byte[] iv = new byte[blockSize];
Array.Copy(inBytes, inOff, cekBlock, 0, inLen);
Array.Copy(inBytes, inOff, iv, 0, iv.Length);
engine.Init(false, new ParametersWithIV(param.Parameters, iv));
for (int i = blockSize; i < cekBlock.Length; i += blockSize)
{
engine.ProcessBlock(cekBlock, i, cekBlock, i);
}
Array.Copy(cekBlock, cekBlock.Length - iv.Length, iv, 0, iv.Length);
engine.Init(false, new ParametersWithIV(param.Parameters, iv));
engine.ProcessBlock(cekBlock, 0, cekBlock, 0);
engine.Init(false, param);
for (int i = 0; i < cekBlock.Length; i += blockSize)
{
engine.ProcessBlock(cekBlock, i, cekBlock, i);
}
bool invalidLength = (int)cekBlock[0] > (cekBlock.Length - 4);
byte[] key;
if (invalidLength)
{
key = new byte[cekBlock.Length - 4];
}
else
{
key = new byte[cekBlock[0]];
}
Array.Copy(cekBlock, 4, key, 0, key.Length);
// Note: Using constant time comparison
int nonEqual = 0;
for (int i = 0; i != 3; i++)
{
byte check = (byte)~cekBlock[1 + i];
nonEqual |= (check ^ cekBlock[4 + i]);
}
Array.Clear(cekBlock, 0, cekBlock.Length);
if (nonEqual != 0 | invalidLength)
throw new InvalidCipherTextException("wrapped key corrupted");
return key;
}
}
}
#pragma warning restore
#endif