diff --git a/crypto/crypto.csproj b/crypto/crypto.csproj
index 26af5666f..ded3d6025 100644
--- a/crypto/crypto.csproj
+++ b/crypto/crypto.csproj
@@ -4294,6 +4294,11 @@
BuildAction = "Compile"
/>
<File
+ RelPath = "src\crypto\signers\X931Signer.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
RelPath = "src\crypto\tls\AbstractTlsAgreementCredentials.cs"
SubType = "Code"
BuildAction = "Compile"
@@ -11068,6 +11073,11 @@
BuildAction = "Compile"
/>
<File
+ RelPath = "test\src\crypto\test\X931SignerTest.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
RelPath = "test\src\crypto\test\XSalsa20Test.cs"
SubType = "Code"
BuildAction = "Compile"
diff --git a/crypto/src/crypto/signers/DsaDigestSigner.cs b/crypto/src/crypto/signers/DsaDigestSigner.cs
index aee713450..086601481 100644
--- a/crypto/src/crypto/signers/DsaDigestSigner.cs
+++ b/crypto/src/crypto/signers/DsaDigestSigner.cs
@@ -26,12 +26,12 @@ namespace Org.BouncyCastle.Crypto.Signers
this.dsaSigner = signer;
}
- public string AlgorithmName
+ public virtual string AlgorithmName
{
get { return digest.AlgorithmName + "with" + dsaSigner.AlgorithmName; }
}
- public void Init(
+ public virtual void Init(
bool forSigning,
ICipherParameters parameters)
{
@@ -62,7 +62,7 @@ namespace Org.BouncyCastle.Crypto.Signers
/**
* update the internal digest with the byte b
*/
- public void Update(
+ public virtual void Update(
byte input)
{
digest.Update(input);
@@ -71,7 +71,7 @@ namespace Org.BouncyCastle.Crypto.Signers
/**
* update the internal digest with the byte array in
*/
- public void BlockUpdate(
+ public virtual void BlockUpdate(
byte[] input,
int inOff,
int length)
@@ -83,7 +83,7 @@ namespace Org.BouncyCastle.Crypto.Signers
* Generate a signature for the message we've been loaded with using
* the key we were initialised with.
*/
- public byte[] GenerateSignature()
+ public virtual byte[] GenerateSignature()
{
if (!forSigning)
throw new InvalidOperationException("DSADigestSigner not initialised for signature generation.");
@@ -97,7 +97,7 @@ namespace Org.BouncyCastle.Crypto.Signers
}
/// <returns>true if the internal state represents the signature described in the passed in array.</returns>
- public bool VerifySignature(
+ public virtual bool VerifySignature(
byte[] signature)
{
if (forSigning)
@@ -118,7 +118,7 @@ namespace Org.BouncyCastle.Crypto.Signers
}
/// <summary>Reset the internal state</summary>
- public void Reset()
+ public virtual void Reset()
{
digest.Reset();
}
diff --git a/crypto/src/crypto/signers/ECGOST3410Signer.cs b/crypto/src/crypto/signers/ECGOST3410Signer.cs
index 6027aa9b9..28ab79c1c 100644
--- a/crypto/src/crypto/signers/ECGOST3410Signer.cs
+++ b/crypto/src/crypto/signers/ECGOST3410Signer.cs
@@ -18,12 +18,12 @@ namespace Org.BouncyCastle.Crypto.Signers
private ECKeyParameters key;
private SecureRandom random;
- public string AlgorithmName
+ public virtual string AlgorithmName
{
get { return "ECGOST3410"; }
}
- public void Init(
+ public virtual void Init(
bool forSigning,
ICipherParameters parameters)
{
@@ -62,7 +62,7 @@ namespace Org.BouncyCastle.Crypto.Signers
*
* @param message the message that will be verified later.
*/
- public BigInteger[] GenerateSignature(
+ public virtual BigInteger[] GenerateSignature(
byte[] message)
{
byte[] mRev = new byte[message.Length]; // conversion is little-endian
@@ -110,7 +110,7 @@ namespace Org.BouncyCastle.Crypto.Signers
* the passed in message (for standard GOST3410 the message should be
* a GOST3411 hash of the real message to be verified).
*/
- public bool VerifySignature(
+ public virtual bool VerifySignature(
byte[] message,
BigInteger r,
BigInteger s)
diff --git a/crypto/src/crypto/signers/ECNRSigner.cs b/crypto/src/crypto/signers/ECNRSigner.cs
index cae15bdbf..bb21a4994 100644
--- a/crypto/src/crypto/signers/ECNRSigner.cs
+++ b/crypto/src/crypto/signers/ECNRSigner.cs
@@ -19,12 +19,12 @@ namespace Org.BouncyCastle.Crypto.Signers
private ECKeyParameters key;
private SecureRandom random;
- public string AlgorithmName
+ public virtual string AlgorithmName
{
get { return "ECNR"; }
}
- public void Init(
+ public virtual void Init(
bool forSigning,
ICipherParameters parameters)
{
@@ -68,7 +68,7 @@ namespace Org.BouncyCastle.Crypto.Signers
* @param digest the digest to be signed.
* @exception DataLengthException if the digest is longer than the key allows
*/
- public BigInteger[] GenerateSignature(
+ public virtual BigInteger[] GenerateSignature(
byte[] message)
{
if (!this.forSigning)
@@ -134,7 +134,7 @@ namespace Org.BouncyCastle.Crypto.Signers
* @param s the s value of the signature.
* @exception DataLengthException if the digest is longer than the key allows
*/
- public bool VerifySignature(
+ public virtual bool VerifySignature(
byte[] message,
BigInteger r,
BigInteger s)
diff --git a/crypto/src/crypto/signers/GOST3410DigestSigner.cs b/crypto/src/crypto/signers/GOST3410DigestSigner.cs
index 58aefa368..bc32808df 100644
--- a/crypto/src/crypto/signers/GOST3410DigestSigner.cs
+++ b/crypto/src/crypto/signers/GOST3410DigestSigner.cs
@@ -26,12 +26,12 @@ namespace Org.BouncyCastle.Crypto.Signers
this.digest = digest;
}
- public string AlgorithmName
+ public virtual string AlgorithmName
{
get { return digest.AlgorithmName + "with" + dsaSigner.AlgorithmName; }
}
- public void Init(
+ public virtual void Init(
bool forSigning,
ICipherParameters parameters)
{
@@ -65,7 +65,7 @@ namespace Org.BouncyCastle.Crypto.Signers
/**
* update the internal digest with the byte b
*/
- public void Update(
+ public virtual void Update(
byte input)
{
digest.Update(input);
@@ -74,7 +74,7 @@ namespace Org.BouncyCastle.Crypto.Signers
/**
* update the internal digest with the byte array in
*/
- public void BlockUpdate(
+ public virtual void BlockUpdate(
byte[] input,
int inOff,
int length)
@@ -86,7 +86,7 @@ namespace Org.BouncyCastle.Crypto.Signers
* Generate a signature for the message we've been loaded with using
* the key we were initialised with.
*/
- public byte[] GenerateSignature()
+ public virtual byte[] GenerateSignature()
{
if (!forSigning)
throw new InvalidOperationException("GOST3410DigestSigner not initialised for signature generation.");
@@ -113,7 +113,7 @@ namespace Org.BouncyCastle.Crypto.Signers
}
/// <returns>true if the internal state represents the signature described in the passed in array.</returns>
- public bool VerifySignature(
+ public virtual bool VerifySignature(
byte[] signature)
{
if (forSigning)
@@ -137,7 +137,7 @@ namespace Org.BouncyCastle.Crypto.Signers
}
/// <summary>Reset the internal state</summary>
- public void Reset()
+ public virtual void Reset()
{
digest.Reset();
}
diff --git a/crypto/src/crypto/signers/GOST3410Signer.cs b/crypto/src/crypto/signers/GOST3410Signer.cs
index 375eeb5cc..f1832ae37 100644
--- a/crypto/src/crypto/signers/GOST3410Signer.cs
+++ b/crypto/src/crypto/signers/GOST3410Signer.cs
@@ -15,12 +15,12 @@ namespace Org.BouncyCastle.Crypto.Signers
private Gost3410KeyParameters key;
private SecureRandom random;
- public string AlgorithmName
+ public virtual string AlgorithmName
{
get { return "GOST3410"; }
}
- public void Init(
+ public virtual void Init(
bool forSigning,
ICipherParameters parameters)
{
@@ -59,7 +59,7 @@ namespace Org.BouncyCastle.Crypto.Signers
*
* @param message the message that will be verified later.
*/
- public BigInteger[] GenerateSignature(
+ public virtual BigInteger[] GenerateSignature(
byte[] message)
{
byte[] mRev = new byte[message.Length]; // conversion is little-endian
@@ -92,7 +92,7 @@ namespace Org.BouncyCastle.Crypto.Signers
* the passed in message for standard Gost3410 the message should be a
* Gost3411 hash of the real message to be verified.
*/
- public bool VerifySignature(
+ public virtual bool VerifySignature(
byte[] message,
BigInteger r,
BigInteger s)
diff --git a/crypto/src/crypto/signers/GenericSigner.cs b/crypto/src/crypto/signers/GenericSigner.cs
index 5035b454d..a5512176f 100644
--- a/crypto/src/crypto/signers/GenericSigner.cs
+++ b/crypto/src/crypto/signers/GenericSigner.cs
@@ -21,7 +21,7 @@ namespace Org.BouncyCastle.Crypto.Signers
this.digest = digest;
}
- public string AlgorithmName
+ public virtual string AlgorithmName
{
get { return "Generic(" + engine.AlgorithmName + "/" + digest.AlgorithmName + ")"; }
}
@@ -34,7 +34,7 @@ namespace Org.BouncyCastle.Crypto.Signers
* @param parameters
* necessary parameters.
*/
- public void Init(bool forSigning, ICipherParameters parameters)
+ public virtual void Init(bool forSigning, ICipherParameters parameters)
{
this.forSigning = forSigning;
@@ -62,7 +62,7 @@ namespace Org.BouncyCastle.Crypto.Signers
/**
* update the internal digest with the byte b
*/
- public void Update(byte input)
+ public virtual void Update(byte input)
{
digest.Update(input);
}
@@ -70,7 +70,7 @@ namespace Org.BouncyCastle.Crypto.Signers
/**
* update the internal digest with the byte array in
*/
- public void BlockUpdate(byte[] input, int inOff, int length)
+ public virtual void BlockUpdate(byte[] input, int inOff, int length)
{
digest.BlockUpdate(input, inOff, length);
}
@@ -79,7 +79,7 @@ namespace Org.BouncyCastle.Crypto.Signers
* Generate a signature for the message we've been loaded with using the key
* we were initialised with.
*/
- public byte[] GenerateSignature()
+ public virtual byte[] GenerateSignature()
{
if (!forSigning)
throw new InvalidOperationException("GenericSigner not initialised for signature generation.");
@@ -94,7 +94,7 @@ namespace Org.BouncyCastle.Crypto.Signers
* return true if the internal state represents the signature described in
* the passed in array.
*/
- public bool VerifySignature(byte[] signature)
+ public virtual bool VerifySignature(byte[] signature)
{
if (forSigning)
throw new InvalidOperationException("GenericSigner not initialised for verification");
@@ -122,7 +122,7 @@ namespace Org.BouncyCastle.Crypto.Signers
}
}
- public void Reset()
+ public virtual void Reset()
{
digest.Reset();
}
diff --git a/crypto/src/crypto/signers/Iso9796d2PssSigner.cs b/crypto/src/crypto/signers/Iso9796d2PssSigner.cs
index d4f6c5522..1486656bd 100644
--- a/crypto/src/crypto/signers/Iso9796d2PssSigner.cs
+++ b/crypto/src/crypto/signers/Iso9796d2PssSigner.cs
@@ -120,7 +120,7 @@ namespace Org.BouncyCastle.Crypto.Signers
{
}
- public string AlgorithmName
+ public virtual string AlgorithmName
{
get { return digest.AlgorithmName + "with" + "ISO9796-2S2"; }
}
@@ -365,7 +365,7 @@ namespace Org.BouncyCastle.Crypto.Signers
/// <summary> Generate a signature for the loaded message using the key we were
/// initialised with.
/// </summary>
- public byte[] GenerateSignature()
+ public virtual byte[] GenerateSignature()
{
int digSize = digest.GetDigestSize();
byte[] m2Hash = new byte[digSize];
diff --git a/crypto/src/crypto/signers/Iso9796d2Signer.cs b/crypto/src/crypto/signers/Iso9796d2Signer.cs
index cfb8942e6..4bb4d17a6 100644
--- a/crypto/src/crypto/signers/Iso9796d2Signer.cs
+++ b/crypto/src/crypto/signers/Iso9796d2Signer.cs
@@ -105,7 +105,7 @@ namespace Org.BouncyCastle.Crypto.Signers
{
}
- public string AlgorithmName
+ public virtual string AlgorithmName
{
get { return digest.AlgorithmName + "with" + "ISO9796-2S1"; }
}
@@ -252,7 +252,7 @@ namespace Org.BouncyCastle.Crypto.Signers
}
/// <summary> update the internal digest with the byte b</summary>
- public void Update(
+ public virtual void Update(
byte input)
{
digest.Update(input);
@@ -266,7 +266,7 @@ namespace Org.BouncyCastle.Crypto.Signers
}
/// <summary> update the internal digest with the byte array in</summary>
- public void BlockUpdate(
+ public virtual void BlockUpdate(
byte[] input,
int inOff,
int length)
diff --git a/crypto/src/crypto/signers/PssSigner.cs b/crypto/src/crypto/signers/PssSigner.cs
index 6900224f3..03890902b 100644
--- a/crypto/src/crypto/signers/PssSigner.cs
+++ b/crypto/src/crypto/signers/PssSigner.cs
@@ -115,7 +115,7 @@ namespace Org.BouncyCastle.Crypto.Signers
this.trailer = trailer;
}
- public string AlgorithmName
+ public virtual string AlgorithmName
{
get { return mgfDigest.AlgorithmName + "withRSAandMGF1"; }
}
diff --git a/crypto/src/crypto/signers/RsaDigestSigner.cs b/crypto/src/crypto/signers/RsaDigestSigner.cs
index 9af4e7145..d9b19cf6b 100644
--- a/crypto/src/crypto/signers/RsaDigestSigner.cs
+++ b/crypto/src/crypto/signers/RsaDigestSigner.cs
@@ -64,8 +64,7 @@ namespace Org.BouncyCastle.Crypto.Signers
this.algId = algId;
}
- [Obsolete]
- public string AlgorithmName
+ public virtual string AlgorithmName
{
get { return digest.AlgorithmName + "withRSA"; }
}
@@ -76,7 +75,7 @@ namespace Org.BouncyCastle.Crypto.Signers
* @param forSigning true if for signing, false otherwise
* @param param necessary parameters.
*/
- public void Init(
+ public virtual void Init(
bool forSigning,
ICipherParameters parameters)
{
@@ -106,7 +105,7 @@ namespace Org.BouncyCastle.Crypto.Signers
/**
* update the internal digest with the byte b
*/
- public void Update(
+ public virtual void Update(
byte input)
{
digest.Update(input);
@@ -115,7 +114,7 @@ namespace Org.BouncyCastle.Crypto.Signers
/**
* update the internal digest with the byte array in
*/
- public void BlockUpdate(
+ public virtual void BlockUpdate(
byte[] input,
int inOff,
int length)
@@ -127,7 +126,7 @@ namespace Org.BouncyCastle.Crypto.Signers
* Generate a signature for the message we've been loaded with using
* the key we were initialised with.
*/
- public byte[] GenerateSignature()
+ public virtual byte[] GenerateSignature()
{
if (!forSigning)
throw new InvalidOperationException("RsaDigestSigner not initialised for signature generation.");
@@ -143,7 +142,7 @@ namespace Org.BouncyCastle.Crypto.Signers
* return true if the internal state represents the signature described
* in the passed in array.
*/
- public bool VerifySignature(
+ public virtual bool VerifySignature(
byte[] signature)
{
if (forSigning)
@@ -197,7 +196,7 @@ namespace Org.BouncyCastle.Crypto.Signers
}
}
- public void Reset()
+ public virtual void Reset()
{
digest.Reset();
}
diff --git a/crypto/src/crypto/signers/X931Signer.cs b/crypto/src/crypto/signers/X931Signer.cs
new file mode 100644
index 000000000..cc3292159
--- /dev/null
+++ b/crypto/src/crypto/signers/X931Signer.cs
@@ -0,0 +1,235 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Utilities;
+
+namespace 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 static readonly IDictionary trailerMap = Platform.CreateHashtable();
+
+ static X931Signer()
+ {
+ trailerMap.Add("RIPEMD128", TRAILER_RIPEMD128);
+ trailerMap.Add("RIPEMD160", TRAILER_RIPEMD160);
+
+ trailerMap.Add("SHA-1", TRAILER_SHA1);
+ trailerMap.Add("SHA-224", TRAILER_SHA224);
+ trailerMap.Add("SHA-256", TRAILER_SHA256);
+ trailerMap.Add("SHA-384", TRAILER_SHA384);
+ trailerMap.Add("SHA-512", TRAILER_SHA512);
+
+ trailerMap.Add("Whirlpool", TRAILER_WHIRLPOOL);
+ }
+
+ private IDigest digest;
+ private IAsymmetricBlockCipher cipher;
+ private RsaKeyParameters kParam;
+
+ private int trailer;
+ private int keyBits;
+ private byte[] block;
+
+ /**
+ * Generate a signer for the with either implicit or explicit trailers
+ * for ISO9796-2.
+ *
+ * @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 = TRAILER_IMPLICIT;
+ }
+ else
+ {
+ string name = digest.AlgorithmName;
+ if (!trailerMap.Contains(name))
+ throw new ArgumentException("no valid trailer", "digest");
+
+ trailer = (int)trailerMap[name];
+ }
+ }
+
+ [Obsolete]
+ public virtual string AlgorithmName
+ {
+ get { return digest.AlgorithmName + "withX931"; }
+ }
+
+ /**
+ * 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));
+
+ return BigIntegers.AsUnsignedByteArray((kParam.Modulus.BitLength + 7) / 8, t);
+ }
+
+ private void CreateSignatureBlock()
+ {
+ int digSize = digest.GetDigestSize();
+
+ int delta;
+
+ if (trailer == TRAILER_IMPLICIT)
+ {
+ delta = block.Length - digSize - 1;
+ digest.DoFinal(block, delta);
+ block[block.Length - 1] = (byte)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(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;
+ }
+ }
+}
diff --git a/crypto/test/src/crypto/test/RegressionTest.cs b/crypto/test/src/crypto/test/RegressionTest.cs
index 27d6bb0e9..0b7a0f72d 100644
--- a/crypto/test/src/crypto/test/RegressionTest.cs
+++ b/crypto/test/src/crypto/test/RegressionTest.cs
@@ -118,7 +118,8 @@ namespace Org.BouncyCastle.Crypto.Tests
new SipHashTest(),
new Poly1305Test(),
new OcbTest(),
- new SM3DigestTest()
+ new SM3DigestTest(),
+ new X931SignerTest()
};
public static void Main(
diff --git a/crypto/test/src/crypto/test/X931SignerTest.cs b/crypto/test/src/crypto/test/X931SignerTest.cs
new file mode 100644
index 000000000..d03cbc8e4
--- /dev/null
+++ b/crypto/test/src/crypto/test/X931SignerTest.cs
@@ -0,0 +1,145 @@
+using System;
+
+using Org.BouncyCastle.Crypto.Digests;
+using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Crypto.Signers;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+using NUnit.Framework;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+ [TestFixture]
+ public class X931SignerTest
+ : SimpleTest
+ {
+ public override string Name
+ {
+ get { return "X931Signer"; }
+ }
+
+ public override void PerformTest()
+ {
+ BigInteger rsaPubMod = new BigInteger(Base64.Decode("AIASoe2PQb1IP7bTyC9usjHP7FvnUMVpKW49iuFtrw/dMpYlsMMoIU2jupfifDpdFxIktSB4P+6Ymg5WjvHKTIrvQ7SR4zV4jaPTu56Ys0pZ9EDA6gb3HLjtU+8Bb1mfWM+yjKxcPDuFjwEtjGlPHg1Vq+CA9HNcMSKNn2+tW6qt"));
+ BigInteger rsaPubExp = new BigInteger(Base64.Decode("EQ=="));
+ BigInteger rsaPrivMod = new BigInteger(Base64.Decode("AIASoe2PQb1IP7bTyC9usjHP7FvnUMVpKW49iuFtrw/dMpYlsMMoIU2jupfifDpdFxIktSB4P+6Ymg5WjvHKTIrvQ7SR4zV4jaPTu56Ys0pZ9EDA6gb3HLjtU+8Bb1mfWM+yjKxcPDuFjwEtjGlPHg1Vq+CA9HNcMSKNn2+tW6qt"));
+ BigInteger rsaPrivDP = new BigInteger(Base64.Decode("JXzfzG5v+HtLJIZqYMUefJfFLu8DPuJGaLD6lI3cZ0babWZ/oPGoJa5iHpX4Ul/7l3s1PFsuy1GhzCdOdlfRcQ=="));
+ BigInteger rsaPrivDQ = new BigInteger(Base64.Decode("YNdJhw3cn0gBoVmMIFRZzflPDNthBiWy/dUMSRfJCxoZjSnr1gysZHK01HteV1YYNGcwPdr3j4FbOfri5c6DUQ=="));
+ BigInteger rsaPrivExp = new BigInteger(Base64.Decode("DxFAOhDajr00rBjqX+7nyZ/9sHWRCCp9WEN5wCsFiWVRPtdB+NeLcou7mWXwf1Y+8xNgmmh//fPV45G2dsyBeZbXeJwB7bzx9NMEAfedchyOwjR8PYdjK3NpTLKtZlEJ6Jkh4QihrXpZMO4fKZWUm9bid3+lmiq43FwW+Hof8/E="));
+ BigInteger rsaPrivP = new BigInteger(Base64.Decode("AJ9StyTVW+AL/1s7RBtFwZGFBgd3zctBqzzwKPda6LbtIFDznmwDCqAlIQH9X14X7UPLokCDhuAa76OnDXb1OiE="));
+ BigInteger rsaPrivQ = new BigInteger(Base64.Decode("AM3JfD79dNJ5A3beScSzPtWxx/tSLi0QHFtkuhtSizeXdkv5FSba7lVzwEOGKHmW829bRoNxThDy4ds1IihW1w0="));
+ BigInteger rsaPrivQinv = new BigInteger(Base64.Decode("Lt0g7wrsNsQxuDdB8q/rH8fSFeBXMGLtCIqfOec1j7FEIuYA/ACiRDgXkHa0WgN7nLXSjHoy630wC5Toq8vvUg=="));
+ RsaKeyParameters rsaPublic = new RsaKeyParameters(false, rsaPubMod, rsaPubExp);
+ RsaPrivateCrtKeyParameters rsaPrivate = new RsaPrivateCrtKeyParameters(rsaPrivMod, rsaPubExp, rsaPrivExp, rsaPrivP, rsaPrivQ, rsaPrivDP, rsaPrivDQ, rsaPrivQinv);
+
+ byte[] msg = new byte[] { 1, 6, 3, 32, 7, 43, 2, 5, 7, 78, 4, 23 };
+
+ X931Signer signer = new X931Signer(new RsaEngine(), new Sha1Digest());
+ signer.Init(true, rsaPrivate);
+ signer.BlockUpdate(msg, 0, msg.Length);
+ byte[] sig = signer.GenerateSignature();
+
+ signer = new X931Signer(new RsaEngine(), new Sha1Digest());
+ signer.Init(false, rsaPublic);
+ signer.BlockUpdate(msg, 0, msg.Length);
+ if (!signer.VerifySignature(sig))
+ {
+ Fail("X9.31 Signer failed.");
+ }
+
+ ShouldPassSignatureTest1();
+ ShouldPassSignatureTest2();
+ ShouldPassSignatureTest3();
+ }
+
+ private void ShouldPassSignatureTest1()
+ {
+ BigInteger n = new BigInteger("c9be1b28f8caccca65d86cc3c9bbcc13eccc059df3b80bd2292b811eff3aa0dd75e1e85c333b8e3fa9bed53bb20f5359ff4e6900c5e9a388e3a4772a583a79e2299c76582c2b27694b65e9ba22e66bfb817f8b70b22206d7d8ae488c86dbb7137c26d5eff9b33c90e6cee640630313b7a715802e15142fef498c404a8de19674974785f0f852e2d470fe85a2e54ffca9f5851f672b71df691785a5cdabe8f14aa628942147de7593b2cf962414a5b59c632c4e14f1768c0ab2e9250824beea60a3529f11bf5e070ce90a47686eb0be1086fb21f0827f55295b4a48307db0b048c05a4aec3f488c576ca6f1879d354224c7e84cbcd8e76dd217a3de54dba73c35", 16);
+ BigInteger e = new BigInteger("e75b1b", 16);
+ byte[] msg = Hex.Decode("5bb0d1c0ef9b5c7af2477fe08d45523d3842a4b2db943f7033126c2a7829bacb3d2cfc6497ec91688189e81b7f8742488224ba320ce983ce9480722f2cc5bc42611f00bb6311884f660ccc244788378673532edb05284fd92e83f6f6dab406209032e6af9a33c998677933e32d6fb95fd27408940d7728f9c9c40267ca1d20ce");
+ byte[] sig = Hex.Decode("0fe8bb8e3109a1eb7489ef35bf4c1a0780071da789c8bd226a4170538eafefdd30b732d628f0e87a0b9450051feae9754d4fb61f57862d10f0bacc4f660d13281d0cd1141c006ade5186ff7d961a4c6cd0a4b352fc1295c5afd088f80ac1f8e192ef116a010a442655fe8ff5eeacea15807906fb0f0dfa86e680d4c005872357f7ece9aa4e20b15d5f709b30f08648ecaa34f2fbf54eb6b414fa2ff6f87561f70163235e69ccb4ac82a2e46d3be214cc2ef5263b569b2d8fd839b21a9e102665105ea762bda25bb446cfd831487a6b846100dee113ae95ae64f4af22c428c87bab809541c962bb3a56d4c86588e0af4ebc7fcc66dadced311051356d3ea745f7");
+
+ RsaKeyParameters rsaPublic = new RsaKeyParameters(false, n, e);
+ X931Signer signer = new X931Signer(new RsaEngine(), new Sha1Digest());
+
+ signer.Init(false, rsaPublic);
+
+ signer.BlockUpdate(msg, 0, msg.Length);
+
+ if (!signer.VerifySignature(sig))
+ {
+ Fail("RSA X931 verify test 1 failed.");
+ }
+ }
+
+ private void ShouldPassSignatureTest2()
+ {
+ BigInteger n = new BigInteger("b746ba6c3c0be64bbe33aa55b2929b0af4e86d773d44bfe5914db9287788c4663984b61a418d2eecca30d752ff6b620a07ec72eeb2b422d2429da352407b99982800b9dd7697be6a7b1baa98ca5f4fc2fe33400f20b9dba337ac25c987804165d4a6e0ee4d18eabd6de5abdfe578cae6713ff91d16c80a5bb20217fe614d9509e75a43e1825327b9da8f0a9f6eeaa1c04b69fb4bacc073569fff4ab491becbe6d0441d437fc3fa823239c4a0f75321666b68dd3f66e2dd394089a15bcc288a68a4eb0a48e17d639743b9dea0a91cc35820544732aff253f8ca9967c609dc01c2f8cd0313a7a91cfa94ff74289a1d2b6f19d1811f4b9a65f4cce9e5759b4cc64f", 16);
+ BigInteger e = new BigInteger("dcbbdb", 16);
+ byte[] msg = Hex.Decode("a5d3c8a060f897bbbc20ae0955052f37fbc70986b6e11c65075c9f457142bfa93856897c69020aa81a91b5e4f39e05cdeecc63395ab849c8262ca8bc5c96870aecb8edb0aba0024a9bdb71e06de6100344e5c318bc979ef32b8a49a8278ba99d4861bce42ebbc5c8c666aaa6cac39aff8779f2cae367620f9edd4cb1d80b6c8c");
+ byte[] sig = Hex.Decode("39fbbd1804c689a533b0043f84da0f06081038c0fbf31e443e46a05e58f50de5198bbca40522afefaba3aed7082a6cb93b1da39f1f5a42246bf64930781948d300549bef0f8d554ecfca60a1b1ecba95a7014ee4545ad4f0c4e3a31942c6738b4ccd6244b6a21267dadf0826a5f713f13b1f5a9ab8501d957a26d4948278ac67851071a315674bdab173bfef2c2690c8373da6bf3d69f30c0e5da8883de872f59521b40793854085641adf98d13db991c5d0a8aaa0222934fa33332e90ef0b954e195cb267d6ffb36c96e14d1ec7b915a87598b4461a3146566354dc2ae748c84ee0cd46543b53ebff8cdf47725b280a1f799fb6ebb4a31ad2bdd5178250f83a");
+
+ RsaKeyParameters rsaPublic = new RsaKeyParameters(false, n, e);
+ X931Signer signer = new X931Signer(new RsaEngine(), new Sha224Digest());
+
+ signer.Init(false, rsaPublic);
+
+ signer.BlockUpdate(msg, 0, msg.Length);
+
+ if (!signer.VerifySignature(sig))
+ {
+ Fail("RSA X931 verify test 2 failed.");
+ }
+ }
+
+ private void ShouldPassSignatureTest3()
+ {
+ BigInteger n = new BigInteger("dcb5686a3d2063a3f9cf7b9b32d2d3765b4c449b09b4960245a9111cd3b0cbd3260496885b8e1fa5db33b03efcc759d9c1afe29d93c6faebc7e0efada334b5b9a29655e2da2c8f11103d8203be311feab7ae88e9f1b2ec7d8fc655d77202b1681dd9717ec0f525b35584987e19539635a1ed23ca482a00149c609a23dc1645fd", 16);
+ BigInteger e = new BigInteger("00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000dc9f7", 16);
+ BigInteger d = new BigInteger("189d6345099098992e0c9ca5f281e1338092342fa0acc85cc2a111f30f9bd2fb4753cd1a48ef0ddca9bf1af33ec76fb2e23a9fb4896c26f2235b516f7c05ef7ae81e70f4b491a5fedba9b935e9c76d761a813ce7776ff8a1e5efe1166ff2eca26aa900da88c908d51af9de26977fe39719cc781df32216fa41b838f0c63803c3", 16);
+
+ byte[] msg = Hex.Decode("911475c6e210ef4ac65b6fe8d2bfe5e01b959771b137c4ef69b88716e0d2ff9ebc1fad0f358c1dd7d50cc99a7b893ac9a6207076f08d8467d9e48c69c683bfe64a44dabaa3f7c243880f6ab7229bf7bb587822314fc5de5131983bfb2eef8b4bc1eac36f353724b567cd1ae8cddd64ddb7057549d5c81ad5fa3b5e751f00abf5");
+ byte[] sig = Hex.Decode("02c50ec0ac8a7f38ef5630c396964d6a6daaa7e3083ab5b57fa2a2632f3b70e2e85c8456cd774d45d7e44fcb063f0f04fff9f1e3adfda11272535a92cb59320b190b5ee4261f23d6ceaa925df3a7bfa42e26bf61ea9645d9d64b3c90a820802768a6e209c9f83705375a3867afccc037e8242a98fa4c3db6b2d9877754d47289");
+
+ RsaKeyParameters rsaPublic = new RsaKeyParameters(false, n, e);
+ X931Signer signer = new X931Signer(new RsaEngine(), new Sha1Digest());
+
+ signer.Init(true, new RsaKeyParameters(true, n, d));
+
+ signer.BlockUpdate(msg, 0, msg.Length);
+
+ byte[] s = signer.GenerateSignature();
+
+ if (!Arrays.AreEqual(sig, s))
+ {
+ Fail("RSA X931 sig test 3 failed.");
+ }
+
+ signer.Init(false, rsaPublic);
+
+ signer.BlockUpdate(msg, 0, msg.Length);
+
+ if (!signer.VerifySignature(sig))
+ {
+ Fail("RSA X931 verify test 3 failed.");
+ }
+ }
+
+ public static void Main(string[] args)
+ {
+ RunTest(new X931SignerTest());
+ }
+
+ [Test]
+ public void TestFunction()
+ {
+ string resultText = Perform().ToString();
+
+ Assert.AreEqual(Name + ": Okay", resultText);
+ }
+ }
+}
|