加密过长的会报错:
org.bouncycastle.crypto.DataLengthException: input too large for RSA cipher.
Data must not be longer than 245 bytes
原因是应为不同长度的密钥对应可以加密不同最大长度的原文,2048就对应245
解决办法是:
1.分段
2.RSA加密是有长度限制的.单纯用RSA加密较长数据时得使用分段加密,效率低下.用RSA+AES是比较主流的做法:AES加密数据产生密文,RSA加密AES密钥产生加密后的AES密钥,然后将密文和加密后的AES密钥一起传输:https://blog.csdn.net/huang007guo/article/details/104639490
maven pom依赖:
<!-- https://mvnrepository.com/artifact/org.bouncycastle/bcprov-jdk15on -->
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>1.64</version>
</dependency>
加解密代码:
package com.wjj.application.paysdk.crypt.impl;
import com.wjj.application.paysdk.crypt.PayCrypt;
import com.wjj.application.paysdk.crypt.entity.SecretKey;
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
import org.bouncycastle.crypto.generators.*;
import org.bouncycastle.crypto.params.*;
import org.bouncycastle.crypto.*;
import org.bouncycastle.crypto.util.PrivateKeyFactory;
import org.bouncycastle.crypto.util.PrivateKeyInfoFactory;
import org.bouncycastle.crypto.util.PublicKeyFactory;
import org.bouncycastle.crypto.util.SubjectPublicKeyInfoFactory;
import org.bouncycastle.crypto.engines.*;
import org.bouncycastle.asn1.pkcs.*;
import org.bouncycastle.asn1.*;
import java.io.IOException;
import java.math.BigInteger;
import java.security.SecureRandom;
import java.util.*;
/**
* RSA 加密工具
* 参考: https://blog.csdn.net/a571574085/article/details/81335095
* @author hank
* @since 2020/2/28 0028 下午 15:42
*/
public class RsaPayCryptImpl{
String charset = "utf-8";
private final Base64.Decoder decoder64 = Base64.getDecoder();
private final Base64.Encoder encoder64 = Base64.getEncoder();
public SecretKey generateSecretKey() throws IOException {
//生成密钥对
RSAKeyPairGenerator rsaKeyPairGenerator = new RSAKeyPairGenerator();
RSAKeyGenerationParameters rsaKeyGenerationParameters = new RSAKeyGenerationParameters(BigInteger.valueOf(3), new SecureRandom(), 1024, 25);
//初始化参数
rsaKeyPairGenerator.init(rsaKeyGenerationParameters);
AsymmetricCipherKeyPair keyPair = rsaKeyPairGenerator.generateKeyPair();
//公钥
AsymmetricKeyParameter publicKey = keyPair.getPublic();
//私钥
AsymmetricKeyParameter privateKey = keyPair.getPrivate();
SubjectPublicKeyInfo subjectPublicKeyInfo = SubjectPublicKeyInfoFactory.createSubjectPublicKeyInfo(publicKey);
PrivateKeyInfo privateKeyInfo = PrivateKeyInfoFactory.createPrivateKeyInfo(privateKey);
//变字符串
ASN1Object asn1ObjectPublic = subjectPublicKeyInfo.toASN1Primitive();
byte[] publicInfoByte = asn1ObjectPublic.getEncoded();
ASN1Object asn1ObjectPrivate = privateKeyInfo.toASN1Primitive();
byte[] privateInfoByte = asn1ObjectPrivate.getEncoded();
//这里可以将密钥对保存到本地
return new SecretKey(encoder64.encodeToString(publicInfoByte), encoder64.encodeToString(privateInfoByte));
}
/**
* 私钥加密
* @param data
* @param privateInfoStr
* @return
* @throws IOException
* @throws InvalidCipherTextException
*/
public String encryptData(String data, String privateInfoStr) throws IOException, InvalidCipherTextException {
AsymmetricBlockCipher cipher = new RSAEngine();
//这里也可以从流中读取,从本地导入
byte[] privateInfoByte=decoder64.decode(privateInfoStr);
AsymmetricKeyParameter priKey = PrivateKeyFactory.createKey(privateInfoByte);
//true表示加密
cipher.init(true, priKey);
byte[] encryptDataBytes = cipher.processBlock(data.getBytes(charset)
, 0, data.getBytes(charset).length);
return encoder64.encodeToString(encryptDataBytes);
}
/**
* 公钥解密
* @param data
* @param publicInfoStr
* @return
* @throws IOException
* @throws InvalidCipherTextException
*/
public String decryptData(String data, String publicInfoStr) throws IOException, InvalidCipherTextException {
AsymmetricBlockCipher cipher = new RSAEngine();
byte[] encryptDataBytes=decoder64.decode(data);
//解密
byte[] publicInfoBytes=decoder64.decode(publicInfoStr);
ASN1Object pubKeyObj =ASN1Primitive.fromByteArray(publicInfoBytes);
AsymmetricKeyParameter pubKey = PublicKeyFactory.createKey(SubjectPublicKeyInfo.getInstance(pubKeyObj));
//false表示解密
cipher.init(false, pubKey);
byte[] decryptDataBytes=cipher.processBlock(encryptDataBytes, 0, encryptDataBytes.length);
return new String(decryptDataBytes, charset);
}
public static void main(String[] args) throws IOException, InvalidCipherTextException {
RsaPayCryptImpl crypt = new RsaPayCryptImpl();
SecretKey secretKey = crypt.generateSecretKey();
System.out.println(secretKey);
String enStr = crypt.encryptData("你好测试测试", secretKey.getPrivateKey());
System.out.println(enStr);
String deStr = crypt.decryptData(enStr, secretKey.getPublicKey());
System.out.println(deStr);
enStr = crypt.encryptData("你好测试测试hello", secretKey.getPrivateKey());
System.out.println(enStr);
deStr = crypt.decryptData(enStr, secretKey.getPublicKey());
System.out.println(deStr);
}
}