summary refs log tree commit diff
diff options
context:
space:
mode:
authorPeter Dettman <peter.dettman@bouncycastle.org>2019-06-01 18:58:01 +0700
committerPeter Dettman <peter.dettman@bouncycastle.org>2019-06-01 18:58:01 +0700
commit17dbcd1de2147c407f30f84d29ac6e223baf5d73 (patch)
tree95a935970c10b2d180a0aae388d60b431ed745ce
parentMerge branch 'rastrup-patch-4' (diff)
downloadBouncyCastle.NET-ed25519-17dbcd1de2147c407f30f84d29ac6e223baf5d73.tar.xz
Support SM2 in SignerUtilities
- including support for non-standard SHA256withSM2
-rw-r--r--crypto/src/cms/CMSSignedGenerator.cs6
-rw-r--r--crypto/src/crypto/signers/SM2Signer.cs28
-rw-r--r--crypto/src/security/SignerUtilities.cs16
-rw-r--r--crypto/test/src/crypto/test/SM2SignerTest.cs260
-rw-r--r--crypto/test/src/security/test/TestSignerUtil.cs39
5 files changed, 240 insertions, 109 deletions
diff --git a/crypto/src/cms/CMSSignedGenerator.cs b/crypto/src/cms/CMSSignedGenerator.cs
index c7bc4ea43..b618ae3d4 100644
--- a/crypto/src/cms/CMSSignedGenerator.cs
+++ b/crypto/src/cms/CMSSignedGenerator.cs
@@ -134,6 +134,8 @@ namespace Org.BouncyCastle.Cms
             algorithms["SHA512WITHCVC-ECDSA"] = EacObjectIdentifiers.id_TA_ECDSA_SHA_512;
             algorithms["SHA3-512WITHSPHINCS256"] = BCObjectIdentifiers.sphincs256_with_SHA3_512;
             algorithms["SHA512WITHSPHINCS256"] = BCObjectIdentifiers.sphincs256_with_SHA512;
+
+            algorithms["SHA256WITHSM2"] = GMObjectIdentifiers.sm2sign_with_sha256;
             algorithms["SM3WITHSM2"] = GMObjectIdentifiers.sm2sign_with_sm3;
 
             algorithms["SHA256WITHXMSS"] = BCObjectIdentifiers.xmss_with_SHA256;
@@ -200,6 +202,7 @@ namespace Org.BouncyCastle.Cms
             //
             // SM2
             //
+            noParams.Add((object)GMObjectIdentifiers.sm2sign_with_sha256);
             noParams.Add((object)GMObjectIdentifiers.sm2sign_with_sm3);
 
             //
@@ -283,8 +286,9 @@ namespace Org.BouncyCastle.Cms
             digestOids[CryptoProObjectIdentifiers.GostR3411x94WithGostR3410x2001] = CryptoProObjectIdentifiers.GostR3411;
             digestOids[RosstandartObjectIdentifiers.id_tc26_signwithdigest_gost_3410_12_256] = RosstandartObjectIdentifiers.id_tc26_gost_3411_12_256;
             digestOids[RosstandartObjectIdentifiers.id_tc26_signwithdigest_gost_3410_12_512] = RosstandartObjectIdentifiers.id_tc26_gost_3411_12_512;
-            digestOids[GMObjectIdentifiers.sm2sign_with_sm3] = GMObjectIdentifiers.sm3;
 
+            digestOids[GMObjectIdentifiers.sm2sign_with_sha256] = NistObjectIdentifiers.IdSha256;
+            digestOids[GMObjectIdentifiers.sm2sign_with_sm3] = GMObjectIdentifiers.sm3;
         }
 
         private static AlgorithmIdentifier Generate(string signatureAlgorithm)
diff --git a/crypto/src/crypto/signers/SM2Signer.cs b/crypto/src/crypto/signers/SM2Signer.cs
index d9ec20525..56ec17cf3 100644
--- a/crypto/src/crypto/signers/SM2Signer.cs
+++ b/crypto/src/crypto/signers/SM2Signer.cs
@@ -15,7 +15,7 @@ namespace Org.BouncyCastle.Crypto.Signers
         : ISigner
     {
         private readonly IDsaKCalculator kCalculator = new RandomDsaKCalculator();
-        private readonly SM3Digest digest = new SM3Digest();
+        private readonly IDigest digest;
         private readonly IDsaEncoding encoding;
 
         private ECDomainParameters ecParams;
@@ -24,13 +24,24 @@ namespace Org.BouncyCastle.Crypto.Signers
         private byte[] z;
 
         public SM2Signer()
+            : this(StandardDsaEncoding.Instance, new SM3Digest())
+        {
+        }
+
+        public SM2Signer(IDigest digest)
+            : this(StandardDsaEncoding.Instance, digest)
         {
-            this.encoding = StandardDsaEncoding.Instance;
         }
 
         public SM2Signer(IDsaEncoding encoding)
+            : this(encoding, new SM3Digest())
+        {
+        }
+
+        public SM2Signer(IDsaEncoding encoding, IDigest digest)
         {
             this.encoding = encoding;
+            this.digest = digest;
         }
 
         public virtual string AlgorithmName
@@ -47,11 +58,15 @@ namespace Org.BouncyCastle.Crypto.Signers
             {
                 baseParam = ((ParametersWithID)parameters).Parameters;
                 userID = ((ParametersWithID)parameters).GetID();
+
+                if (userID.Length >= 8192)
+                    throw new ArgumentException("SM2 user ID must be less than 2^16 bits long");
             }
             else
             {
                 baseParam = parameters;
-                userID = Hex.Decode("31323334353637383132333435363738"); // the default value (ASCII "1234567812345678")
+                // the default value, string value is "1234567812345678"
+                userID = Hex.Decode("31323334353637383132333435363738");
             }
 
             if (forSigning)
@@ -124,7 +139,7 @@ namespace Org.BouncyCastle.Crypto.Signers
             byte[] eHash = DigestUtilities.DoFinal(digest);
 
             BigInteger n = ecParams.N;
-            BigInteger e = CalculateE(eHash);
+            BigInteger e = CalculateE(n, eHash);
             BigInteger d = ((ECPrivateKeyParameters)ecKey).D;
 
             BigInteger r, s;
@@ -184,7 +199,7 @@ namespace Org.BouncyCastle.Crypto.Signers
             byte[] eHash = DigestUtilities.DoFinal(digest);
 
             // B4
-            BigInteger e = CalculateE(eHash);
+            BigInteger e = CalculateE(n, eHash);
 
             // B5
             BigInteger t = r.Add(s).Mod(n);
@@ -229,8 +244,9 @@ namespace Org.BouncyCastle.Crypto.Signers
             digest.BlockUpdate(p, 0, p.Length);
         }
 
-        protected virtual BigInteger CalculateE(byte[] message)
+        protected virtual BigInteger CalculateE(BigInteger n, byte[] message)
         {
+            // TODO Should hashes larger than the order be truncated as with ECDSA?
             return new BigInteger(1, message);
         }
 
diff --git a/crypto/src/security/SignerUtilities.cs b/crypto/src/security/SignerUtilities.cs
index ae8d21f0a..93d20a697 100644
--- a/crypto/src/security/SignerUtilities.cs
+++ b/crypto/src/security/SignerUtilities.cs
@@ -7,6 +7,7 @@ using Org.BouncyCastle.Asn1.Bsi;
 using Org.BouncyCastle.Asn1.CryptoPro;
 using Org.BouncyCastle.Asn1.Eac;
 using Org.BouncyCastle.Asn1.EdEC;
+using Org.BouncyCastle.Asn1.GM;
 using Org.BouncyCastle.Asn1.Nist;
 using Org.BouncyCastle.Asn1.Oiw;
 using Org.BouncyCastle.Asn1.Pkcs;
@@ -344,6 +345,11 @@ namespace Org.BouncyCastle.Security
             algorithms[EdECObjectIdentifiers.id_Ed448.Id] = "Ed448";
             algorithms["ED448PH"] = "Ed448ph";
 
+            algorithms["SHA256WITHSM2"] = "SHA256withSM2";
+            algorithms[GMObjectIdentifiers.sm2sign_with_sha256.Id] = "SHA256withSM2";
+            algorithms["SM3WITHSM2"] = "SM3withSM2";
+            algorithms[GMObjectIdentifiers.sm2sign_with_sm3.Id] = "SM3withSM2";
+
             oids["MD2withRSA"] = PkcsObjectIdentifiers.MD2WithRsaEncryption;
             oids["MD4withRSA"] = PkcsObjectIdentifiers.MD4WithRsaEncryption;
             oids["MD5withRSA"] = PkcsObjectIdentifiers.MD5WithRsaEncryption;
@@ -392,6 +398,9 @@ namespace Org.BouncyCastle.Security
 
             oids["Ed25519"] = EdECObjectIdentifiers.id_Ed25519;
             oids["Ed448"] = EdECObjectIdentifiers.id_Ed448;
+
+            oids["SHA256withSM2"] = GMObjectIdentifiers.sm2sign_with_sha256;
+            oids["SM3withSM2"] = GMObjectIdentifiers.sm2sign_with_sm3;
         }
 
         /// <summary>
@@ -570,6 +579,13 @@ namespace Org.BouncyCastle.Security
                 return new DsaDigestSigner(new ECNRSigner(), digest);
             }
 
+            if (Platform.EndsWith(mechanism, "withSM2"))
+            {
+                string digestName = mechanism.Substring(0, mechanism.LastIndexOf("with"));
+                IDigest digest = DigestUtilities.GetDigest(digestName);
+                return new SM2Signer(digest);
+            }
+
             if (mechanism.Equals("GOST3410"))
             {
                 return new Gost3410DigestSigner(new Gost3410Signer(), new Gost3411Digest());
diff --git a/crypto/test/src/crypto/test/SM2SignerTest.cs b/crypto/test/src/crypto/test/SM2SignerTest.cs
index e3c9c21ae..67cb1a443 100644
--- a/crypto/test/src/crypto/test/SM2SignerTest.cs
+++ b/crypto/test/src/crypto/test/SM2SignerTest.cs
@@ -4,6 +4,8 @@ using System.IO;
 using NUnit.Framework;
 
 using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X9;
+using Org.BouncyCastle.Crypto.Digests;
 using Org.BouncyCastle.Crypto.Generators;
 using Org.BouncyCastle.Crypto.Parameters;
 using Org.BouncyCastle.Crypto.Signers;
@@ -18,132 +20,157 @@ namespace Org.BouncyCastle.Crypto.Tests
     public class SM2SignerTest
         : SimpleTest
     {
+        private static readonly ECDomainParameters ParametersFpDraft = CreateParamsFpDraft();
+        private static readonly ECDomainParameters ParametersF2m = CreateParamsF2m();
+
         public override string Name
         {
             get { return "SM2Signer"; }
         }
 
-        private void DoSignerTestFp()
+        private void DoSignerTestFpDraftSM3()
         {
-            BigInteger SM2_ECC_P = new BigInteger("8542D69E4C044F18E8B92435BF6FF7DE457283915C45517D722EDB8B08F1DFC3", 16);
-            BigInteger SM2_ECC_A = new BigInteger("787968B4FA32C3FD2417842E73BBFEFF2F3C848B6831D7E0EC65228B3937E498", 16);
-            BigInteger SM2_ECC_B = new BigInteger("63E4C6D3B23B0C849CF84241484BFE48F61D59A5B16BA06E6E12D1DA27C5249A", 16);
-            BigInteger SM2_ECC_N = new BigInteger("8542D69E4C044F18E8B92435BF6FF7DD297720630485628D5AE74EE7C32E79B7", 16);
-            BigInteger SM2_ECC_H = BigInteger.ValueOf(4);
-            BigInteger SM2_ECC_GX = new BigInteger("421DEBD61B62EAB6746434EBC3CC315E32220B3BADD50BDC4C4E6C147FEDD43D", 16);
-            BigInteger SM2_ECC_GY = new BigInteger("0680512BCBB42C07D47349D2153B70C4E5D7FDFCBFA36EA1A85841B9E46E09A2", 16);
-
-            ECCurve curve = new FpCurve(SM2_ECC_P, SM2_ECC_A, SM2_ECC_B, SM2_ECC_N, SM2_ECC_H);
-
-            ECPoint g = curve.CreatePoint(SM2_ECC_GX, SM2_ECC_GY);
-            ECDomainParameters domainParams = new ECDomainParameters(curve, g, SM2_ECC_N);
-
-            ECKeyGenerationParameters keyGenerationParams = new ECKeyGenerationParameters(domainParams, new TestRandomBigInteger("128B2FA8BD433C6C068C8D803DFF79792A519A55171B1B650C23661D15897263", 16));
-            ECKeyPairGenerator keyPairGenerator = new ECKeyPairGenerator();
-
-            keyPairGenerator.Init(keyGenerationParams);
-            AsymmetricCipherKeyPair kp = keyPairGenerator.GenerateKeyPair();
-
-            ECPublicKeyParameters ecPub = (ECPublicKeyParameters)kp.Public;
-            ECPrivateKeyParameters ecPriv = (ECPrivateKeyParameters)kp.Private;
-
-            SM2Signer signer = new SM2Signer();
-
-            signer.Init(true,
-                new ParametersWithID(new ParametersWithRandom(ecPriv,
-                        new TestRandomBigInteger("6CB28D99385C175C94F94E934817663FC176D925DD72B727260DBAAE1FB2F96F", 16)),
-                    Strings.ToByteArray("ALICE123@YAHOO.COM")));
-
-            byte[] msg = Strings.ToByteArray("message digest");
-
-            signer.BlockUpdate(msg, 0, msg.Length);
-
-            byte[] sig = signer.GenerateSignature();
+            DoSignerTest(
+                ParametersFpDraft,
+                new SM3Digest(),
+                "ALICE123@YAHOO.COM",
+                "message digest",
+                "128B2FA8BD433C6C068C8D803DFF79792A519A55171B1B650C23661D15897263",
+                "6CB28D99385C175C94F94E934817663FC176D925DD72B727260DBAAE1FB2F96F",
+                "40F1EC59F793D9F49E09DCEF49130D4194F79FB1EED2CAA55BACDB49C4E755D1",
+                "6FC6DAC32C5D5CF10C77DFB20F7C2EB667A457872FB09EC56327A67EC7DEEBE7"
+            );
+        }
 
-            BigInteger[] rs = Decode(sig);
+        private void DoSignerTestFpDraftSha256()
+        {
+            DoSignerTest(
+                ParametersFpDraft,
+                new Sha256Digest(),
+                "ALICE123@YAHOO.COM",
+                "message digest",
+                "128B2FA8BD433C6C068C8D803DFF79792A519A55171B1B650C23661D15897263",
+                "6CB28D99385C175C94F94E934817663FC176D925DD72B727260DBAAE1FB2F96F",
+                "7D62A5EDBDDC8AF4D69C9E37A60D31F5CEFE8727709117E0869648D0A9AE4F57",
+                "1E5E89718B716AAFC6253443168E4F7CF7E1B7B3934307686CE5947C1BD55EDA"
+            );
+        }
 
-            IsTrue("r wrong", rs[0].Equals(new BigInteger("40F1EC59F793D9F49E09DCEF49130D4194F79FB1EED2CAA55BACDB49C4E755D1", 16)));
-            IsTrue("s wrong", rs[1].Equals(new BigInteger("6FC6DAC32C5D5CF10C77DFB20F7C2EB667A457872FB09EC56327A67EC7DEEBE7", 16)));
+        private void DoSignerTestFpStandardSM3()
+        {
+            DoSignerTest(
+                "sm2p256v1",
+                new SM3Digest(),
+                "sm2test@example.com",
+                "hi chappy",
+                "110E7973206F68C19EE5F7328C036F26911C8C73B4E4F36AE3291097F8984FFC",
+                "3174C6FFC3C279D2422F3FC0A9F3E574674A4490FE45A5325CAF7D3EC4C8F96C",
+                "05890B9077B92E47B17A1FF42A814280E556AFD92B4A98B9670BF8B1A274C2FA",
+                "E3ABBB8DB2B6ECD9B24ECCEA7F679FB9A4B1DB52F4AA985E443AD73237FA1993"
+            );
+        }
 
-            signer.Init(false, new ParametersWithID(ecPub, Strings.ToByteArray("ALICE123@YAHOO.COM")));
+        private void DoSignerTestFpStandardSha256()
+        {
+            DoSignerTest(
+                "sm2p256v1",
+                new Sha256Digest(),
+                "sm2test@example.com",
+                "hi chappy",
+                "110E7973206F68C19EE5F7328C036F26911C8C73B4E4F36AE3291097F8984FFC",
+                "3174C6FFC3C279D2422F3FC0A9F3E574674A4490FE45A5325CAF7D3EC4C8F96C",
+                "94DA20EA69E4FC70692158BF3D30F87682A4B2F84DF4A4829A1EFC5D9C979D3F",
+                "EE15AF8D455B728AB80E592FCB654BF5B05620B2F4D25749D263D5C01FAD365F"
+            );
+        }
 
-            signer.BlockUpdate(msg, 0, msg.Length);
+        private void DoSignerTestFpP256SM3()
+        {
+            DoSignerTest(
+                "P-256",
+                new SM3Digest(),
+                "sm2_p256_test@example.com",
+                "no backdoors here",
+                "110E7973206F68C19EE5F7328C036F26911C8C73B4E4F36AE3291097F8984FFC",
+                "3174C6FFC3C279D2422F3FC0A9F3E574674A4490FE45A5325CAF7D3EC4C8F96C",
+                "96AA39A0C4A5C454653F394E86386F2E38BE14C57D0E555F3A27A5CEF30E51BD",
+                "62372BE4AC97DBE725AC0B279BB8FD15883858D814FD792DDB0A401DCC988E70"
+            );
+        }
 
-            IsTrue("verification failed", signer.VerifySignature(sig));
+        private void DoSignerTestFpP256Sha256()
+        {
+            DoSignerTest(
+                "P-256",
+                new Sha256Digest(),
+                "sm2_p256_test@example.com",
+                "no backdoors here",
+                "110E7973206F68C19EE5F7328C036F26911C8C73B4E4F36AE3291097F8984FFC",
+                "3174C6FFC3C279D2422F3FC0A9F3E574674A4490FE45A5325CAF7D3EC4C8F96C",
+                "503D234A22123D7029271EB9E0D763619A69868DE8296C13EDD4CA32D280CFDE",
+                "0BDE97699B77268584DDD238DA120095F01130AD2DB37184270F37C02FB2E86B"
+            );
         }
 
         private void DoSignerTestF2m()
         {
-            BigInteger SM2_ECC_A = new BigInteger("00", 16);
-            BigInteger SM2_ECC_B = new BigInteger("E78BCD09746C202378A7E72B12BCE00266B9627ECB0B5A25367AD1AD4CC6242B", 16);
-            BigInteger SM2_ECC_N = new BigInteger("7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBC972CF7E6B6F900945B3C6A0CF6161D", 16);
-            BigInteger SM2_ECC_H = BigInteger.ValueOf(4);
-            BigInteger SM2_ECC_GX = new BigInteger("00CDB9CA7F1E6B0441F658343F4B10297C0EF9B6491082400A62E7A7485735FADD", 16);
-            BigInteger SM2_ECC_GY = new BigInteger("013DE74DA65951C4D76DC89220D5F7777A611B1C38BAE260B175951DC8060C2B3E", 16);
-
-            ECCurve curve = new F2mCurve(257, 12, SM2_ECC_A, SM2_ECC_B, SM2_ECC_N, SM2_ECC_H);
-
-            ECPoint g = curve.CreatePoint(SM2_ECC_GX, SM2_ECC_GY);
-            ECDomainParameters domainParams = new ECDomainParameters(curve, g, SM2_ECC_N);
-
-            ECKeyGenerationParameters keyGenerationParams = new ECKeyGenerationParameters(domainParams, new TestRandomBigInteger("771EF3DBFF5F1CDC32B9C572930476191998B2BF7CB981D7F5B39202645F0931", 16));
-            ECKeyPairGenerator keyPairGenerator = new ECKeyPairGenerator();
+            DoSignerTest(
+                ParametersF2m,
+                new SM3Digest(),
+                "ALICE123@YAHOO.COM",
+                "message digest",
+                "771EF3DBFF5F1CDC32B9C572930476191998B2BF7CB981D7F5B39202645F0931",
+                "36CD79FC8E24B7357A8A7B4A46D454C397703D6498158C605399B341ADA186D6",
+                "6D3FBA26EAB2A1054F5D198332E335817C8AC453ED26D3391CD4439D825BF25B",
+                "3124C5688D95F0A10252A9BED033BEC84439DA384621B6D6FAD77F94B74A9556"
+            );
+        }
 
-            keyPairGenerator.Init(keyGenerationParams);
-            AsymmetricCipherKeyPair kp = keyPairGenerator.GenerateKeyPair();
+        private void DoSignerTest(string curveName, IDigest d, string ident, string msg, string x, string nonce, string r, string s)
+        {
+            X9ECParameters x9 = ECNamedCurveTable.GetByName(curveName);
+            ECDomainParameters domainParams = new ECDomainParameters(x9.Curve, x9.G, x9.N, x9.H, x9.GetSeed());
 
-            ECPublicKeyParameters ecPub = (ECPublicKeyParameters)kp.Public;
-            ECPrivateKeyParameters ecPriv = (ECPrivateKeyParameters)kp.Private;
+            DoSignerTest(domainParams, d, ident, msg, x, nonce, r, s);
+        }
 
-            SM2Signer signer = new SM2Signer();
+        private void DoSignerTest(ECDomainParameters domainParams, IDigest d, string ident, string msg, string x, string nonce, string r, string s)
+        {
+            byte[] idBytes = Strings.ToByteArray(ident);
+            byte[] msgBytes = Strings.ToByteArray(msg);
+            AsymmetricCipherKeyPair kp = GenerateKeyPair(domainParams, x);
 
-            signer.Init(true,
-                new ParametersWithID(new ParametersWithRandom(ecPriv,
-                        new TestRandomBigInteger("36CD79FC8E24B7357A8A7B4A46D454C397703D6498158C605399B341ADA186D6", 16)),
-                    Strings.ToByteArray("ALICE123@YAHOO.COM")));
+            SM2Signer signer = new SM2Signer(d);
 
-            byte[] msg = Strings.ToByteArray("message digest");
+            signer.Init(true, new ParametersWithID(
+                new ParametersWithRandom(kp.Private, new TestRandomBigInteger(nonce, 16)),
+                idBytes));
 
-            signer.BlockUpdate(msg, 0, msg.Length);
+            signer.BlockUpdate(msgBytes, 0, msgBytes.Length);
 
             byte[] sig = signer.GenerateSignature();
 
             BigInteger[] rs = Decode(sig);
 
-            IsTrue("F2m r wrong", rs[0].Equals(new BigInteger("6D3FBA26EAB2A1054F5D198332E335817C8AC453ED26D3391CD4439D825BF25B", 16)));
-            IsTrue("F2m s wrong", rs[1].Equals(new BigInteger("3124C5688D95F0A10252A9BED033BEC84439DA384621B6D6FAD77F94B74A9556", 16)));
+            IsTrue("r wrong", rs[0].Equals(new BigInteger(r, 16)));
+            IsTrue("s wrong", rs[1].Equals(new BigInteger(s, 16)));
 
-            signer.Init(false, new ParametersWithID(ecPub, Strings.ToByteArray("ALICE123@YAHOO.COM")));
+            signer.Init(false, new ParametersWithID(kp.Public, idBytes));
 
-            signer.BlockUpdate(msg, 0, msg.Length);
+            signer.BlockUpdate(msgBytes, 0, msgBytes.Length);
 
             IsTrue("verification failed", signer.VerifySignature(sig));
         }
 
         private void DoVerifyBoundsCheck()
         {
-            BigInteger SM2_ECC_A = new BigInteger("00", 16);
-            BigInteger SM2_ECC_B = new BigInteger("E78BCD09746C202378A7E72B12BCE00266B9627ECB0B5A25367AD1AD4CC6242B", 16);
-            BigInteger SM2_ECC_N = new BigInteger("7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBC972CF7E6B6F900945B3C6A0CF6161D", 16);
-            BigInteger SM2_ECC_GX = new BigInteger("00CDB9CA7F1E6B0441F658343F4B10297C0EF9B6491082400A62E7A7485735FADD", 16);
-            BigInteger SM2_ECC_GY = new BigInteger("013DE74DA65951C4D76DC89220D5F7777A611B1C38BAE260B175951DC8060C2B3E", 16);
-
-            ECCurve curve = new F2mCurve(257, 12, SM2_ECC_A, SM2_ECC_B);
+            ECDomainParameters domainParams = ParametersF2m;
 
-            ECPoint g = curve.CreatePoint(SM2_ECC_GX, SM2_ECC_GY);
-            ECDomainParameters domainParams = new ECDomainParameters(curve, g, SM2_ECC_N);
-
-            ECKeyGenerationParameters keyGenerationParams = new ECKeyGenerationParameters(domainParams, new TestRandomBigInteger("771EF3DBFF5F1CDC32B9C572930476191998B2BF7CB981D7F5B39202645F0931", 16));
-            ECKeyPairGenerator keyPairGenerator = new ECKeyPairGenerator();
-
-            keyPairGenerator.Init(keyGenerationParams);
-            AsymmetricCipherKeyPair kp = keyPairGenerator.GenerateKeyPair();
-
-            ECPublicKeyParameters ecPub = (ECPublicKeyParameters)kp.Public;
+            AsymmetricCipherKeyPair kp = GenerateKeyPair(domainParams, "771EF3DBFF5F1CDC32B9C572930476191998B2BF7CB981D7F5B39202645F0931");
 
             SM2Signer signer = new SM2Signer();
 
-            signer.Init(false, ecPub);
+            signer.Init(false, kp.Public);
 
             signer.BlockUpdate(new byte[20], 0, 20);
             IsTrue(!signer.VerifySignature(Encode(BigInteger.Zero, BigInteger.ValueOf(8))));
@@ -152,25 +179,65 @@ namespace Org.BouncyCastle.Crypto.Tests
             IsTrue(!signer.VerifySignature(Encode(BigInteger.ValueOf(8), BigInteger.Zero)));
 
             signer.BlockUpdate(new byte[20], 0, 20);
-            IsTrue(!signer.VerifySignature(Encode(SM2_ECC_N, BigInteger.ValueOf(8))));
+            IsTrue(!signer.VerifySignature(Encode(domainParams.N, BigInteger.ValueOf(8))));
 
             signer.BlockUpdate(new byte[20], 0, 20);
-            IsTrue(!signer.VerifySignature(Encode(BigInteger.ValueOf(8), SM2_ECC_N)));
+            IsTrue(!signer.VerifySignature(Encode(BigInteger.ValueOf(8), domainParams.N)));
         }
 
         public override void PerformTest()
         {
-            DoSignerTestFp();
+            DoSignerTestFpDraftSM3();
+            DoSignerTestFpDraftSha256();
+            DoSignerTestFpStandardSM3();
+            DoSignerTestFpStandardSha256();
+            DoSignerTestFpP256SM3();
+            DoSignerTestFpP256Sha256();
             DoSignerTestF2m();
             DoVerifyBoundsCheck();
         }
 
+        private static ECDomainParameters CreateParamsFpDraft()
+        {
+            BigInteger SM2_ECC_P = new BigInteger("8542D69E4C044F18E8B92435BF6FF7DE457283915C45517D722EDB8B08F1DFC3", 16);
+            BigInteger SM2_ECC_A = new BigInteger("787968B4FA32C3FD2417842E73BBFEFF2F3C848B6831D7E0EC65228B3937E498", 16);
+            BigInteger SM2_ECC_B = new BigInteger("63E4C6D3B23B0C849CF84241484BFE48F61D59A5B16BA06E6E12D1DA27C5249A", 16);
+            BigInteger SM2_ECC_N = new BigInteger("8542D69E4C044F18E8B92435BF6FF7DD297720630485628D5AE74EE7C32E79B7", 16);
+            BigInteger SM2_ECC_H = BigInteger.One;
+            BigInteger SM2_ECC_GX = new BigInteger("421DEBD61B62EAB6746434EBC3CC315E32220B3BADD50BDC4C4E6C147FEDD43D", 16);
+            BigInteger SM2_ECC_GY = new BigInteger("0680512BCBB42C07D47349D2153B70C4E5D7FDFCBFA36EA1A85841B9E46E09A2", 16);
+
+            ECCurve curve = new FpCurve(SM2_ECC_P, SM2_ECC_A, SM2_ECC_B, SM2_ECC_N, SM2_ECC_H);
+            ECPoint g = curve.CreatePoint(SM2_ECC_GX, SM2_ECC_GY);
+            return new ECDomainParameters(curve, g, SM2_ECC_N, SM2_ECC_H);
+        }
+
+        private static ECDomainParameters CreateParamsF2m()
+        {
+            BigInteger SM2_ECC_A = new BigInteger("00", 16);
+            BigInteger SM2_ECC_B = new BigInteger("E78BCD09746C202378A7E72B12BCE00266B9627ECB0B5A25367AD1AD4CC6242B", 16);
+            BigInteger SM2_ECC_N = new BigInteger("7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBC972CF7E6B6F900945B3C6A0CF6161D", 16);
+            BigInteger SM2_ECC_H = BigInteger.ValueOf(4);
+            BigInteger SM2_ECC_GX = new BigInteger("00CDB9CA7F1E6B0441F658343F4B10297C0EF9B6491082400A62E7A7485735FADD", 16);
+            BigInteger SM2_ECC_GY = new BigInteger("013DE74DA65951C4D76DC89220D5F7777A611B1C38BAE260B175951DC8060C2B3E", 16);
+
+            ECCurve curve = new F2mCurve(257, 12, SM2_ECC_A, SM2_ECC_B, SM2_ECC_N, SM2_ECC_H);
+            ECPoint g = curve.CreatePoint(SM2_ECC_GX, SM2_ECC_GY);
+            return new ECDomainParameters(curve, g, SM2_ECC_N, SM2_ECC_H);
+        }
+
         private static BigInteger[] Decode(byte[] sig)
         {
             Asn1Sequence s = Asn1Sequence.GetInstance(sig);
 
-            return new BigInteger[] { DerInteger.GetInstance(s[0]).Value,
-                DerInteger.GetInstance(s[1]).Value };
+            return new BigInteger[] {
+                DecodeValue(s[0]),
+                DecodeValue(s[1]) };
+        }
+
+        private static BigInteger DecodeValue(Asn1Encodable e)
+        {
+            return DerInteger.GetInstance(e).Value;
         }
 
         private static byte[] Encode(BigInteger r, BigInteger s)
@@ -178,6 +245,13 @@ namespace Org.BouncyCastle.Crypto.Tests
             return new DerSequence(new DerInteger(r), new DerInteger(s)).GetEncoded();
         }
 
+        private static AsymmetricCipherKeyPair GenerateKeyPair(ECDomainParameters domainParams, string x)
+        {
+            ECKeyPairGenerator kpg = new ECKeyPairGenerator();
+            kpg.Init(new ECKeyGenerationParameters(domainParams, new TestRandomBigInteger(x, 16)));
+            return kpg.GenerateKeyPair();
+        }
+
         public static void Main(
             string[] args)
         {
diff --git a/crypto/test/src/security/test/TestSignerUtil.cs b/crypto/test/src/security/test/TestSignerUtil.cs
index 48bf49a63..8088f21fd 100644
--- a/crypto/test/src/security/test/TestSignerUtil.cs
+++ b/crypto/test/src/security/test/TestSignerUtil.cs
@@ -25,6 +25,8 @@ namespace Org.BouncyCastle.Security.Tests
         [Test]
         public void TestAlgorithms()
         {
+            SecureRandom RANDOM = new SecureRandom();
+
             //
             // RSA parameters
             //
@@ -90,29 +92,43 @@ namespace Org.BouncyCastle.Security.Tests
             ecGostKpg.Init(
                 new ECKeyGenerationParameters(
                     CryptoProObjectIdentifiers.GostR3410x2001CryptoProA,
-                    new SecureRandom()));
+                    RANDOM));
 
             AsymmetricCipherKeyPair ecGostPair = ecGostKpg.GenerateKeyPair();
 
             IAsymmetricCipherKeyPairGenerator ed25519Kpg = GeneratorUtilities.GetKeyPairGenerator("Ed25519");
-            ed25519Kpg.Init(new Ed25519KeyGenerationParameters(new SecureRandom()));
+            ed25519Kpg.Init(new Ed25519KeyGenerationParameters(RANDOM));
             AsymmetricCipherKeyPair ed25519Pair = ed25519Kpg.GenerateKeyPair();
 
             IAsymmetricCipherKeyPairGenerator ed448Kpg = GeneratorUtilities.GetKeyPairGenerator("Ed448");
-            ed448Kpg.Init(new Ed448KeyGenerationParameters(new SecureRandom()));
+            ed448Kpg.Init(new Ed448KeyGenerationParameters(RANDOM));
             AsymmetricCipherKeyPair ed448Pair = ed448Kpg.GenerateKeyPair();
 
             //
             // GOST3410 parameters
             //
             IAsymmetricCipherKeyPairGenerator gostKpg = GeneratorUtilities.GetKeyPairGenerator("GOST3410");
-            gostKpg.Init(
-                new Gost3410KeyGenerationParameters(
-                    new SecureRandom(),
-                    CryptoProObjectIdentifiers.GostR3410x94CryptoProA));
-
+            gostKpg.Init(new Gost3410KeyGenerationParameters(RANDOM, CryptoProObjectIdentifiers.GostR3410x94CryptoProA));
             AsymmetricCipherKeyPair gostPair = gostKpg.GenerateKeyPair();
 
+            //
+            // SM2 parameters
+            //
+            BigInteger SM2_ECC_P = new BigInteger("8542D69E4C044F18E8B92435BF6FF7DE457283915C45517D722EDB8B08F1DFC3", 16);
+            BigInteger SM2_ECC_A = new BigInteger("787968B4FA32C3FD2417842E73BBFEFF2F3C848B6831D7E0EC65228B3937E498", 16);
+            BigInteger SM2_ECC_B = new BigInteger("63E4C6D3B23B0C849CF84241484BFE48F61D59A5B16BA06E6E12D1DA27C5249A", 16);
+            BigInteger SM2_ECC_N = new BigInteger("8542D69E4C044F18E8B92435BF6FF7DD297720630485628D5AE74EE7C32E79B7", 16);
+            BigInteger SM2_ECC_H = BigInteger.One;
+            BigInteger SM2_ECC_GX = new BigInteger("421DEBD61B62EAB6746434EBC3CC315E32220B3BADD50BDC4C4E6C147FEDD43D", 16);
+            BigInteger SM2_ECC_GY = new BigInteger("0680512BCBB42C07D47349D2153B70C4E5D7FDFCBFA36EA1A85841B9E46E09A2", 16);
+
+            ECCurve sm2Curve = new FpCurve(SM2_ECC_P, SM2_ECC_A, SM2_ECC_B, SM2_ECC_N, SM2_ECC_H);
+            ECPoint sm2G = sm2Curve.CreatePoint(SM2_ECC_GX, SM2_ECC_GY);
+            ECDomainParameters sm2Domain = new ECDomainParameters(sm2Curve, sm2G, SM2_ECC_N, SM2_ECC_H);
+
+            ECKeyPairGenerator sm2Kpg = new ECKeyPairGenerator();
+            sm2Kpg.Init(new ECKeyGenerationParameters(sm2Domain, RANDOM));
+            AsymmetricCipherKeyPair sm2Pair = sm2Kpg.GenerateKeyPair();
 
 
             //
@@ -120,7 +136,7 @@ namespace Org.BouncyCastle.Security.Tests
             //
             byte[] shortMsg = new byte[] { 1, 4, 5, 6, 8, 8, 4, 2, 1, 3 };
             byte[] longMsg = new byte[100];
-            new SecureRandom().NextBytes(longMsg);
+            RANDOM.NextBytes(longMsg);
 
             foreach (string algorithm in SignerUtilities.Algorithms)
             {
@@ -172,6 +188,11 @@ namespace Org.BouncyCastle.Security.Tests
                     signParams = gostPair.Private;
                     verifyParams = gostPair.Public;
                 }
+                else if (cipherName == "SM2")
+                {
+                    signParams = sm2Pair.Private;
+                    verifyParams = sm2Pair.Public;
+                }
                 else
                 {
                     Assert.Fail("Unknown algorithm encountered: " + cipherName);