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());
|