|
|
|
|
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
|
|
|
|
#pragma warning disable
|
|
|
|
|
using System;
|
|
|
|
|
using System.Collections;
|
|
|
|
|
|
|
|
|
|
using BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto.Parameters;
|
|
|
|
|
using BestHTTP.SecureProtocol.Org.BouncyCastle.Math;
|
|
|
|
|
using BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities;
|
|
|
|
|
|
|
|
|
|
namespace BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto.Signers
|
|
|
|
|
{
|
|
|
|
|
/**
|
|
|
|
|
* X9.31-1998 - signing using a hash.
|
|
|
|
|
* <p>
|
|
|
|
|
* The message digest hash, H, is encapsulated to form a byte string as follows
|
|
|
|
|
* </p>
|
|
|
|
|
* <pre>
|
|
|
|
|
* EB = 06 || PS || 0xBA || H || TRAILER
|
|
|
|
|
* </pre>
|
|
|
|
|
* where PS is a string of bytes all of value 0xBB of length such that |EB|=|n|, and TRAILER is the ISO/IEC 10118 part number†for the digest. The byte string, EB, is converted to an integer value, the message representative, f.
|
|
|
|
|
*/
|
|
|
|
|
public class X931Signer
|
|
|
|
|
: ISigner
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
public const int TRAILER_IMPLICIT = 0xBC;
|
|
|
|
|
|
|
|
|
|
public const int TRAILER_RIPEMD160 = 0x31CC;
|
|
|
|
|
|
|
|
|
|
public const int TRAILER_RIPEMD128 = 0x32CC;
|
|
|
|
|
|
|
|
|
|
public const int TRAILER_SHA1 = 0x33CC;
|
|
|
|
|
|
|
|
|
|
public const int TRAILER_SHA256 = 0x34CC;
|
|
|
|
|
|
|
|
|
|
public const int TRAILER_SHA512 = 0x35CC;
|
|
|
|
|
|
|
|
|
|
public const int TRAILER_SHA384 = 0x36CC;
|
|
|
|
|
|
|
|
|
|
public const int TRAILER_WHIRLPOOL = 0x37CC;
|
|
|
|
|
|
|
|
|
|
public const int TRAILER_SHA224 = 0x38CC;
|
|
|
|
|
|
|
|
|
|
private IDigest digest;
|
|
|
|
|
private IAsymmetricBlockCipher cipher;
|
|
|
|
|
private RsaKeyParameters kParam;
|
|
|
|
|
|
|
|
|
|
private int trailer;
|
|
|
|
|
private int keyBits;
|
|
|
|
|
private byte[] block;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Generate a signer with either implicit or explicit trailers for X9.31.
|
|
|
|
|
*
|
|
|
|
|
* @param cipher base cipher to use for signature creation/verification
|
|
|
|
|
* @param digest digest to use.
|
|
|
|
|
* @param implicit whether or not the trailer is implicit or gives the hash.
|
|
|
|
|
*/
|
|
|
|
|
public X931Signer(IAsymmetricBlockCipher cipher, IDigest digest, bool isImplicit)
|
|
|
|
|
{
|
|
|
|
|
this.cipher = cipher;
|
|
|
|
|
this.digest = digest;
|
|
|
|
|
|
|
|
|
|
if (isImplicit)
|
|
|
|
|
{
|
|
|
|
|
trailer = IsoTrailers.TRAILER_IMPLICIT;
|
|
|
|
|
}
|
|
|
|
|
else if (IsoTrailers.NoTrailerAvailable(digest))
|
|
|
|
|
{
|
|
|
|
|
throw new ArgumentException("no valid trailer", "digest");
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
trailer = IsoTrailers.GetTrailer(digest);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public virtual string AlgorithmName
|
|
|
|
|
{
|
|
|
|
|
get { return digest.AlgorithmName + "with" + cipher.AlgorithmName + "/X9.31"; }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Constructor for a signer with an explicit digest trailer.
|
|
|
|
|
*
|
|
|
|
|
* @param cipher cipher to use.
|
|
|
|
|
* @param digest digest to sign with.
|
|
|
|
|
*/
|
|
|
|
|
public X931Signer(IAsymmetricBlockCipher cipher, IDigest digest)
|
|
|
|
|
: this(cipher, digest, false)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public virtual void Init(bool forSigning, ICipherParameters parameters)
|
|
|
|
|
{
|
|
|
|
|
kParam = (RsaKeyParameters)parameters;
|
|
|
|
|
|
|
|
|
|
cipher.Init(forSigning, kParam);
|
|
|
|
|
|
|
|
|
|
keyBits = kParam.Modulus.BitLength;
|
|
|
|
|
|
|
|
|
|
block = new byte[(keyBits + 7) / 8];
|
|
|
|
|
|
|
|
|
|
Reset();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary> clear possible sensitive data</summary>
|
|
|
|
|
private void ClearBlock(byte[] block)
|
|
|
|
|
{
|
|
|
|
|
Array.Clear(block, 0, block.Length);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* update the internal digest with the byte b
|
|
|
|
|
*/
|
|
|
|
|
public virtual void Update(byte b)
|
|
|
|
|
{
|
|
|
|
|
digest.Update(b);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* update the internal digest with the byte array in
|
|
|
|
|
*/
|
|
|
|
|
public virtual void BlockUpdate(byte[] input, int off, int len)
|
|
|
|
|
{
|
|
|
|
|
digest.BlockUpdate(input, off, len);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* reset the internal state
|
|
|
|
|
*/
|
|
|
|
|
public virtual void Reset()
|
|
|
|
|
{
|
|
|
|
|
digest.Reset();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* generate a signature for the loaded message using the key we were
|
|
|
|
|
* initialised with.
|
|
|
|
|
*/
|
|
|
|
|
public virtual byte[] GenerateSignature()
|
|
|
|
|
{
|
|
|
|
|
CreateSignatureBlock();
|
|
|
|
|
|
|
|
|
|
BigInteger t = new BigInteger(1, cipher.ProcessBlock(block, 0, block.Length));
|
|
|
|
|
ClearBlock(block);
|
|
|
|
|
|
|
|
|
|
t = t.Min(kParam.Modulus.Subtract(t));
|
|
|
|
|
|
|
|
|
|
int size = BigIntegers.GetUnsignedByteLength(kParam.Modulus);
|
|
|
|
|
return BigIntegers.AsUnsignedByteArray(size, t);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void CreateSignatureBlock()
|
|
|
|
|
{
|
|
|
|
|
int digSize = digest.GetDigestSize();
|
|
|
|
|
|
|
|
|
|
int delta;
|
|
|
|
|
if (trailer == IsoTrailers.TRAILER_IMPLICIT)
|
|
|
|
|
{
|
|
|
|
|
delta = block.Length - digSize - 1;
|
|
|
|
|
digest.DoFinal(block, delta);
|
|
|
|
|
block[block.Length - 1] = (byte)IsoTrailers.TRAILER_IMPLICIT;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
delta = block.Length - digSize - 2;
|
|
|
|
|
digest.DoFinal(block, delta);
|
|
|
|
|
block[block.Length - 2] = (byte)(trailer >> 8);
|
|
|
|
|
block[block.Length - 1] = (byte)trailer;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
block[0] = 0x6b;
|
|
|
|
|
for (int i = delta - 2; i != 0; i--)
|
|
|
|
|
{
|
|
|
|
|
block[i] = (byte)0xbb;
|
|
|
|
|
}
|
|
|
|
|
block[delta - 1] = (byte)0xba;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* return true if the signature represents a ISO9796-2 signature
|
|
|
|
|
* for the passed in message.
|
|
|
|
|
*/
|
|
|
|
|
public virtual bool VerifySignature(byte[] signature)
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
block = cipher.ProcessBlock(signature, 0, signature.Length);
|
|
|
|
|
}
|
|
|
|
|
catch (Exception)
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BigInteger t = new BigInteger(1, block);
|
|
|
|
|
BigInteger f;
|
|
|
|
|
|
|
|
|
|
if ((t.IntValue & 15) == 12)
|
|
|
|
|
{
|
|
|
|
|
f = t;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
t = kParam.Modulus.Subtract(t);
|
|
|
|
|
if ((t.IntValue & 15) == 12)
|
|
|
|
|
{
|
|
|
|
|
f = t;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CreateSignatureBlock();
|
|
|
|
|
|
|
|
|
|
byte[] fBlock = BigIntegers.AsUnsignedByteArray(block.Length, f);
|
|
|
|
|
|
|
|
|
|
bool rv = Arrays.ConstantTimeAreEqual(block, fBlock);
|
|
|
|
|
|
|
|
|
|
ClearBlock(block);
|
|
|
|
|
ClearBlock(fBlock);
|
|
|
|
|
|
|
|
|
|
return rv;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#pragma warning restore
|
|
|
|
|
#endif
|