diff --git a/CHANGELOG.md b/CHANGELOG.md index 6219ce04f..f4be29d81 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ * 【aop 】 增加Spring-cglib支持,改为SPI实现 * 【json 】 增加JSONUtil.parseXXX增加JSONConfig参数 * 【core 】 RandomUtil.randomNumber改为返回char +* 【crypto 】 SM2支持设置Digest和DSAEncoding(issue#829@Github) ### Bug修复 * 【json 】 修复解析JSON字符串时配置无法传递问题 diff --git a/hutool-crypto/src/main/java/cn/hutool/crypto/asymmetric/SM2.java b/hutool-crypto/src/main/java/cn/hutool/crypto/asymmetric/SM2.java index 643aec6a1..cf91415c4 100644 --- a/hutool-crypto/src/main/java/cn/hutool/crypto/asymmetric/SM2.java +++ b/hutool-crypto/src/main/java/cn/hutool/crypto/asymmetric/SM2.java @@ -6,13 +6,18 @@ import cn.hutool.crypto.BCUtil; import cn.hutool.crypto.CryptoException; import cn.hutool.crypto.SecureUtil; import org.bouncycastle.crypto.CipherParameters; +import org.bouncycastle.crypto.Digest; import org.bouncycastle.crypto.InvalidCipherTextException; +import org.bouncycastle.crypto.digests.SM3Digest; import org.bouncycastle.crypto.engines.SM2Engine; import org.bouncycastle.crypto.params.ECPrivateKeyParameters; import org.bouncycastle.crypto.params.ECPublicKeyParameters; import org.bouncycastle.crypto.params.ParametersWithID; import org.bouncycastle.crypto.params.ParametersWithRandom; +import org.bouncycastle.crypto.signers.DSAEncoding; +import org.bouncycastle.crypto.signers.PlainDSAEncoding; import org.bouncycastle.crypto.signers.SM2Signer; +import org.bouncycastle.crypto.signers.StandardDSAEncoding; import java.security.PrivateKey; import java.security.PublicKey; @@ -35,10 +40,13 @@ public class SM2 extends AbstractAsymmetricCrypto { protected SM2Engine engine; protected SM2Signer signer; - private SM2Engine.Mode mode = SM2Engine.Mode.C1C3C2; private ECPrivateKeyParameters privateKeyParams; private ECPublicKeyParameters publicKeyParams; + private DSAEncoding encoding = StandardDSAEncoding.INSTANCE; + private Digest digest = new SM3Digest(); + private SM2Engine.Mode mode = SM2Engine.Mode.C1C3C2; + // ------------------------------------------------------------------ Constructor start /** @@ -414,16 +422,51 @@ public class SM2 extends AbstractAsymmetricCrypto { } /** - * 设置加密类型 + * 设置DSA signatures的编码为PlainDSAEncoding + * + * @return this + * @since 5.3.1 + */ + public SM2 usePlainEncoding() { + return setEncoding(PlainDSAEncoding.INSTANCE); + } + + /** + * 设置DSA signatures的编码 + * + * @param encoding {@link DSAEncoding}实现 + * @return this + * @since 5.3.1 + */ + public SM2 setEncoding(DSAEncoding encoding) { + this.encoding = encoding; + this.signer = null; + return this; + } + + /** + * 设置Hash算法 + * + * @param digest {@link Digest}实现 + * @return this + * @since 5.3.1 + */ + public SM2 setDigest(Digest digest) { + this.digest = digest; + this.engine = null; + this.signer = null; + return this; + } + + /** + * 设置SM2模式,旧版是C1C2C3,新版本是C1C3C2 * * @param mode {@link SM2Engine.Mode} * @return this */ public SM2 setMode(SM2Engine.Mode mode) { this.mode = mode; - if (null != this.engine) { - this.engine = null; - } + this.engine = null; return this; } @@ -455,7 +498,7 @@ public class SM2 extends AbstractAsymmetricCrypto { */ private SM2Engine getEngine() { if (null == this.engine) { - this.engine = new SM2Engine(this.mode); + this.engine = new SM2Engine(this.digest, this.mode); } return this.engine; } @@ -467,10 +510,9 @@ public class SM2 extends AbstractAsymmetricCrypto { */ private SM2Signer getSigner() { if (null == this.signer) { - this.signer = new SM2Signer(); + this.signer = new SM2Signer(this.encoding, this.digest); } return this.signer; } - // ------------------------------------------------------------------------------------------------------------------------- Private method end } diff --git a/hutool-crypto/src/test/java/cn/hutool/crypto/test/SM2Test.java b/hutool-crypto/src/test/java/cn/hutool/crypto/test/SM2Test.java index bef62d52c..a5ed710d8 100644 --- a/hutool-crypto/src/test/java/cn/hutool/crypto/test/SM2Test.java +++ b/hutool-crypto/src/test/java/cn/hutool/crypto/test/SM2Test.java @@ -174,4 +174,23 @@ public class SM2Test { final String sign = sm2.signHex(data, id); Assert.assertTrue(sm2.verifyHex(data, sign)); } + + @Test + public void sm2PlainWithPointTest(){ + // 测试地址:https://i.goto327.top/CryptTools/SM2.aspx?tdsourcetag=s_pctim_aiomsg + + String d = "FAB8BBE670FAE338C9E9382B9FB6485225C11A3ECB84C938F10F20A93B6215F0"; + String x = "9EF573019D9A03B16B0BE44FC8A5B4E8E098F56034C97B312282DD0B4810AFC3"; + String y = "CC759673ED0FC9B9DC7E6FA38F0E2B121E02654BF37EA6B63FAF2A0D6013EADF"; + + String data = "434477813974bf58f94bcf760833c2b40f77a5fc360485b0b9ed1bd9682edb45"; + String id = "31323334353637383132333435363738"; + + final SM2 sm2 = new SM2(d, x, y); + // 生成的签名是64位 + sm2.usePlainEncoding(); + + String sign = "DCA0E80A7F46C93714B51C3EFC55A922BCEF7ECF0FE9E62B53BA6A7438B543A76C145A452CA9036F3CB70D7E6C67D4D9D7FE114E5367A2F6F5A4D39F2B10F3D6"; + Assert.assertTrue(sm2.verifyHex(data, sign)); + } }