浏览代码

sm2 support encoding

Looly 5 年之前
父节点
当前提交
2f9fa2c29a

+ 1 - 0
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字符串时配置无法传递问题

+ 50 - 8
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<SM2> {
 	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<SM2> {
 	}
 
 	/**
-	 * 设置加密类型
+	 * 设置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<SM2> {
 	 */
 	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<SM2> {
 	 */
 	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
 }

+ 19 - 0
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));
+	}
 }