Java实现RSA分段加密解密

本文完成的是公钥加密,私钥解密(私钥加密公钥解密是一样的)。

注意点:

  1. 秘钥生成的格式不同,使用算法也不同,公钥是X509EncodedKeySpec,私钥是PKCS8EncodedKeySpec
  2. 报错java.security.spec.InvalidKeySpecException就是因为密钥格式问题。
  3. 报错Data must not be longer than *** bytes是因为没有分段解密,密文太长。
  4. 分段加密解密时钥注意偏移量,256位或者128位钥看自己密钥的生成。
  5. 本文把公私密钥做了编码获取处理是为了方便传输,如果不需要传输,可以不做,代码稍改即可。

代码如下

package RSA;



import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.*;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;


/**
 * @version v1.0
 * @ProjectName: Cryptography
 * @ClassName: RSA
 * @Description: TODO(RSA加密解密算法类)
 * @Author: 你还年轻
 * @Date: 2020/9/27 21:04
 */
public class RSA {
    /**
     * @Description: TODO(获取密钥对)
     * @param 
     * @return {@link KeyPair}
     * @author 你还年轻
     * @throws
     * @date 2020/9/27 21:48
     */
    public static KeyPair generateKeyPairs() throws NoSuchAlgorithmException, UnsupportedEncodingException {
        //标明算法类型
        String algorithm = "RSA";
        //创建秘钥对生成对象(密钥生成器)
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(algorithm);
        SecureRandom secureRandom = new SecureRandom(String.valueOf(System.currentTimeMillis()).getBytes("utf-8")); // 说的一个安全的随机数
        keyPairGenerator.initialize(2048, secureRandom);    // 这里可以是1024、2048 初始化一个密钥对
        //生成密钥对,此时公钥好私钥已经在keyPair对象中
        KeyPair keyPair = keyPairGenerator.generateKeyPair();
        return keyPair;
    }


    /**
     * @Description: TODO(获取密钥对中的公钥,并对其进行Base64编码处理)
     * @param keyPair
     * @return {@link String}
     * @author 你还年轻
     * @throws
     * @date 2020/9/27 21:49
     */
    public static String getPublicKeyBase64(KeyPair keyPair){
        //获取传进来的密钥对中的公钥
        PublicKey publicKey = keyPair.getPublic();
        //对公钥进行Base64编码
        String publicKeyBase64 = Base64.getEncoder().encodeToString(publicKey.getEncoded());
        return publicKeyBase64;
    }

    /**
     * @Description: TODO(获取密钥对中的私钥,并对其进行Base64编码处理)
     * @param keyPair
     * @return {@link String}
     * @author 你还年轻
     * @throws
     * @date 2020/9/27 22:43
     */
    public static String getPrivateKeyBase64(KeyPair keyPair){
        //获取传进来的密钥对中的私钥
        PrivateKey privateKey = keyPair.getPrivate();
        //对私钥进行Base64编码处理
        String privateKeyBase64 = Base64.getEncoder().encodeToString(privateKey.getEncoded());

        return privateKeyBase64;
    }
    /**
     * @Description: TODO(使用公钥加密)
     * @param publicKeyStr 经过Base64编码过的公钥字符串
     * @param content
     * @return {@link String}
     * @author 你还年轻
     * @throws
     * @date 2020/9/27 23:12
     */
    public static String publicKeyEncrypt(String content,String publicKeyStr)
            throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException, NoSuchProviderException, IOException {
//        传递进来的公钥是经过Base64编码过的字符串,要返回成字节数组形式,需要解码
        byte[] decodePublicKeyByte = Base64.getDecoder().decode(publicKeyStr);
        //调用X509EncodedKeySpec对象,转换格式
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(decodePublicKeyByte);
        //调用密钥工厂
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        PublicKey publicKey = keyFactory.generatePublic(keySpec);

        //调用Java加密的Cipher对象,
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.ENCRYPT_MODE,publicKey);//第一个参数表示这是加密模式,第二个参数表示密钥

        //分段加密
        byte[] bytesContent = content.getBytes();
        int inputLen = bytesContent.length;
        int offLen = 0;//偏移量
        int i = 0;
        ByteArrayOutputStream bops = new ByteArrayOutputStream();
        while(inputLen - offLen > 0){
            byte [] cache;
            if(inputLen - offLen > 256){
                cache = cipher.doFinal(bytesContent, offLen,256);
            }else{
                cache = cipher.doFinal(bytesContent, offLen,inputLen - offLen);
            }
            bops.write(cache);
            i++;
            offLen = 256 * i;
        }
        bops.close();
        byte[] encryptedData = bops.toByteArray();


        //使用Base64对加密结果进行编码
        String encode = Base64.getEncoder().encodeToString(encryptedData);
        return new String(encode);
    }

    /**
     * @Description: TODO(私钥解密)
     * @param content 秘文,base64编码过的字符串
     * @param privateKeyStr 私钥,base64编码过的字符串
     * @return {@link String}
     * @author 你还年轻
     * @throws
     * @date 2020/9/27 23:15
     */
    public static String privateKeyDecrypt(String content,String privateKeyStr)
            throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException, BadPaddingException, IllegalBlockSizeException, InvalidKeyException, IOException {
        //传递进来的私钥是经过Base64编码过的字符串,要返回成字节数组形式,需要解码
        byte[] decodePrivateKeyByte = Base64.getDecoder().decode(privateKeyStr);
        //调用PKCS8EncodedKeySpec对象
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(decodePrivateKeyByte);
        //调用密钥工厂
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
        //调用Java加密的Cipher对象,
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.DECRYPT_MODE,privateKey);//第一个参数表示这是加密模式,第二个参数表示密钥


        byte[] bytesContent = Base64.getDecoder().decode(content.getBytes());
        int inputLen = bytesContent.length;
        int offLen = 0;
        int i = 0;
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        while(inputLen - offLen > 0){
            byte[] cache;
            if(inputLen - offLen > 256){
                cache = cipher.doFinal(bytesContent,offLen,256);
            }else{
                cache = cipher.doFinal(bytesContent,offLen,inputLen - offLen);
            }
            byteArrayOutputStream.write(cache);
            i++;
            offLen = 256 * i;

        }
        byteArrayOutputStream.close();
        byte[] byteArray = byteArrayOutputStream.toByteArray();

        //使用Base64对加密结果进行编码
        return new String(byteArray);
    }


    public static void main(String[] args) throws
            NoSuchAlgorithmException, IllegalBlockSizeException, InvalidKeyException, BadPaddingException, InvalidKeySpecException, NoSuchPaddingException, IOException, NoSuchProviderException {
        String input = "123321";
        KeyPair keyPair = generateKeyPairs();
        String en = publicKeyEncrypt(input,getPublicKeyBase64(keyPair));
        String de = privateKeyDecrypt(en, getPrivateKeyBase64(keyPair));
        System.out.println("原文:"+input);
        System.out.println("密文:"+ en);
        System.out.println("解密:"+de);
    }
}

测试
在这里插入图片描述

  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值