From 22590b51e0efc33b9bd6f181ea997e3f0a335fc2 Mon Sep 17 00:00:00 2001 From: Looly Date: Wed, 30 Oct 2024 11:56:29 +0800 Subject: [PATCH] =?UTF-8?q?SM2.signHex=E6=94=B9=E5=90=8D=E4=B8=BAsignHexFr?= =?UTF-8?q?omHex=EF=BC=8C=E5=8E=9F=E5=90=8D=E6=A0=87=E8=AE=B0=E5=BA=9F?= =?UTF-8?q?=E5=BC=83=EF=BC=8C=E9=81=BF=E5=85=8D=E6=AD=A7=E4=B9=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dromara/hutool/core/codec/binary/Hex.java | 20 +- .../dromara/hutool/crypto/asymmetric/SM2.java | 28 +-- .../hutool/crypto/asymmetric/Sign.java | 175 +++++++----------- .../dromara/hutool/crypto/SignUtilTest.java | 3 +- .../hutool/crypto/asymmetric/SM2Test.java | 6 +- 5 files changed, 88 insertions(+), 144 deletions(-) diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/codec/binary/Hex.java b/hutool-core/src/main/java/org/dromara/hutool/core/codec/binary/Hex.java index 77ec59b7d..db1a0815f 100644 --- a/hutool-core/src/main/java/org/dromara/hutool/core/codec/binary/Hex.java +++ b/hutool-core/src/main/java/org/dromara/hutool/core/codec/binary/Hex.java @@ -87,7 +87,7 @@ public class Hex { * @param data 被编码的字符串 * @return 十六进制String */ - public static String encodeStr(final String data) { + public static String encodeStr(final CharSequence data) { return encodeStr(data, CharsetUtil.UTF_8); } @@ -98,7 +98,7 @@ public class Hex { * @param charset 编码 * @return 十六进制String */ - public static String encodeStr(final String data, final Charset charset) { + public static String encodeStr(final CharSequence data, final Charset charset) { return encodeStr(ByteUtil.toBytes(data, charset), true); } @@ -122,7 +122,7 @@ public class Hex { * @param hexStr 十六进制String * @return 字符串 */ - public static String decodeStr(final String hexStr) { + public static String decodeStr(final CharSequence hexStr) { return decodeStr(hexStr, CharsetUtil.UTF_8); } @@ -133,9 +133,9 @@ public class Hex { * @param charset 编码 * @return 字符串 */ - public static String decodeStr(final String hexStr, final Charset charset) { + public static String decodeStr(final CharSequence hexStr, final Charset charset) { if (StrUtil.isEmpty(hexStr)) { - return hexStr; + return StrUtil.toStringOrNull(hexStr); } return StrUtil.str(decode(hexStr), charset); } @@ -151,16 +151,6 @@ public class Hex { return StrUtil.str(decode(hexData), charset); } - /** - * 将十六进制字符串解码为byte[] - * - * @param hexStr 十六进制String - * @return byte[] - */ - public static byte[] decode(final String hexStr) { - return decode((CharSequence) hexStr); - } - /** * 将十六进制字符数组转换为字节数组 * diff --git a/hutool-crypto/src/main/java/org/dromara/hutool/crypto/asymmetric/SM2.java b/hutool-crypto/src/main/java/org/dromara/hutool/crypto/asymmetric/SM2.java index c6322206b..5a39ce422 100644 --- a/hutool-crypto/src/main/java/org/dromara/hutool/crypto/asymmetric/SM2.java +++ b/hutool-crypto/src/main/java/org/dromara/hutool/crypto/asymmetric/SM2.java @@ -475,11 +475,22 @@ public class SM2 extends AbstractAsymmetricCrypto { /** * 用私钥对信息生成数字签名 * - * @param dataHex 被签名的数据数据 + * @param data 被签名的数据数据 * @return 签名 */ - public String signHex(final String dataHex) { - return signHex(dataHex, null); + public String signHex(final byte[] data) { + return signHex(data, null); + } + + /** + * 用私钥对信息生成数字签名 + * + * @param data 被签名的数据数据 + * @param id 可以为null,若为null,则默认withId为字节数组:"1234567812345678".getBytes() + * @return 签名 + */ + public String signHex(final byte[] data, final byte[] id) { + return HexUtil.encodeStr(sign(data, id)); } /** @@ -493,17 +504,6 @@ public class SM2 extends AbstractAsymmetricCrypto { return sign(data, null); } - /** - * 用私钥对信息生成数字签名 - * - * @param dataHex 被签名的数据数据 - * @param idHex 可以为null,若为null,则默认withId为字节数组:"1234567812345678".getBytes() - * @return 签名 - */ - public String signHex(final String dataHex, final String idHex) { - return HexUtil.encodeStr(sign(HexUtil.decode(dataHex), HexUtil.decode(idHex))); - } - /** * 用私钥对信息生成数字签名,签名格式为ASN1
* 在硬件签名中,返回结果为R+S,可以通过调用{@link SmUtil#rsAsn1ToPlain(byte[])}方法转换之。 diff --git a/hutool-crypto/src/main/java/org/dromara/hutool/crypto/asymmetric/Sign.java b/hutool-crypto/src/main/java/org/dromara/hutool/crypto/asymmetric/Sign.java index 91b1f5d6f..437e9331d 100644 --- a/hutool-crypto/src/main/java/org/dromara/hutool/crypto/asymmetric/Sign.java +++ b/hutool-crypto/src/main/java/org/dromara/hutool/crypto/asymmetric/Sign.java @@ -16,12 +16,10 @@ package org.dromara.hutool.crypto.asymmetric; -import org.dromara.hutool.core.codec.binary.HexUtil; import org.dromara.hutool.core.codec.binary.Base64; +import org.dromara.hutool.core.codec.binary.HexUtil; import org.dromara.hutool.core.collection.CollUtil; import org.dromara.hutool.core.io.IoUtil; -import org.dromara.hutool.core.util.ByteUtil; -import org.dromara.hutool.core.util.CharsetUtil; import org.dromara.hutool.crypto.CryptoException; import org.dromara.hutool.crypto.KeyUtil; import org.dromara.hutool.crypto.SecureUtil; @@ -29,8 +27,9 @@ import org.dromara.hutool.crypto.SignUtil; import java.io.ByteArrayInputStream; import java.io.InputStream; -import java.nio.charset.Charset; -import java.security.*; +import java.security.InvalidAlgorithmParameterException; +import java.security.KeyPair; +import java.security.Signature; import java.security.cert.Certificate; import java.security.cert.X509Certificate; import java.security.spec.AlgorithmParameterSpec; @@ -179,64 +178,57 @@ public class Sign extends BaseAsymmetric { return this; } - // --------------------------------------------------------------------------------- Sign and Verify - /** - * 生成文件签名 + * 获得签名对象 * - * @param data 被签名数据 - * @param charset 编码 - * @return 签名 - * @since 5.7.0 + * @return {@link Signature} */ - public byte[] sign(final String data, final Charset charset) { - return sign(ByteUtil.toBytes(data, charset)); + public Signature getSignature() { + return signature; } /** - * 生成文件签名 + * 设置签名 * - * @param data 被签名数据 - * @return 签名 - * @since 5.7.0 + * @param signature 签名对象 {@link Signature} + * @return 自身 {@link AsymmetricCrypto} */ - public byte[] sign(final String data) { - return sign(data, CharsetUtil.UTF_8); + public Sign setSignature(final Signature signature) { + this.signature = signature; + return this; } /** - * 生成文件签名,并转为16进制字符串 + * 设置{@link Certificate} 为PublicKey
+ * 如果Certificate是X509Certificate,我们需要检查是否有密钥扩展 * - * @param data 被签名数据 - * @param charset 编码 - * @return 签名 - * @since 5.7.0 + * @param certificate {@link Certificate} + * @return this */ - public String signHex(final String data, final Charset charset) { - return HexUtil.encodeStr(sign(data, charset)); - } - - /** - * 生成文件签名 - * - * @param data 被签名数据 - * @return 签名 - * @since 5.7.0 - */ - public String signHex(final String data) { - return signHex(data, CharsetUtil.UTF_8); - } - - /** - * 用私钥对信息生成数字签名 - * - * @param data 加密数据 - * @return 签名 - */ - public byte[] sign(final byte[] data) { - return sign(new ByteArrayInputStream(data), -1); + public Sign setCertificate(final Certificate certificate) { + // If the certificate is of type X509Certificate, + // we should check whether it has a Key Usage + // extension marked as critical. + if (certificate instanceof X509Certificate) { + // Check whether the cert has a key usage extension + // marked as a critical extension. + // The OID for KeyUsage extension is 2.5.29.15. + final X509Certificate cert = (X509Certificate) certificate; + final Set critSet = cert.getCriticalExtensionOIDs(); + + if (CollUtil.isNotEmpty(critSet) && critSet.contains("2.5.29.15")) { + final boolean[] keyUsageInfo = cert.getKeyUsage(); + // keyUsageInfo[0] is for digitalSignature. + if ((keyUsageInfo != null) && (keyUsageInfo[0] == false)) { + throw new CryptoException("Wrong key usage"); + } + } + } + this.publicKey = certificate.getPublicKey(); + return this; } + // region ----- Sign and Verify /** * 生成签名,并转为16进制字符串
* @@ -257,18 +249,7 @@ public class Sign extends BaseAsymmetric { * @since 5.7.0 */ public String signHex(final InputStream data) { - return HexUtil.encodeStr(sign(data)); - } - - /** - * 生成签名,使用默认缓存大小,见 {@link IoUtil#DEFAULT_BUFFER_SIZE} - * - * @param data {@link InputStream} 数据流 - * @return 签名bytes - * @since 5.7.0 - */ - public byte[] sign(final InputStream data) { - return sign(data, IoUtil.DEFAULT_BUFFER_SIZE); + return signHex(data, -1); } /** @@ -280,10 +261,31 @@ public class Sign extends BaseAsymmetric { * @return 签名 * @since 5.7.0 */ - public String digestHex(final InputStream data, final int bufferLength) { + public String signHex(final InputStream data, final int bufferLength) { return HexUtil.encodeStr(sign(data, bufferLength)); } + /** + * 用私钥对信息生成数字签名 + * + * @param data 加密数据 + * @return 签名 + */ + public byte[] sign(final byte[] data) { + return sign(new ByteArrayInputStream(data), -1); + } + + /** + * 生成签名,使用默认缓存大小,见 {@link IoUtil#DEFAULT_BUFFER_SIZE} + * + * @param data {@link InputStream} 数据流 + * @return 签名bytes + * @since 5.7.0 + */ + public byte[] sign(final InputStream data) { + return sign(data, -1); + } + /** * 生成签名 * @@ -339,54 +341,5 @@ public class Sign extends BaseAsymmetric { lock.unlock(); } } - - /** - * 获得签名对象 - * - * @return {@link Signature} - */ - public Signature getSignature() { - return signature; - } - - /** - * 设置签名 - * - * @param signature 签名对象 {@link Signature} - * @return 自身 {@link AsymmetricCrypto} - */ - public Sign setSignature(final Signature signature) { - this.signature = signature; - return this; - } - - /** - * 设置{@link Certificate} 为PublicKey
- * 如果Certificate是X509Certificate,我们需要检查是否有密钥扩展 - * - * @param certificate {@link Certificate} - * @return this - */ - public Sign setCertificate(final Certificate certificate) { - // If the certificate is of type X509Certificate, - // we should check whether it has a Key Usage - // extension marked as critical. - if (certificate instanceof X509Certificate) { - // Check whether the cert has a key usage extension - // marked as a critical extension. - // The OID for KeyUsage extension is 2.5.29.15. - final X509Certificate cert = (X509Certificate) certificate; - final Set critSet = cert.getCriticalExtensionOIDs(); - - if (CollUtil.isNotEmpty(critSet) && critSet.contains("2.5.29.15")) { - final boolean[] keyUsageInfo = cert.getKeyUsage(); - // keyUsageInfo[0] is for digitalSignature. - if ((keyUsageInfo != null) && (keyUsageInfo[0] == false)) { - throw new CryptoException("Wrong key usage"); - } - } - } - this.publicKey = certificate.getPublicKey(); - return this; - } + // endregion } diff --git a/hutool-crypto/src/test/java/org/dromara/hutool/crypto/SignUtilTest.java b/hutool-crypto/src/test/java/org/dromara/hutool/crypto/SignUtilTest.java index 27f20cca0..a37a645ae 100644 --- a/hutool-crypto/src/test/java/org/dromara/hutool/crypto/SignUtilTest.java +++ b/hutool-crypto/src/test/java/org/dromara/hutool/crypto/SignUtilTest.java @@ -25,6 +25,7 @@ import org.dromara.hutool.crypto.bc.PemUtil; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; +import java.nio.charset.StandardCharsets; import java.security.KeyPair; import java.security.PublicKey; @@ -39,7 +40,7 @@ public class SignUtilTest { final PublicKey publicKey = KeyUtil.generatePublicKey(SignAlgorithm.SHA256withRSA.getValue(), Base64.decode(base64)); Assertions.assertEquals(sign.getPublicKey(), publicKey); - final String signHex = sign.signHex("abcd"); + final String signHex = sign.signHex("abcd".getBytes(StandardCharsets.UTF_8)); Assert.notNull(signHex); } diff --git a/hutool-crypto/src/test/java/org/dromara/hutool/crypto/asymmetric/SM2Test.java b/hutool-crypto/src/test/java/org/dromara/hutool/crypto/asymmetric/SM2Test.java index 0d86267e4..ba8bd1b57 100644 --- a/hutool-crypto/src/test/java/org/dromara/hutool/crypto/asymmetric/SM2Test.java +++ b/hutool-crypto/src/test/java/org/dromara/hutool/crypto/asymmetric/SM2Test.java @@ -169,7 +169,7 @@ public class SM2Test { final SM2 sm2 = SmUtil.sm2(); - final String sign = sm2.signHex(HexUtil.encodeStr(content)); + final String sign = sm2.signHex(content.getBytes(StandardCharsets.UTF_8)); final boolean verify = sm2.verifyHex(HexUtil.encodeStr(content), sign); Assertions.assertTrue(verify); } @@ -226,7 +226,7 @@ public class SM2Test { final String id = "31323334353637383132333435363738"; final SM2 sm2 = new SM2(d, x, y); - final String sign = sm2.signHex(data, id); + final String sign = sm2.signHex(HexUtil.decode(data), HexUtil.decode(id)); Assertions.assertTrue(sm2.verifyHex(data, sign)); } @@ -249,7 +249,7 @@ public class SM2Test { final String sign = "DCA0E80A7F46C93714B51C3EFC55A922BCEF7ECF0FE9E62B53BA6A7438B543A76C145A452CA9036F3CB70D7E6C67D4D9D7FE114E5367A2F6F5A4D39F2B10F3D6"; Assertions.assertTrue(sm2.verifyHex(data, sign)); - final String sign2 = sm2.signHex(data, id); + final String sign2 = sm2.signHex(HexUtil.decode(data), HexUtil.decode(id)); Assertions.assertTrue(sm2.verifyHex(data, sign2)); }