diff --git a/hutool-crypto/src/main/java/org/dromara/hutool/crypto/Cipher.java b/hutool-crypto/src/main/java/org/dromara/hutool/crypto/Cipher.java
index 38565b93c..6c10896b6 100644
--- a/hutool-crypto/src/main/java/org/dromara/hutool/crypto/Cipher.java
+++ b/hutool-crypto/src/main/java/org/dromara/hutool/crypto/Cipher.java
@@ -21,8 +21,11 @@ import java.util.Arrays;
/**
* 密码接口,提供统一的API,用于兼容和统一JCE和BouncyCastle等库的操作
*
- * - process和doFinal组合使用,用于分块加密或解密
- * - processFinal默认处理并输出小于块的数据,或一次性数据
+ * - process和doFinal组合使用,用于分块加密或解密。
+ * 例如处理块的大小为8,实际需要加密的报文长度为23,那么需要分三块进行加密,前面2块长度为8的报文需要调用process进行部分加密,
+ * 部分加密的结果可以从process的返回值获取到,
+ * 最后的7长度(其实一般会填充到长度为块长度8)的报文则调用doFinal进行加密,结束整个部分加密的操作。
+ * - processFinal默认处理并输出小于块的数据,或一次性数据。
*
*
* @author Looly
diff --git a/hutool-crypto/src/main/java/org/dromara/hutool/crypto/asymmetric/paillier/PaillierCipher.java b/hutool-crypto/src/main/java/org/dromara/hutool/crypto/asymmetric/paillier/PaillierCipher.java
new file mode 100644
index 000000000..e4562fdc8
--- /dev/null
+++ b/hutool-crypto/src/main/java/org/dromara/hutool/crypto/asymmetric/paillier/PaillierCipher.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2024 Hutool Team.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.dromara.hutool.crypto.asymmetric.paillier;
+
+import org.dromara.hutool.core.lang.Assert;
+import org.dromara.hutool.crypto.Cipher;
+import org.dromara.hutool.crypto.CipherMode;
+import org.dromara.hutool.crypto.CryptoException;
+
+import java.security.InvalidKeyException;
+import java.security.Key;
+import java.security.SecureRandom;
+
+/**
+ * Paillier加密算法实现
+ *
+ * @author Looly
+ * @since 6.0.0
+ */
+public class PaillierCipher implements Cipher {
+
+ private final PaillierCipherSpiImpl impl;
+
+ /**
+ * 构造
+ */
+ public PaillierCipher() {
+ this.impl = new PaillierCipherSpiImpl();
+ }
+
+ @Override
+ public String getAlgorithmName() {
+ return PaillierKey.ALGORITHM_NAME;
+ }
+
+ @Override
+ public int getBlockSize() {
+ return impl.engineGetBlockSize();
+ }
+
+ @Override
+ public void init(final CipherMode mode, final Parameters parameters) {
+ Assert.isInstanceOf(PaillierParameters.class, parameters, "Only support JceParameters!");
+ final PaillierParameters paillierParameters = (PaillierParameters) parameters;
+ try {
+ impl.engineInit(mode.getValue(), paillierParameters.key, paillierParameters.random);
+ } catch (final InvalidKeyException e) {
+ throw new CryptoException(e);
+ }
+ }
+
+ @Override
+ public int getOutputSize(final int len) {
+ return impl.engineGetOutputSize(len);
+ }
+
+ @Override
+ public int process(final byte[] in, final int inOff, final int len, final byte[] out, final int outOff) {
+ return impl.engineUpdate(in, inOff, len, out, outOff);
+ }
+
+ @Override
+ public int doFinal(final byte[] out, final int outOff) {
+ return impl.engineDoFinal(null, 0, 0, out, outOff);
+ }
+
+ @Override
+ public byte[] processFinal(final byte[] in, final int inOffset, final int inputLen) {
+ return impl.engineDoFinal(in, inOffset, inputLen);
+ }
+
+ /**
+ * Paillier算法的key和random封装
+ */
+ public static class PaillierParameters implements Parameters {
+ private final Key key;
+ /**
+ * 随机数生成器,可自定义随机数种子
+ */
+ private final SecureRandom random;
+
+ /**
+ * 构造
+ *
+ * @param key 密钥
+ * @param random 自定义随机数生成器
+ */
+ public PaillierParameters(final Key key, final SecureRandom random) {
+ this.key = key;
+ this.random = random;
+ }
+ }
+}
diff --git a/hutool-crypto/src/main/java/org/dromara/hutool/crypto/asymmetric/paillier/PaillierCrypto.java b/hutool-crypto/src/main/java/org/dromara/hutool/crypto/asymmetric/paillier/PaillierCrypto.java
index 8137bfb47..3b67e5f0a 100755
--- a/hutool-crypto/src/main/java/org/dromara/hutool/crypto/asymmetric/paillier/PaillierCrypto.java
+++ b/hutool-crypto/src/main/java/org/dromara/hutool/crypto/asymmetric/paillier/PaillierCrypto.java
@@ -16,12 +16,15 @@
package org.dromara.hutool.crypto.asymmetric.paillier;
+import org.dromara.hutool.crypto.CipherMode;
import org.dromara.hutool.crypto.CryptoException;
import org.dromara.hutool.crypto.asymmetric.AbstractAsymmetricCrypto;
import org.dromara.hutool.crypto.asymmetric.KeyType;
import javax.crypto.Cipher;
-import java.security.*;
+import java.security.Key;
+import java.security.KeyPair;
+import java.security.SecureRandom;
/**
* 同态加密算法Paillier
@@ -45,7 +48,11 @@ import java.security.*;
public class PaillierCrypto extends AbstractAsymmetricCrypto {
private static final long serialVersionUID = 1L;
- private final PaillierCipherSpiImpl spi;
+ private final PaillierCipher cipher;
+ /**
+ * 自定义随机数
+ */
+ private SecureRandom random;
/**
* 构造,使用随机密钥对
@@ -64,7 +71,19 @@ public class PaillierCrypto extends AbstractAsymmetricCrypto {
*/
public PaillierCrypto(final KeyPair keyPair) {
super(PaillierKey.ALGORITHM_NAME, keyPair);
- this.spi = new PaillierCipherSpiImpl();
+ this.cipher = new PaillierCipher();
+ }
+
+ /**
+ * 设置随机数生成器,可自定义随机数种子
+ *
+ * @param random 随机数生成器,可自定义随机数种子
+ * @return this
+ * @since 5.7.17
+ */
+ public PaillierCrypto setRandom(final SecureRandom random) {
+ this.random = random;
+ return this;
}
@Override
@@ -72,7 +91,7 @@ public class PaillierCrypto extends AbstractAsymmetricCrypto {
final Key key = getKeyByType(keyType);
lock.lock();
try {
- initMode(Cipher.ENCRYPT_MODE, key);
+ initMode(CipherMode.ENCRYPT, key);
return doFinal(data, 0, data.length);
} catch (final Exception e) {
throw new CryptoException(e);
@@ -86,7 +105,7 @@ public class PaillierCrypto extends AbstractAsymmetricCrypto {
final Key key = getKeyByType(keyType);
lock.lock();
try {
- initMode(Cipher.DECRYPT_MODE, key);
+ initMode(CipherMode.DECRYPT, key);
return doFinal(bytes, 0, bytes.length);
} catch (final Exception e) {
throw new CryptoException(e);
@@ -105,10 +124,9 @@ public class PaillierCrypto extends AbstractAsymmetricCrypto {
* @param mode 模式,可选{@link Cipher#ENCRYPT_MODE}或{@link Cipher#DECRYPT_MODE}
* @param key 公钥或私钥
* @return this
- * @throws InvalidKeyException 密钥错误
*/
- public PaillierCrypto initMode(final int mode, final Key key) throws InvalidKeyException {
- this.spi.engineInit(mode, key, null);
+ public PaillierCrypto initMode(final CipherMode mode, final Key key) {
+ this.cipher.init(mode, new PaillierCipher.PaillierParameters(key, this.random));
return this;
}
@@ -121,6 +139,6 @@ public class PaillierCrypto extends AbstractAsymmetricCrypto {
* @return 执行后的数据
*/
public byte[] doFinal(final byte[] input, final int inputOffset, final int inputLen) {
- return this.spi.engineDoFinal(input, inputOffset, inputLen);
+ return this.cipher.processFinal(input, inputOffset, inputLen);
}
}