169 lines
3.8 KiB
C#
169 lines
3.8 KiB
C#
using System;
|
|
using Org.BouncyCastle.Crypto.Parameters;
|
|
using Org.BouncyCastle.Math;
|
|
using Org.BouncyCastle.Utilities;
|
|
|
|
namespace Org.BouncyCastle.Crypto.Signers;
|
|
|
|
public class X931Signer : ISigner
|
|
{
|
|
[Obsolete("Use 'IsoTrailers' instead")]
|
|
public const int TRAILER_IMPLICIT = 188;
|
|
|
|
[Obsolete("Use 'IsoTrailers' instead")]
|
|
public const int TRAILER_RIPEMD160 = 12748;
|
|
|
|
[Obsolete("Use 'IsoTrailers' instead")]
|
|
public const int TRAILER_RIPEMD128 = 13004;
|
|
|
|
[Obsolete("Use 'IsoTrailers' instead")]
|
|
public const int TRAILER_SHA1 = 13260;
|
|
|
|
[Obsolete("Use 'IsoTrailers' instead")]
|
|
public const int TRAILER_SHA256 = 13516;
|
|
|
|
[Obsolete("Use 'IsoTrailers' instead")]
|
|
public const int TRAILER_SHA512 = 13772;
|
|
|
|
[Obsolete("Use 'IsoTrailers' instead")]
|
|
public const int TRAILER_SHA384 = 14028;
|
|
|
|
[Obsolete("Use 'IsoTrailers' instead")]
|
|
public const int TRAILER_WHIRLPOOL = 14284;
|
|
|
|
[Obsolete("Use 'IsoTrailers' instead")]
|
|
public const int TRAILER_SHA224 = 14540;
|
|
|
|
private IDigest digest;
|
|
|
|
private IAsymmetricBlockCipher cipher;
|
|
|
|
private RsaKeyParameters kParam;
|
|
|
|
private int trailer;
|
|
|
|
private int keyBits;
|
|
|
|
private byte[] block;
|
|
|
|
public virtual string AlgorithmName => digest.AlgorithmName + "with" + cipher.AlgorithmName + "/X9.31";
|
|
|
|
public X931Signer(IAsymmetricBlockCipher cipher, IDigest digest, bool isImplicit)
|
|
{
|
|
this.cipher = cipher;
|
|
this.digest = digest;
|
|
if (isImplicit)
|
|
{
|
|
trailer = 188;
|
|
return;
|
|
}
|
|
if (IsoTrailers.NoTrailerAvailable(digest))
|
|
{
|
|
throw new ArgumentException("no valid trailer", "digest");
|
|
}
|
|
trailer = IsoTrailers.GetTrailer(digest);
|
|
}
|
|
|
|
public X931Signer(IAsymmetricBlockCipher cipher, IDigest digest)
|
|
: this(cipher, digest, isImplicit: 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();
|
|
}
|
|
|
|
private void ClearBlock(byte[] block)
|
|
{
|
|
Array.Clear(block, 0, block.Length);
|
|
}
|
|
|
|
public virtual void Update(byte b)
|
|
{
|
|
digest.Update(b);
|
|
}
|
|
|
|
public virtual void BlockUpdate(byte[] input, int off, int len)
|
|
{
|
|
digest.BlockUpdate(input, off, len);
|
|
}
|
|
|
|
public virtual void Reset()
|
|
{
|
|
digest.Reset();
|
|
}
|
|
|
|
public virtual byte[] GenerateSignature()
|
|
{
|
|
CreateSignatureBlock();
|
|
BigInteger bigInteger = new BigInteger(1, cipher.ProcessBlock(block, 0, block.Length));
|
|
ClearBlock(block);
|
|
bigInteger = bigInteger.Min(kParam.Modulus.Subtract(bigInteger));
|
|
int unsignedByteLength = BigIntegers.GetUnsignedByteLength(kParam.Modulus);
|
|
return BigIntegers.AsUnsignedByteArray(unsignedByteLength, bigInteger);
|
|
}
|
|
|
|
private void CreateSignatureBlock()
|
|
{
|
|
int digestSize = digest.GetDigestSize();
|
|
int num;
|
|
if (trailer == 188)
|
|
{
|
|
num = block.Length - digestSize - 1;
|
|
digest.DoFinal(block, num);
|
|
block[block.Length - 1] = 188;
|
|
}
|
|
else
|
|
{
|
|
num = block.Length - digestSize - 2;
|
|
digest.DoFinal(block, num);
|
|
block[block.Length - 2] = (byte)(trailer >> 8);
|
|
block[block.Length - 1] = (byte)trailer;
|
|
}
|
|
block[0] = 107;
|
|
for (int num2 = num - 2; num2 != 0; num2--)
|
|
{
|
|
block[num2] = 187;
|
|
}
|
|
block[num - 1] = 186;
|
|
}
|
|
|
|
public virtual bool VerifySignature(byte[] signature)
|
|
{
|
|
try
|
|
{
|
|
block = cipher.ProcessBlock(signature, 0, signature.Length);
|
|
}
|
|
catch (Exception)
|
|
{
|
|
return false;
|
|
}
|
|
BigInteger bigInteger = new BigInteger(1, block);
|
|
BigInteger n;
|
|
if ((bigInteger.IntValue & 0xF) == 12)
|
|
{
|
|
n = bigInteger;
|
|
}
|
|
else
|
|
{
|
|
bigInteger = kParam.Modulus.Subtract(bigInteger);
|
|
if ((bigInteger.IntValue & 0xF) != 12)
|
|
{
|
|
return false;
|
|
}
|
|
n = bigInteger;
|
|
}
|
|
CreateSignatureBlock();
|
|
byte[] b = BigIntegers.AsUnsignedByteArray(block.Length, n);
|
|
bool result = Arrays.ConstantTimeAreEqual(block, b);
|
|
ClearBlock(block);
|
|
ClearBlock(b);
|
|
return result;
|
|
}
|
|
}
|