RSA实现对文件的加密解密

很多示例只能加密小文件 这个可以加密大点的文件 文件越大加解密时间越长




package com.harp.oa.utils;

import org.bouncycastle.jce.provider.BouncyCastleProvider;
import javax.crypto.Cipher;
import java.io.*;
import java.math.BigInteger;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.*;
import java.util.Date;

public class RSAFileUtil {

    /** 加解密算法关键字 */
    public static final String KEY_ALGORITHM = "RSA";

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

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

    public static KeyPair generateKeyPair() {
        try {
            KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(KEY_ALGORITHM,
                                          new BouncyCastleProvider());

            final int KEY_SIZE = 1024;
            keyPairGen.initialize(KEY_SIZE, new SecureRandom());
            KeyPair keyPair = keyPairGen.genKeyPair();
            return keyPair;
        } catch (Exception e) {
            return null;
        }
    }


    /**
     * 生成公钥
     * @param modulus
     * @param
     * @return RSAPublicKey
     * @throws
     */
    public static RSAPublicKey generateRSAPublicKey(byte[] modulus,byte[] publicExponent) {
        KeyFactory keyFac = null;
        try {
            keyFac = KeyFactory.getInstance(KEY_ALGORITHM,
                    new org.bouncycastle.jce.provider.BouncyCastleProvider());
        } catch (NoSuchAlgorithmException ex) {
        }
        RSAPublicKeySpec pubKeySpec = new RSAPublicKeySpec(new BigInteger(
                  modulus), new BigInteger(publicExponent));
        try {
            return (RSAPublicKey) keyFac.generatePublic(pubKeySpec);
        } catch (InvalidKeySpecException ex) {
            return null;
        }
    }

    /**
     * 生成私钥
     * @param modulus
     * @param privateExponent
     * @return RSAPrivateKey
     * @throws
     */
    public static RSAPrivateKey generateRSAPrivateKey(byte[] modulus, byte[] privateExponent) {
        KeyFactory keyFac = null;
        try {
            keyFac = KeyFactory.getInstance(KEY_ALGORITHM,
                    new org.bouncycastle.jce.provider.BouncyCastleProvider());
        } catch (NoSuchAlgorithmException ex) {

        }
        RSAPrivateKeySpec priKeySpec = new RSAPrivateKeySpec(new BigInteger(modulus),
                                       new BigInteger(privateExponent));
        try {
            return (RSAPrivateKey) keyFac.generatePrivate(priKeySpec);
        } catch (InvalidKeySpecException ex) {
            return null;
        }
    }

    /**
     * 使用公钥进行分段加密
     * @param
     * @return 公钥base64字符串
     * @throws Exception
     */
    public static byte[] encryptByPublicKeyToFile(byte[] filebyte,byte[] key)
            throws Exception {
        //要加密的数据
        PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(key);
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        Key privateKey = keyFactory.generatePrivate(pkcs8KeySpec);
        // 对数据加密
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        cipher.init(Cipher.ENCRYPT_MODE, privateKey);
        int inputLen = filebyte.length;
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        int offSet = 0;
        byte[] cache;
        int i = 0;
        // 对数据分段加密
        while (inputLen - offSet > 0) {
            if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {
                cache = cipher.doFinal(filebyte, offSet, MAX_ENCRYPT_BLOCK);
            } else {
                cache = cipher.doFinal(filebyte, offSet, inputLen - offSet);
            }
            out.write(cache, 0, cache.length);
            i++;
            offSet = i * MAX_ENCRYPT_BLOCK;
        }
        byte[] encryptedData = out.toByteArray();
        out.close();
        return encryptedData;
    }

    /**
     * 使用私钥进行分段解密
     * @param dataStr 使用base64处理过的密文
     * @return 解密后的数据
     * @throws Exception
     */
    public static byte[] decryptByPrivateKeyFile(byte[] dataStr ,byte[] pubKey)
            throws Exception {

        X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(pubKey);
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        Key publicKey = keyFactory.generatePublic(x509KeySpec);
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        cipher.init(Cipher.DECRYPT_MODE, publicKey);
        int inputLen = dataStr.length;
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        int offSet = 0;
        byte[] cache;
        int i = 0;
        // 对数据分段解密
        while (inputLen - offSet > 0) {
            if (inputLen - offSet > MAX_DECRYPT_BLOCK) {
                cache = cipher.doFinal(dataStr, offSet, MAX_DECRYPT_BLOCK);
            } else {
                cache = cipher.doFinal(dataStr, offSet, inputLen - offSet);
            }
            out.write(cache, 0, cache.length);
            i++;
            offSet = i * MAX_DECRYPT_BLOCK;
        }
        byte[] decryptedData = out.toByteArray();
        out.close();
        return decryptedData;
    }

    /**
     * @param keyPair
     * @param path1   原文件
     * @param path2   加密文件
     * @throws Exception
     */
    public static void encrypt(KeyPair keyPair,String path1,String path2) throws Exception{
        // 读取要加密的文件
        RSAPrivateKey priKey = (RSAPrivateKey) keyPair.getPrivate();
        File file = new File(path1);
        FileInputStream in = new FileInputStream(file);
        ByteArrayOutputStream bout = new ByteArrayOutputStream();
        byte[] tmpbuf = new byte[1024];
        int count = 0;
        while ((count = in.read(tmpbuf)) != -1) {
            bout.write(tmpbuf, 0, count);
            tmpbuf = new byte[1024];
        }
        in.close();
        // 对数据文件进行加密处理
        byte[] orgData = bout.toByteArray();
        byte[] priModBytes = priKey.getModulus().toByteArray();
        byte[] priPriExpBytes = priKey.getPrivateExponent().toByteArray();
        RSAPrivateKey recoveryPriKey = RSAFileUtil.generateRSAPrivateKey(priModBytes, priPriExpBytes);
        // 对文件进行加密
        byte[] raw = encryptByPublicKeyToFile(orgData,priKey.getEncoded());
        file = new File(path2);
        OutputStream out = new FileOutputStream(file);
        out.write(raw);
        out.close();
    }

    /**
     *
     * @param keyPair
     * @param path1 加密文件
     * @param path2   解密文件
     * @throws Exception
     */
    public static void decrypt(KeyPair keyPair,String path1,String path2) throws Exception{

        // 对文件进行解密
        RSAPublicKey pubKey = (RSAPublicKey) keyPair.getPublic();
        byte[] pubModBytes = pubKey.getModulus().toByteArray();
        byte[] pubPubExpBytes = pubKey.getPublicExponent().toByteArray();
        RSAPublicKey recoveryPubKey = RSAFileUtil.generateRSAPublicKey(pubModBytes, pubPubExpBytes);
        File file = new File(path1);
        FileInputStream in = new FileInputStream(file);
        ByteArrayOutputStream bout = new ByteArrayOutputStream();
        byte[] tmpbuf = new byte[1024];
        int count = 0;
        while ((count = in.read(tmpbuf)) != -1) {
            bout.write(tmpbuf, 0, count);
            tmpbuf = new byte[1024];
        }
        in.close();
        byte[] orgData1 = bout.toByteArray();
        byte[] data = decryptByPrivateKeyFile(orgData1,recoveryPubKey.getEncoded());
        file = new File(path2);
        FileOutputStream out = new FileOutputStream(file);
        out.write(data);
        out.flush();
        out.close();
    }

    public static void main(String[] args) throws Exception {
        System.out.println("加密开始:"+DateUtils.getAllStringDate(new Date()));
        KeyPair keyPair = RSAFileUtil.generateKeyPair();
        encrypt(keyPair,"D:\\zhr\\image\\123.pdf","D:\\zhr\\image\\encrypt.ms");
        System.out.println("加密结束 解密开始:"+DateUtils.getAllStringDate(new Date()));
        decrypt(keyPair,"D:\\zhr\\image\\encrypt.ms","D:\\zhr\\image\\456.pdf");
        System.out.println("解密结束:"+DateUtils.getAllStringDate(new Date()));
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值