RSA分段加解密

推荐 源码巴士 696浏览
package com.kengkeng.rsa;

import org.apache.commons.codec.binary.Base64;

import javax.crypto.Cipher;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.security.KeyFactory;
import java.security.Signature;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;


public class RSAUtil {

    public static void main(String[] args) {

        String str = "我们都是共产主义接班人。";
        String crypt = encryptByPrivateKey(str);
        System.out.println("私钥加密密文:" + crypt);
        String result = decryptByPublicKey(crypt);
        System.out.println("公钥解密原文:" + result);

        System.out.println("---");

        str = "我们都是共产主义接班人。";
        crypt = encryptByPublicKey(str);
        System.out.println("公钥加密密文:" + crypt);
        result = decryptByPrivateKey(crypt);
        System.out.println("密钥解密原文:" + result);

        System.out.println("---");

        str = "签名。";
        System.out.println("原文:" + str);
        String str1 = signByPrivateKey(str);
        System.out.println("签名结果:" + str1);
        if (verifyByPublicKey(str1, str)) {
            System.out.println("成功");
        } else {
            System.out.println("失败");
        }
    }

    /**
     * 密钥
     */
    private static String priKey = readStringFromFile("pri.key");
    /**
     * 公钥
     */
    private static String pubKey = readStringFromFile("pub.key");
    /**
     * 加密算法RSA
     */
    public static final String KEY_ALGORITHM = "RSA";

    /**
     * 签名算法
     */
    public static final String SIGNATURE_ALGORITHM = "SHA1withRSA";

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

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

    /**
     * 使用私钥加密
     * @param data 源数据
     * @see decByPriKey
     */
    public static String encryptByPrivateKey(String data) {
        // 加密
        String str = "";
        try {
            byte[] priByte = base64decode(priKey.trim());
            PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(priByte);
            KeyFactory fac = KeyFactory.getInstance(KEY_ALGORITHM);
            RSAPrivateKey privateKey = (RSAPrivateKey) fac.generatePrivate(keySpec);
            //算法/模式/填充
            Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
            cipher.init(Cipher.ENCRYPT_MODE, privateKey);

            int inputLen = data.getBytes().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(data.getBytes(), offSet, MAX_ENCRYPT_BLOCK);
                } else {
                    cache = cipher.doFinal(data.getBytes(), offSet, inputLen - offSet);
                }
                out.write(cache, 0, cache.length);
                i++;
                offSet = i * MAX_ENCRYPT_BLOCK;
            }
            byte[] encryptedData = out.toByteArray();
            out.close();

            str = base64encode(encryptedData);
        } catch (Exception e) {
            e.printStackTrace();

        }
        return str;
    }

    /**
     * 使用私钥解密
     * @param data 已加密数据
     * @see decByPriKey
     */
    public static String decryptByPrivateKey(String data) {
        // 加密
        String str = "";
        try {
            byte[] priByte = base64decode(priKey.trim());
            PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(priByte);
            KeyFactory fac = KeyFactory.getInstance(KEY_ALGORITHM);
            RSAPrivateKey privateKey = (RSAPrivateKey) fac.generatePrivate(keySpec);
            Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
            cipher.init(Cipher.DECRYPT_MODE, privateKey);

            byte[] dataBytes = Base64.decodeBase64(data);
            int inputLen = dataBytes.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(dataBytes, offset, MAX_DECRYPT_BLOCK);
                } else {
                    cache = cipher.doFinal(dataBytes, offset, inputLen - offset);
                }
                out.write(cache, 0, cache.length);
                i++;
                offset = i * MAX_DECRYPT_BLOCK;
            }
            byte[] decryptedData = out.toByteArray();
            out.close();
            // 解密后的内容
            str = new String(decryptedData);

        } catch (Exception e) {
            e.printStackTrace();

        }
        return str;
    }


    /**
     * 使用公钥加密
     * @param data 源数据
     * @see decByPriKey
     */
    public static String encryptByPublicKey(String data) {
        // 加密
        String str = "";
        try {
            byte[] pubByte = base64decode(pubKey.trim());
            X509EncodedKeySpec keySpec = new X509EncodedKeySpec(pubByte);
            KeyFactory fac = KeyFactory.getInstance(KEY_ALGORITHM);
            RSAPublicKey rsaPubKey = (RSAPublicKey) fac.generatePublic(keySpec);
            Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
            cipher.init(Cipher.ENCRYPT_MODE, rsaPubKey);
            int inputLen = data.getBytes().length;
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            int offSet = 0;
            byte[] cache;
            int i = 0;
            while (inputLen - offSet > 0) {
                //MAX_ENCRYPT_BLOCK 117
                if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {
                    cache = cipher.doFinal(data.getBytes(), offSet, MAX_ENCRYPT_BLOCK);
                } else {
                    cache = cipher.doFinal(data.getBytes(), offSet, inputLen - offSet);
                }
                out.write(cache, 0, cache.length);
                i++;
                offSet = i * MAX_ENCRYPT_BLOCK;
            }
            byte[] encryptedData = out.toByteArray();
            out.close();

            str = base64encode(encryptedData);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return str;
    }

    /**
     * 使用公钥解密
     * @param data 已加密数据
     * @see decByPriKey
     */
    public static String decryptByPublicKey(String data) {
        // 加密
        String str = "";
        try {
            byte[] pubByte = base64decode(pubKey.trim());
            X509EncodedKeySpec keySpec = new X509EncodedKeySpec(pubByte);
            KeyFactory fac = KeyFactory.getInstance(KEY_ALGORITHM);
            RSAPublicKey rsaPubKey = (RSAPublicKey) fac.generatePublic(keySpec);
            Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
            cipher.init(Cipher.DECRYPT_MODE, rsaPubKey);
            byte[] dataBytes = Base64.decodeBase64(data);
            int inputLen = dataBytes.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(dataBytes, offset, MAX_DECRYPT_BLOCK);
                } else {
                    cache = cipher.doFinal(dataBytes, offset, inputLen - offset);
                }
                out.write(cache, 0, cache.length);
                i++;
                offset = i * MAX_DECRYPT_BLOCK;
            }
            byte[] decryptedData = out.toByteArray();
            out.close();
            str = new String(decryptedData);
        } catch (Exception e) {
            e.printStackTrace();

        }
        // 解密后的内容
        return str;
    }

    /**
     * 本方法使用SHA1withRSA签名算法产生签名
     *
     * @param String src 签名的原字符串
     * @return String 签名的返回结果(16进制编码)。当产生签名出错的时候,返回null。
     */
    public static String signByPrivateKey(String src) {
        try {
            Signature sigEng = Signature.getInstance(SIGNATURE_ALGORITHM);
            byte[] priByte = base64decode(priKey.trim());
            PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(priByte);
            KeyFactory fac = KeyFactory.getInstance(KEY_ALGORITHM);
            RSAPrivateKey privateKey = (RSAPrivateKey) fac.generatePrivate(keySpec);
            sigEng.initSign(privateKey);
            sigEng.update(src.getBytes());
            byte[] signature = sigEng.sign();
            return base64encode(signature);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 使用共钥验证签名
     *
     * @param sign
     * @param src
     * @return
     */
    public static boolean verifyByPublicKey(String sign, String src) {
        try {
            Signature sigEng = Signature.getInstance(SIGNATURE_ALGORITHM);
            byte[] pubByte = base64decode(pubKey.trim());
            X509EncodedKeySpec keySpec = new X509EncodedKeySpec(pubByte);
            KeyFactory fac = KeyFactory.getInstance(KEY_ALGORITHM);
            RSAPublicKey rsaPubKey = (RSAPublicKey) fac.generatePublic(keySpec);
            sigEng.initVerify(rsaPubKey);
            sigEng.update(src.getBytes());
            byte[] sign1 = base64decode(sign);
            return sigEng.verify(sign1);
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * base64加密
     *
     * @param bytes
     * @return
     */
    @SuppressWarnings("restriction")
    private static String base64encode(byte[] bytes) {
        String str = new sun.misc.BASE64Encoder().encode(bytes);
        str = str.replaceAll("\r\n", "").replaceAll("\r", "").replaceAll("\n", "");
        return str;
    }

    /**
     * base64解密
     *
     * @param str
     * @return byte[]
     */
    @SuppressWarnings("restriction")
    private static byte[] base64decode(String str) {
        byte[] bt = null;
        try {
            sun.misc.BASE64Decoder decoder = new sun.misc.BASE64Decoder();
            bt = decoder.decodeBuffer(str);
        } catch (IOException e) {
            e.printStackTrace();
        }

        return bt;
    }

    /**
     * 从文件中读取所有字符串
     *
     * @param fileName
     * @return String
     */
    private static String readStringFromFile(String fileName) {
        StringBuffer str = new StringBuffer();
        try {
            File file = new File(fileName);
            FileReader fr = new FileReader(file);
            char[] temp = new char[1024];
            while (fr.read(temp) != -1) {
                str.append(temp);
            }
            fr.close();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();

        }
        return str.toString();
    }
}

转载请注明:源码巴士 » RSA分段加解密