/**
* 构造
- *
+ *
* 私钥和公钥同时为空时生成一对新的私钥和公钥
* 私钥和公钥可以单独传入一个,如此则只能使用此钥匙来做加密或者解密
- *
- * @param algorithm 算法
+ *
+ * @param algorithm 算法
* @param privateKey 私钥
- * @param publicKey 公钥
+ * @param publicKey 公钥
*/
public AsymmetricCrypto(String algorithm, byte[] privateKey, byte[] publicKey) {
this(algorithm, //
- SecureUtil.generatePrivateKey(algorithm, privateKey), //
- SecureUtil.generatePublicKey(algorithm, publicKey)//
+ KeyUtil.generatePrivateKey(algorithm, privateKey), //
+ KeyUtil.generatePublicKey(algorithm, publicKey)//
);
}
/**
* 构造
- *
+ *
* 私钥和公钥同时为空时生成一对新的私钥和公钥
* 私钥和公钥可以单独传入一个,如此则只能使用此钥匙来做加密或者解密
- *
- * @param algorithm 算法
+ *
+ * @param algorithm 算法
* @param privateKey 私钥
- * @param publicKey 公钥
+ * @param publicKey 公钥
* @since 3.1.1
*/
public AsymmetricCrypto(String algorithm, PrivateKey privateKey, PublicKey publicKey) {
@@ -143,7 +158,7 @@ public class AsymmetricCrypto extends AbstractAsymmetricCrypto
/**
* 获取加密块大小
- *
+ *
* @return 加密块大小
*/
public int getEncryptBlockSize() {
@@ -152,7 +167,7 @@ public class AsymmetricCrypto extends AbstractAsymmetricCrypto
/**
* 设置加密块大小
- *
+ *
* @param encryptBlockSize 加密块大小
*/
public void setEncryptBlockSize(int encryptBlockSize) {
@@ -161,7 +176,7 @@ public class AsymmetricCrypto extends AbstractAsymmetricCrypto
/**
* 获取解密块大小
- *
+ *
* @return 解密块大小
*/
public int getDecryptBlockSize() {
@@ -170,13 +185,35 @@ public class AsymmetricCrypto extends AbstractAsymmetricCrypto
/**
* 设置解密块大小
- *
+ *
* @param decryptBlockSize 解密块大小
*/
public void setDecryptBlockSize(int decryptBlockSize) {
this.decryptBlockSize = decryptBlockSize;
}
+ /**
+ * 获取{@link AlgorithmParameterSpec}
+ * 在某些算法中,需要特别的参数,例如在ECIES中,此处为IESParameterSpec
+ *
+ * @return {@link AlgorithmParameterSpec}
+ * @since 5.4.3
+ */
+ public AlgorithmParameterSpec getAlgorithmParameterSpec() {
+ return algorithmParameterSpec;
+ }
+
+ /**
+ * 设置{@link AlgorithmParameterSpec}
+ * 在某些算法中,需要特别的参数,例如在ECIES中,此处为IESParameterSpec
+ *
+ * @param algorithmParameterSpec {@link AlgorithmParameterSpec}
+ * @since 5.4.3
+ */
+ public void setAlgorithmParameterSpec(AlgorithmParameterSpec algorithmParameterSpec) {
+ this.algorithmParameterSpec = algorithmParameterSpec;
+ }
+
@Override
public AsymmetricCrypto init(String algorithm, PrivateKey privateKey, PublicKey publicKey) {
super.init(algorithm, privateKey, publicKey);
@@ -185,10 +222,11 @@ public class AsymmetricCrypto extends AbstractAsymmetricCrypto
}
// --------------------------------------------------------------------------------- Encrypt
+
/**
* 加密
- *
- * @param data 被加密的bytes
+ *
+ * @param data 被加密的bytes
* @param keyType 私钥或公钥 {@link KeyType}
* @return 加密后的bytes
*/
@@ -197,12 +235,12 @@ public class AsymmetricCrypto extends AbstractAsymmetricCrypto
final Key key = getKeyByType(keyType);
lock.lock();
try {
- cipher.init(Cipher.ENCRYPT_MODE, key);
+ initCipher(Cipher.ENCRYPT_MODE, key);
- if(this.encryptBlockSize < 0){
+ if (this.encryptBlockSize < 0) {
// 在引入BC库情况下,自动获取块大小
final int blockSize = this.cipher.getBlockSize();
- if(blockSize > 0){
+ if (blockSize > 0) {
this.encryptBlockSize = blockSize;
}
}
@@ -216,10 +254,11 @@ public class AsymmetricCrypto extends AbstractAsymmetricCrypto
}
// --------------------------------------------------------------------------------- Decrypt
+
/**
* 解密
- *
- * @param data 被解密的bytes
+ *
+ * @param data 被解密的bytes
* @param keyType 私钥或公钥 {@link KeyType}
* @return 解密后的bytes
*/
@@ -228,12 +267,12 @@ public class AsymmetricCrypto extends AbstractAsymmetricCrypto
final Key key = getKeyByType(keyType);
lock.lock();
try {
- cipher.init(Cipher.DECRYPT_MODE, key);
+ initCipher(Cipher.DECRYPT_MODE, key);
- if(this.decryptBlockSize < 0){
+ if (this.decryptBlockSize < 0) {
// 在引入BC库情况下,自动获取块大小
final int blockSize = this.cipher.getBlockSize();
- if(blockSize > 0){
+ if (blockSize > 0) {
this.decryptBlockSize = blockSize;
}
}
@@ -250,16 +289,28 @@ public class AsymmetricCrypto extends AbstractAsymmetricCrypto
/**
* 获得加密或解密器
- *
+ *
* @return 加密或解密
+ * @deprecated 拼写错误,请使用{@link #getCipher()}
*/
+ @Deprecated
public Cipher getClipher() {
return cipher;
}
+ /**
+ * 获得加密或解密器
+ *
+ * @return 加密或解密
+ * @since 5.4.3
+ */
+ public Cipher getCipher() {
+ return cipher;
+ }
+
/**
* 初始化{@link Cipher},默认尝试加载BC库
- *
+ *
* @since 4.5.2
*/
protected void initCipher() {
@@ -268,13 +319,13 @@ public class AsymmetricCrypto extends AbstractAsymmetricCrypto
/**
* 加密或解密
- *
- * @param data 被加密或解密的内容数据
+ *
+ * @param data 被加密或解密的内容数据
* @param maxBlockSize 最大块(分段)大小
* @return 加密或解密后的数据
* @throws IllegalBlockSizeException 分段异常
- * @throws BadPaddingException padding错误异常
- * @throws IOException IO异常,不会被触发
+ * @throws BadPaddingException padding错误异常
+ * @throws IOException IO异常,不会被触发
*/
private byte[] doFinal(byte[] data, int maxBlockSize) throws IllegalBlockSizeException, BadPaddingException, IOException {
// 模长
@@ -291,19 +342,18 @@ public class AsymmetricCrypto extends AbstractAsymmetricCrypto
/**
* 分段加密或解密
- *
- * @param data 数据
+ *
+ * @param data 数据
* @param maxBlockSize 最大分段的段大小,不能为小于1
* @return 加密或解密后的数据
* @throws IllegalBlockSizeException 分段异常
- * @throws BadPaddingException padding错误异常
- * @throws IOException IO异常,不会被触发
+ * @throws BadPaddingException padding错误异常
+ * @throws IOException IO异常,不会被触发
*/
private byte[] doFinalWithBlock(byte[] data, int maxBlockSize) throws IllegalBlockSizeException, BadPaddingException, IOException {
final int dataLength = data.length;
- @SuppressWarnings("resource")
- final FastByteArrayOutputStream out = new FastByteArrayOutputStream();
-
+ @SuppressWarnings("resource") final FastByteArrayOutputStream out = new FastByteArrayOutputStream();
+
int offSet = 0;
// 剩余长度
int remainLength = dataLength;
@@ -316,7 +366,23 @@ public class AsymmetricCrypto extends AbstractAsymmetricCrypto
offSet += blockSize;
remainLength = dataLength - offSet;
}
-
+
return out.toByteArray();
}
+
+ /**
+ * 初始化{@link Cipher}
+ *
+ * @param mode 模式,可选{@link Cipher#ENCRYPT_MODE}或者{@link Cipher#DECRYPT_MODE}
+ * @param key 密钥
+ * @throws InvalidAlgorithmParameterException 异常算法错误
+ * @throws InvalidKeyException 异常KEY错误
+ */
+ private void initCipher(int mode, Key key) throws InvalidAlgorithmParameterException, InvalidKeyException {
+ if (null != this.algorithmParameterSpec) {
+ cipher.init(mode, key, this.algorithmParameterSpec);
+ } else {
+ cipher.init(mode, key);
+ }
+ }
}
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 266006656..ae46f935a 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
@@ -196,6 +196,6 @@ public class BaseAsymmetric> {
}
return this.publicKey;
}
- throw new CryptoException("Uknown key type: " + type);
+ throw new CryptoException("Unsupported key type: " + type);
}
}
diff --git a/hutool-crypto/src/main/java/cn/hutool/crypto/asymmetric/KeyType.java b/hutool-crypto/src/main/java/cn/hutool/crypto/asymmetric/KeyType.java
index 56038502a..62383231a 100644
--- a/hutool-crypto/src/main/java/cn/hutool/crypto/asymmetric/KeyType.java
+++ b/hutool-crypto/src/main/java/cn/hutool/crypto/asymmetric/KeyType.java
@@ -1,5 +1,7 @@
package cn.hutool.crypto.asymmetric;
+import javax.crypto.Cipher;
+
/**
* 密钥类型
*
@@ -7,5 +9,37 @@ package cn.hutool.crypto.asymmetric;
*
*/
public enum KeyType {
- PrivateKey, PublicKey
+ /**
+ * 公钥
+ */
+ PublicKey(Cipher.PUBLIC_KEY),
+ /**
+ * 私钥
+ */
+ PrivateKey(Cipher.PRIVATE_KEY),
+ /**
+ * 密钥
+ */
+ SecretKey(Cipher.SECRET_KEY);
+
+
+ /**
+ * 构造
+ *
+ * @param value 见{@link Cipher}
+ */
+ KeyType(int value) {
+ this.value = value;
+ }
+
+ private final int value;
+
+ /**
+ * 获取枚举值对应的int表示
+ *
+ * @return 枚举值对应的int表示
+ */
+ public int getValue() {
+ return this.value;
+ }
}
\ No newline at end of file
diff --git a/hutool-crypto/src/test/java/cn/hutool/crypto/test/KeyUtilTest.java b/hutool-crypto/src/test/java/cn/hutool/crypto/test/KeyUtilTest.java
index b038fd67d..0489bc9ba 100644
--- a/hutool-crypto/src/test/java/cn/hutool/crypto/test/KeyUtilTest.java
+++ b/hutool-crypto/src/test/java/cn/hutool/crypto/test/KeyUtilTest.java
@@ -31,4 +31,19 @@ public class KeyUtilTest {
final PublicKey rsaPublicKey = KeyUtil.getRSAPublicKey(aPrivate);
Assert.assertEquals(rsaPublicKey, keyPair.getPublic());
}
+
+ /**
+ * 测试EC和ECIES算法生成的KEY是一致的
+ */
+ @Test
+ public void generateECIESKeyTest(){
+ final KeyPair ecies = KeyUtil.generateKeyPair("ECIES");
+ Assert.assertNotNull(ecies.getPrivate());
+ Assert.assertNotNull(ecies.getPublic());
+
+ byte[] privateKeyBytes = ecies.getPrivate().getEncoded();
+
+ final PrivateKey privateKey = KeyUtil.generatePrivateKey("EC", privateKeyBytes);
+ Assert.assertEquals(ecies.getPrivate(), privateKey);
+ }
}
diff --git a/hutool-crypto/src/test/java/cn/hutool/crypto/test/asymmetric/ECIESTest.java b/hutool-crypto/src/test/java/cn/hutool/crypto/test/asymmetric/ECIESTest.java
index 1b83fe4f0..e00e6b65f 100644
--- a/hutool-crypto/src/test/java/cn/hutool/crypto/test/asymmetric/ECIESTest.java
+++ b/hutool-crypto/src/test/java/cn/hutool/crypto/test/asymmetric/ECIESTest.java
@@ -1,6 +1,7 @@
package cn.hutool.crypto.test.asymmetric;
import cn.hutool.core.util.StrUtil;
+import cn.hutool.crypto.asymmetric.AsymmetricCrypto;
import cn.hutool.crypto.asymmetric.ECIES;
import cn.hutool.crypto.asymmetric.KeyType;
import org.junit.Assert;
@@ -12,6 +13,25 @@ public class ECIESTest {
public void eciesTest(){
final ECIES ecies = new ECIES();
+ doTest(ecies, ecies);
+ }
+
+ @Test
+ public void eciesTest2(){
+ final ECIES ecies = new ECIES();
+ final byte[] privateKeyBytes = ecies.getPrivateKey().getEncoded();
+ final ECIES ecies2 = new ECIES(privateKeyBytes, null);
+
+ doTest(ecies, ecies2);
+ }
+
+ /**
+ * 测试用例
+ *
+ * @param cryptoForEncrypt 加密的Crypto
+ * @param cryptoForDecrypt 解密的Crypto
+ */
+ private void doTest(AsymmetricCrypto cryptoForEncrypt, AsymmetricCrypto cryptoForDecrypt){
String textBase = "我是一段特别长的测试";
StringBuilder text = new StringBuilder();
for (int i = 0; i < 10; i++) {
@@ -19,8 +39,9 @@ public class ECIESTest {
}
// 公钥加密,私钥解密
- String encryptStr = ecies.encryptBase64(text.toString(), KeyType.PublicKey);
- String decryptStr = StrUtil.utf8Str(ecies.decrypt(encryptStr, KeyType.PrivateKey));
+ String encryptStr = cryptoForEncrypt.encryptBase64(text.toString(), KeyType.PublicKey);
+
+ String decryptStr = StrUtil.utf8Str(cryptoForDecrypt.decrypt(encryptStr, KeyType.PrivateKey));
Assert.assertEquals(text.toString(), decryptStr);
}
}