From b47125c9f1896d47c31093b23451be2a426d5da1 Mon Sep 17 00:00:00 2001 From: Looly Date: Thu, 23 Jul 2020 12:10:58 +0800 Subject: [PATCH] fix bug and add crypto --- CHANGELOG.md | 2 + .../java/cn/hutool/core/util/StrUtil.java | 2 +- .../main/java/cn/hutool/crypto/KeyUtil.java | 7 +- .../crypto/asymmetric/BaseAsymmetric.java | 4 +- .../cn/hutool/crypto/asymmetric/ECIES.java | 103 ++++++++++++++++++ .../java/cn/hutool/crypto/test/ECIESTest.java | 26 +++++ .../java/cn/hutool/crypto/test/RSATest.java | 1 - 7 files changed, 140 insertions(+), 5 deletions(-) create mode 100644 hutool-crypto/src/main/java/cn/hutool/crypto/asymmetric/ECIES.java create mode 100644 hutool-crypto/src/test/java/cn/hutool/crypto/test/ECIESTest.java diff --git a/CHANGELOG.md b/CHANGELOG.md index 7782461d0..005e2a569 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,10 +12,12 @@ * 【core 】 增加CRC16算法若干(pr#963@Github) * 【core 】 LocalDateTimeUtil增加format等方法(pr#140@Gitee) * 【http 】 UserAgentUtil增加Android原生浏览器识别(pr#975@Github) +* 【crypto 】 增加ECIES算法类(issue#979@Github) ### Bug修复 * 【core 】 修复ZipUtil中finish位于循环内的问题(issue#961@Github) * 【core 】 修复CollUtil.page未越界检查的问题(issue#I1O2LR@Gitee) +* 【core 】 修复StrUtil.removeAny的bug(issue#977@Github) ------------------------------------------------------------------------------------------------------------- ## 5.3.9 (2020-07-12) diff --git a/hutool-core/src/main/java/cn/hutool/core/util/StrUtil.java b/hutool-core/src/main/java/cn/hutool/core/util/StrUtil.java index 0feba5ea0..8e85bb7b3 100644 --- a/hutool-core/src/main/java/cn/hutool/core/util/StrUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/util/StrUtil.java @@ -978,7 +978,7 @@ public class StrUtil { String result = str(str); if (isNotEmpty(str)) { for (CharSequence strToRemove : strsToRemove) { - result = removeAll(str, strToRemove); + result = removeAll(result, strToRemove); } } return result; diff --git a/hutool-crypto/src/main/java/cn/hutool/crypto/KeyUtil.java b/hutool-crypto/src/main/java/cn/hutool/crypto/KeyUtil.java index 67e19b29b..2c9a834c1 100644 --- a/hutool-crypto/src/main/java/cn/hutool/crypto/KeyUtil.java +++ b/hutool-crypto/src/main/java/cn/hutool/crypto/KeyUtil.java @@ -342,7 +342,12 @@ public class KeyUtil { * @return {@link KeyPair} */ public static KeyPair generateKeyPair(String algorithm) { - return generateKeyPair(algorithm, DEFAULT_KEY_SIZE); + int keySize = DEFAULT_KEY_SIZE; + if("ECIES".equalsIgnoreCase(algorithm)){ + // ECIES算法对KEY的长度有要求,此处默认256 + keySize = 256; + } + return generateKeyPair(algorithm, keySize); } /** diff --git a/hutool-crypto/src/main/java/cn/hutool/crypto/asymmetric/BaseAsymmetric.java b/hutool-crypto/src/main/java/cn/hutool/crypto/asymmetric/BaseAsymmetric.java index bd8469257..266006656 100644 --- a/hutool-crypto/src/main/java/cn/hutool/crypto/asymmetric/BaseAsymmetric.java +++ b/hutool-crypto/src/main/java/cn/hutool/crypto/asymmetric/BaseAsymmetric.java @@ -3,7 +3,7 @@ package cn.hutool.crypto.asymmetric; import cn.hutool.core.codec.Base64; import cn.hutool.core.lang.Assert; import cn.hutool.crypto.CryptoException; -import cn.hutool.crypto.SecureUtil; +import cn.hutool.crypto.KeyUtil; import java.security.Key; import java.security.KeyPair; @@ -89,7 +89,7 @@ public class BaseAsymmetric> { */ @SuppressWarnings("unchecked") public T initKeys() { - KeyPair keyPair = SecureUtil.generateKeyPair(this.algorithm); + KeyPair keyPair = KeyUtil.generateKeyPair(this.algorithm); this.publicKey = keyPair.getPublic(); this.privateKey = keyPair.getPrivate(); return (T) this; diff --git a/hutool-crypto/src/main/java/cn/hutool/crypto/asymmetric/ECIES.java b/hutool-crypto/src/main/java/cn/hutool/crypto/asymmetric/ECIES.java new file mode 100644 index 000000000..e3e213000 --- /dev/null +++ b/hutool-crypto/src/main/java/cn/hutool/crypto/asymmetric/ECIES.java @@ -0,0 +1,103 @@ +package cn.hutool.crypto.asymmetric; + +import java.security.PrivateKey; +import java.security.PublicKey; + +/** + * ECIES(集成加密方案,elliptic curve integrate encrypt scheme) + * + *

+ * 详细介绍见:https://blog.csdn.net/baidu_26954729/article/details/90437344 + * 此算法必须引入Bouncy Castle库 + * + * @author loolly + * @since 5.3.10 + */ +public class ECIES extends AsymmetricCrypto{ + + /** 默认的ECIES算法 */ + private static final String ALGORITHM_ECIES = "ECIES"; + + // ------------------------------------------------------------------ Constructor start + /** + * 构造,生成新的私钥公钥对 + */ + public ECIES() { + super(ALGORITHM_ECIES); + } + + /** + * 构造,生成新的私钥公钥对 + * + * @param eciesAlgorithm 自定义ECIES算法,例如ECIESwithDESede/NONE/PKCS7Padding + */ + public ECIES(String eciesAlgorithm) { + super(eciesAlgorithm); + } + + /** + * 构造
+ * 私钥和公钥同时为空时生成一对新的私钥和公钥
+ * 私钥和公钥可以单独传入一个,如此则只能使用此钥匙来做加密或者解密 + * + * @param privateKeyStr 私钥Hex或Base64表示 + * @param publicKeyStr 公钥Hex或Base64表示 + */ + public ECIES(String privateKeyStr, String publicKeyStr) { + super(ALGORITHM_ECIES, privateKeyStr, publicKeyStr); + } + + /** + * 构造
+ * 私钥和公钥同时为空时生成一对新的私钥和公钥
+ * 私钥和公钥可以单独传入一个,如此则只能使用此钥匙来做加密或者解密 + * + * @param eciesAlgorithm 自定义ECIES算法,例如ECIESwithDESede/NONE/PKCS7Padding + * @param privateKeyStr 私钥Hex或Base64表示 + * @param publicKeyStr 公钥Hex或Base64表示 + * @since 4.5.8 + */ + public ECIES(String eciesAlgorithm, String privateKeyStr, String publicKeyStr) { + super(eciesAlgorithm, privateKeyStr, publicKeyStr); + } + + /** + * 构造
+ * 私钥和公钥同时为空时生成一对新的私钥和公钥
+ * 私钥和公钥可以单独传入一个,如此则只能使用此钥匙来做加密或者解密 + * + * @param privateKey 私钥 + * @param publicKey 公钥 + */ + public ECIES(byte[] privateKey, byte[] publicKey) { + super(ALGORITHM_ECIES, privateKey, publicKey); + } + + /** + * 构造
+ * 私钥和公钥同时为空时生成一对新的私钥和公钥
+ * 私钥和公钥可以单独传入一个,如此则只能使用此钥匙来做加密或者解密 + * + * @param privateKey 私钥 + * @param publicKey 公钥 + * @since 3.1.1 + */ + public ECIES(PrivateKey privateKey, PublicKey publicKey) { + super(ALGORITHM_ECIES, privateKey, publicKey); + } + + /** + * 构造
+ * 私钥和公钥同时为空时生成一对新的私钥和公钥
+ * 私钥和公钥可以单独传入一个,如此则只能使用此钥匙来做加密或者解密 + * + * @param eciesAlgorithm 自定义ECIES算法,例如ECIESwithDESede/NONE/PKCS7Padding + * @param privateKey 私钥 + * @param publicKey 公钥 + * @since 4.5.8 + */ + public ECIES(String eciesAlgorithm, PrivateKey privateKey, PublicKey publicKey) { + super(eciesAlgorithm, privateKey, publicKey); + } + // ------------------------------------------------------------------ Constructor end +} diff --git a/hutool-crypto/src/test/java/cn/hutool/crypto/test/ECIESTest.java b/hutool-crypto/src/test/java/cn/hutool/crypto/test/ECIESTest.java new file mode 100644 index 000000000..ca83c61ad --- /dev/null +++ b/hutool-crypto/src/test/java/cn/hutool/crypto/test/ECIESTest.java @@ -0,0 +1,26 @@ +package cn.hutool.crypto.test; + +import cn.hutool.core.util.StrUtil; +import cn.hutool.crypto.asymmetric.ECIES; +import cn.hutool.crypto.asymmetric.KeyType; +import org.junit.Assert; +import org.junit.Test; + +public class ECIESTest { + + @Test + public void eciesTest(){ + final ECIES ecies = new ECIES(); + + String textBase = "我是一段特别长的测试"; + StringBuilder text = new StringBuilder(); + for (int i = 0; i < 10; i++) { + text.append(textBase); + } + + // 公钥加密,私钥解密 + String encryptStr = ecies.encryptBase64(text.toString(), KeyType.PublicKey); + String decryptStr = StrUtil.utf8Str(ecies.decrypt(encryptStr, KeyType.PrivateKey)); + Assert.assertEquals(text.toString(), decryptStr); + } +} diff --git a/hutool-crypto/src/test/java/cn/hutool/crypto/test/RSATest.java b/hutool-crypto/src/test/java/cn/hutool/crypto/test/RSATest.java index a167b8d64..fcb9faa70 100644 --- a/hutool-crypto/src/test/java/cn/hutool/crypto/test/RSATest.java +++ b/hutool-crypto/src/test/java/cn/hutool/crypto/test/RSATest.java @@ -196,5 +196,4 @@ public class RSATest { final String encryptBase64 = rsa.encryptBase64("测试内容", KeyType.PublicKey); Assert.assertNotNull(encryptBase64); } - }