使用bouncycastle在Java下进行RSA加密(私钥加密,公钥解密)

41 篇文章 1 订阅
38 篇文章 0 订阅

加密过长的会报错:

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

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值