This commit is contained in:
Looly 2024-08-15 13:05:50 +08:00
parent 3bb4cb3012
commit 19a5876078
3 changed files with 139 additions and 11 deletions

View File

@ -21,8 +21,11 @@ import java.util.Arrays;
/**
* 密码接口提供统一的API用于兼容和统一JCE和BouncyCastle等库的操作<br>
* <ul>
* <li>process和doFinal组合使用用于分块加密或解密</li>
* <li>processFinal默认处理并输出小于块的数据或一次性数据</li>
* <li>process和doFinal组合使用用于分块加密或解密
* 例如处理块的大小为8实际需要加密的报文长度为23那么需要分三块进行加密前面2块长度为8的报文需要调用process进行部分加密
* 部分加密的结果可以从process的返回值获取到
* 最后的7长度(其实一般会填充到长度为块长度8)的报文则调用doFinal进行加密结束整个部分加密的操作</li>
* <li>processFinal默认处理并输出小于块的数据或一次性数据</li>
* </ul>
*
* @author Looly

View File

@ -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;
}
}
}

View File

@ -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<br>
@ -45,7 +48,11 @@ import java.security.*;
public class PaillierCrypto extends AbstractAsymmetricCrypto<PaillierCrypto> {
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<PaillierCrypto> {
*/
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<PaillierCrypto> {
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<PaillierCrypto> {
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<PaillierCrypto> {
* @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<PaillierCrypto> {
* @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);
}
}