JAVA RSA PKCS1 分段加解密 | 祭夜博客
  • 欢迎光临,这个博客颜色有点多

JAVA RSA PKCS1 分段加解密

Wordpress msojocs 4年前 (2021-04-26) 2788次浏览 已收录 0个评论 扫描二维码
文章目录[隐藏]

pom.xml文件

    <dependency>
      <groupId>org.bouncycastle</groupId>
      <artifactId>bcprov-jdk15on</artifactId>
      <version>1.64</version>
    </dependency>
    <!-- Feb, 2011 -->
    <dependency>
      <groupId>org.bouncycastle</groupId>
      <artifactId>bcpg-jdk16</artifactId>
      <version>1.46</version>
    </dependency>
    <!-- Oct, 2019 -->
    <dependency>
      <groupId>org.bouncycastle</groupId>
      <artifactId>bcpkix-jdk15on</artifactId>
      <version>1.64</version>
    </dependency>

代码

package cn.wecuit.utils;

import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
import org.bouncycastle.asn1.pkcs.RSAPrivateKey;

import javax.crypto.Cipher;
import java.io.ByteArrayOutputStream;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Security;
import java.security.spec.RSAPrivateKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;

public class RSAUtils {

    /**
     * RSA最大加密明文大小
     */
    private static final int MAX_ENCRYPT_BLOCK = 117;

    /**
     * RSA最大解密密文大小
     */
    private static final int MAX_DECRYPT_BLOCK = 128;


    public static String encryptRSAByPubKey(String str, String publicKey) throws Exception {
        Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
        Cipher rsa = Cipher.getInstance("RSA/ECB/PKCS1Padding", "BC");
        rsa.init(Cipher.ENCRYPT_MODE, getPublicKey(publicKey));   //getPrivateKey(privateKey):将privateKey转成pkcs1的密文形式

        byte[] data = str.getBytes();
        int inputLen = data.length;
        int offset = 0;
        byte[] cache;
        int i = 0;
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        //分段加密 参考:https://www.cnblogs.com/duanjt/p/11459600.html
        while(inputLen -offset > 0){
            if(inputLen - offset > MAX_ENCRYPT_BLOCK)
                cache = rsa.doFinal(data, offset, MAX_ENCRYPT_BLOCK);
            else
                cache = rsa.doFinal(data, offset, inputLen - offset);
            out.write(cache, 0, cache.length);
            i++;
            offset = i * MAX_ENCRYPT_BLOCK;
        }
        String result = new String(Base64.getEncoder().encode(out.toByteArray()));
        out.close();
        return result;
    }
    public static String decryptRSAByPriKey(String str, String privateKey) throws Exception {
        Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
        Cipher rsa = Cipher.getInstance("RSA/ECB/PKCS1Padding", "BC");
        rsa.init(Cipher.DECRYPT_MODE, getPrivateKey(privateKey));   //getPrivateKey(privateKey):将privateKey转成pkcs1的密文形式

        byte[] data = Base64.getDecoder().decode(str);
        int inputLen = data.length;
        int offset = 0;
        byte[] cache;
        int i = 0;
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        //分段加密
        while(inputLen -offset > 0){
            if(inputLen - offset > MAX_DECRYPT_BLOCK)
                cache = rsa.doFinal(data, offset, MAX_DECRYPT_BLOCK);
            else
                cache = rsa.doFinal(data, offset, inputLen - offset);
            out.write(cache, 0, cache.length);
            i++;
            offset = i * MAX_DECRYPT_BLOCK;
        }
        String result = out.toString("UTF-8");
        out.close();
        return result;
    }

    /**
     * 参考: https://blog.csdn.net/weixin_43303530/article/details/111479748
     * @param privateKey
     * @return
     * @throws Exception
     */
    private static PrivateKey getPrivateKey(String privateKey) throws Exception {
        String privKeyPEMNew = privateKey.replaceAll("\\n", "")
                .replace("-----BEGIN PRIVATE KEY-----", "")
                .replace("-----END PRIVATE KEY-----", "");
        byte[] e = Base64.getDecoder().decode(privKeyPEMNew);   //base64无法解析换行符,-等特殊符号
        PrivateKeyInfo pki = PrivateKeyInfo.getInstance(e);
        RSAPrivateKey pkcs1Key = RSAPrivateKey.getInstance(pki.parsePrivateKey());
        //RSAPrivateKeyStructure pkcs1Key = RSAPrivateKeyStructure.getInstance(pki.parsePrivateKey());
        //byte[] pkcs1Bytes = pkcs1Key.getEncoded();
        // 读取 PKCS#1的私钥
        //RSAPrivateKeyStructure asn1PrivateKey = new RSAPrivateKeyStructure((ASN1Sequence) ASN1Sequence.fromByteArray(pkcs1Bytes));
        //RSAPrivateKeySpec rsaPrivateKeySpec = new RSAPrivateKeySpec(asn1PrivateKey.getModulus(),asn1PrivateKey.getPrivateExponent());   此处注释的为过时方法,同样可以完成所需的效果
        RSAPrivateKeySpec rsaPrivateKeySpec = new RSAPrivateKeySpec(pkcs1Key.getModulus(),pkcs1Key.getPrivateExponent());
        // 实例化KeyFactory对象,并指定 RSA 算法
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        // 获得 PrivateKey 对象
        return keyFactory.generatePrivate(rsaPrivateKeySpec);
    }

    /**
     *
     * 参考:https://blog.csdn.net/chaiqunxing51/article/details/52116433?locationNum=3&fps=1
     * @param publicKey
     * @return
     * @throws Exception
     */
    private static PublicKey getPublicKey(String publicKey) throws Exception {
        String pubKeyPEMNew = publicKey.replaceAll("\\n", "")
                .replace("-----BEGIN PUBLIC KEY-----", "")
                .replace("-----END PUBLIC KEY-----", "");
        byte[] e = Base64.getDecoder().decode(pubKeyPEMNew);   //base64无法解析换行符,-等特殊符号
        // RSAPublicKey pki = RSAPublicKey.getInstance(e);
        // RSAPublicKeySpec rsaPublicKeySpec = new RSAPublicKeySpec(pki.getModulus(), pki.getPublicExponent());
        // // 实例化KeyFactory对象,并指定 RSA 算法
        // KeyFactory keyFactory = KeyFactory.getInstance("RSA");

        X509EncodedKeySpec pubX509 = new X509EncodedKeySpec(e);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        return keyFactory.generatePublic(pubX509);

        // 获得 PrivateKey 对象
        // return keyFactory.generatePublic(rsaPublicKeySpec);
    }

}

测试

package cn.wecuit.test;

import cn.wecuit.utils.RSAUtils;
import org.junit.Assert;
import org.junit.Test;


public class TestRSA {
    static String privateKey = "-----BEGIN PRIVATE KEY-----\n" +
            "MIICeQIBADANBgkqhkiG9w0BAQEFAASCAmMwggJfAgEAAoGBALKFyImIYEg6vhNe\n" +
            "iNLQGixxY8cmeJshEXRtUrI75LDMQBBAIK4qzgcqg8KTIAD9m5/BX7m5Y/s67+q0\n" +
            "4EIvZEEgmq8/IPuIHkCDix2+e+ZP+VFCfZPA3LUyVSsfVvV0aNf2G/vCsuRLTBOx\n" +
            "P1Mqv1/a8xZKHGLwA0L/hloohAOrAgMBAAECgYEApC739Mzwx90GjKfHrCJpv+/0\n" +
            "tOaDyyAJfotAn90HgTYHwSpJJAUIAH0wOpW2vFKBetaMZDHFavuURMZe7V/KkbRX\n" +
            "Oa4U0RdRBdqXhlLPWV6vXovrzp8QNsaU4k40y1/r12wVREKvd9wVoeUMPmApDlpW\n" +
            "yuNS5RTsQZEfTJXQdAkCQQDplPWdJar/rUNUvkHtjSeI1GmstkK4h0tdNt9cZOBG\n" +
            "LS7YCL26lxFq4mVq8I7Uw6KMBhBHRxRrpwiXxPvqdprNAkEAw6gIbq837orvbnqg\n" +
            "UWYpp1L91e3NuxVtipIJVkKPE4VGKcpoTkAcVyzFDNyfQT76GmK5jvVLw/m6781w\n" +
            "uNsIVwJBAL0Uitoh0tFTNQzVUlL0j4swvzZC97GeO4CCWb7WHcJQ8vmH4eW4Qi4u\n" +
            "hABUKJrMnrkQc37vZ/VY6hjJKU97oQUCQQCBPtKzKxPrg+O+O0sD+lSxr2T2mGw6\n" +
            "lWETFH0OelFBN9ytZoOYjUkrXOueH28kDpHwNB8XjHpMLv+JwVAhDK9pAkEAln6F\n" +
            "BHZYpFhiJXdfX5Cme8t9p039TDHmvvJfpRlaftWHIp4YNzyHTAXAm+58nkrIy9AY\n" +
            "2snwriQay+UX0RggdQ==\n" +
            "-----END PRIVATE KEY-----";
    static  String publicKey ="-----BEGIN PUBLIC KEY-----\n" +
            "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCyhciJiGBIOr4TXojS0BoscWPH\n" +
            "JnibIRF0bVKyO+SwzEAQQCCuKs4HKoPCkyAA/ZufwV+5uWP7Ou/qtOBCL2RBIJqv\n" +
            "PyD7iB5Ag4sdvnvmT/lRQn2TwNy1MlUrH1b1dGjX9hv7wrLkS0wTsT9TKr9f2vMW\n" +
            "Shxi8ANC/4ZaKIQDqwIDAQAB\n" +
            "-----END PUBLIC KEY-----";

    @Test
    public void test() throws Exception {
        String original = "000000009797976986123456789012345888888888888888888888888888888888888888213hgfjhgfggggguuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuhghg";
        String encryptData = RSAUtils.encryptRSAByPubKey(original, publicKey);
        System.out.println(encryptData);

        String s = RSAUtils.decryptRSAByPriKey(encryptData, privateKey);
        System.out.println(s);

        Assert.assertEquals(original, s);
    }

}

祭夜の咖啡馆 , 版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权
转载请注明原文链接:JAVA RSA PKCS1 分段加解密
喜欢 (4)
[1690127128@qq.com]
分享 (0)
发表我的评论
取消评论
OwO表情
贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址