RSA算法的Java实现

半世苍凉 提交于 2020-01-07 14:54:24

pom.xml导入jar包

<dependencies>
    <!-- https://mvnrepository.com/artifact/commons-io/commons-io -->
    <dependency>
        <groupId>commons-io</groupId>
        <artifactId>commons-io</artifactId>
        <version>2.6</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/commons-codec/commons-codec -->
    <dependency>
        <groupId>commons-codec</groupId>
        <artifactId>commons-codec</artifactId>
        <version>1.13</version>
    </dependency>
</dependencies>

代码:

package com.echo.servlet;

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

import javax.crypto.Cipher;
import java.io.ByteArrayOutputStream;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;

/**
 * @author echo
 * @create 2020-01-07 13:53
 */

public class RSAUtils {

    public static final String CHARSET = "UTF-8";
    public static final String RSA_ALGORITHM = "RSA";


    public static Map<String, String> createKeys(int keySize){
        //为RSA算法创建一个KeyPairGenerator对象
        KeyPairGenerator kpg;
        try{
            kpg = KeyPairGenerator.getInstance(RSA_ALGORITHM);
        }catch(NoSuchAlgorithmException e){
            throw new IllegalArgumentException("No such algorithm-->[" + RSA_ALGORITHM + "]");
        }

        //初始化KeyPairGenerator对象,密钥长度
        kpg.initialize(keySize);
        //生成密匙对
        KeyPair keyPair = kpg.generateKeyPair();
        //得到公钥
        Key publicKey = keyPair.getPublic();
        String publicKeyStr = Base64.encodeBase64URLSafeString(publicKey.getEncoded());
        //得到私钥
        Key privateKey = keyPair.getPrivate();
        String privateKeyStr = Base64.encodeBase64URLSafeString(privateKey.getEncoded());
        Map<String, String> keyPairMap = new HashMap<String, String>();
        keyPairMap.put("publicKey", publicKeyStr);
        keyPairMap.put("privateKey", privateKeyStr);

        return keyPairMap;
    }

    /**
     * 得到公钥
     * @param publicKey 密钥字符串(经过base64编码)
     * @throws Exception
     */
    public static RSAPublicKey getPublicKey(String publicKey) throws NoSuchAlgorithmException, InvalidKeySpecException {
        //通过X509编码的Key指令获得公钥对象
        KeyFactory keyFactory = KeyFactory.getInstance(RSA_ALGORITHM);
        X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(Base64.decodeBase64(publicKey));
        RSAPublicKey key = (RSAPublicKey) keyFactory.generatePublic(x509KeySpec);
        return key;
    }

    /**
     * 得到私钥
     * @param privateKey 密钥字符串(经过base64编码)
     * @throws Exception
     */
    public static RSAPrivateKey getPrivateKey(String privateKey) throws NoSuchAlgorithmException, InvalidKeySpecException {
        //通过PKCS#8编码的Key指令获得私钥对象
        KeyFactory keyFactory = KeyFactory.getInstance(RSA_ALGORITHM);
        PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKey));
        RSAPrivateKey key = (RSAPrivateKey) keyFactory.generatePrivate(pkcs8KeySpec);
        return key;
    }

    /**
     * 公钥加密
     * @param data
     * @param publicKey
     * @return
     */
    public static String publicEncrypt(String data, RSAPublicKey publicKey){
        try{
            Cipher cipher = Cipher.getInstance(RSA_ALGORITHM);
            cipher.init(Cipher.ENCRYPT_MODE, publicKey);
            return Base64.encodeBase64URLSafeString(rsaSplitCodec(cipher, Cipher.ENCRYPT_MODE, data.getBytes(CHARSET), publicKey.getModulus().bitLength()));
        }catch(Exception e){
            throw new RuntimeException("加密字符串[" + data + "]时遇到异常", e);
        }
    }

    /**
     * 私钥解密
     * @param data
     * @param privateKey
     * @return
     */

    public static String privateDecrypt(String data, RSAPrivateKey privateKey){
        try{
            Cipher cipher = Cipher.getInstance(RSA_ALGORITHM);
            cipher.init(Cipher.DECRYPT_MODE, privateKey);
            return new String(rsaSplitCodec(cipher, Cipher.DECRYPT_MODE, Base64.decodeBase64(data), privateKey.getModulus().bitLength()), CHARSET);
        }catch(Exception e){
            throw new RuntimeException("解密字符串[" + data + "]时遇到异常", e);
        }
    }

    /**
     * 私钥加密
     * @param data
     * @param privateKey
     * @return
     */

    public static String privateEncrypt(String data, RSAPrivateKey privateKey){
        try{
            Cipher cipher = Cipher.getInstance(RSA_ALGORITHM);
            cipher.init(Cipher.ENCRYPT_MODE, privateKey);
            return Base64.encodeBase64URLSafeString(rsaSplitCodec(cipher, Cipher.ENCRYPT_MODE, data.getBytes(CHARSET), privateKey.getModulus().bitLength()));
        }catch(Exception e){
            throw new RuntimeException("加密字符串[" + data + "]时遇到异常", e);
        }
    }

    /**
     * 公钥解密
     * @param data
     * @param publicKey
     * @return
     */

    public static String publicDecrypt(String data, RSAPublicKey publicKey){
        try{
            Cipher cipher = Cipher.getInstance(RSA_ALGORITHM);
            cipher.init(Cipher.DECRYPT_MODE, publicKey);
            return new String(rsaSplitCodec(cipher, Cipher.DECRYPT_MODE, Base64.decodeBase64(data), publicKey.getModulus().bitLength()), CHARSET);
        }catch(Exception e){
            throw new RuntimeException("解密字符串[" + data + "]时遇到异常", e);
        }
    }

    private static byte[] rsaSplitCodec(Cipher cipher, int opmode, byte[] datas, int keySize){
        int maxBlock = 0;
        if(opmode == Cipher.DECRYPT_MODE){
            maxBlock = keySize / 8;
        }else{
            maxBlock = keySize / 8 - 11;
        }
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        int offSet = 0;
        byte[] buff;
        int i = 0;
        try{
            while(datas.length > offSet){
                if(datas.length-offSet > maxBlock){
                    buff = cipher.doFinal(datas, offSet, maxBlock);
                }else{
                    buff = cipher.doFinal(datas, offSet, datas.length-offSet);
                }
                out.write(buff, 0, buff.length);
                i++;
                offSet = i * maxBlock;
            }
        }catch(Exception e){
            throw new RuntimeException("加解密阀值为["+maxBlock+"]的数据时发生异常", e);
        }
        byte[] resultDatas = out.toByteArray();
        IOUtils.closeQuietly(out);
        return resultDatas;
    }



    public static void main (String[] args) throws Exception {
        Map<String, String> keyMap = RSAUtils.createKeys(1024);
        String  publicKey = keyMap.get("publicKey");
        String  privateKey = keyMap.get("privateKey");
        System.out.println("公钥: \n\r" + publicKey);
        System.out.println("私钥: \n\r" + privateKey);

        System.out.println("公钥加密——私钥解密");
        String str = "\n" +
                "成长带走的不只是时光\n" +
                "还带走了当初那些不害怕失去的勇气\n" +
                "让自己忙一点,忙到没时间去思考无关紧要的事,很多事就能悄悄淡忘了\n" +
                "时间不一定能证明很多东西\n" +
                "但是一定能看透很多东西\n" +
                "坚信自己的选择,不动摇,使劲跑,明天会更好";
        System.out.println("\r明文:\r\n" + str);
        System.out.println("\r明文大小:\r\n" + str.getBytes().length);
        String encodedData = RSAUtils.publicEncrypt(str, RSAUtils.getPublicKey(publicKey));
        System.out.println("密文:\r\n" + encodedData);
        String decodedData = RSAUtils.privateDecrypt(encodedData, RSAUtils.getPrivateKey(privateKey));
        System.out.println("解密后文字: \r\n" + decodedData);


    }
}

运行结果:

公钥: 
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCFMgookxhkEjaNo9h1YbMZ4qRfv91EpCscaCRHVpnJqotBe1zIwF8ngjiXAZ1li7hjv2LnOi_YgKNFeyBRkKZflQGdCeNWzYK3Hq4s1aR0TnJJuKjXRTbqdlZ-NvERllKoU865Ga8g3-2Pt-XHMQyf-5XxNEfLEE64zFeMsumvUwIDAQAB
私钥: 
MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAIUyCiiTGGQSNo2j2HVhsxnipF-_3USkKxxoJEdWmcmqi0F7XMjAXyeCOJcBnWWLuGO_Yuc6L9iAo0V7IFGQpl-VAZ0J41bNgrcerizVpHROckm4qNdFNup2Vn428RGWUqhTzrkZryDf7Y-35ccxDJ_7lfE0R8sQTrjMV4yy6a9TAgMBAAECgYBQULIrcTc98HWQxwGZFkaHD1EKo4jrAQs1394wXhnxrrK104tJSiaWjkFNXR3pw2x2SUt8HmwHYtoQ5YPBazXGgjCiO3XNrG4rA6fwFsQ-ufEfQShLS43q7-_rnLKWWIbZ2Bmx9DHurrKu4V3fXHMKqmS_-jiAToZ6tT8dRzi98QJBAL1zE2C1XwwkefIsn34hb-Cssmxiq0VGfvQYzTz80Iv1cvVClAa7l4Y29BlN4XTdp-G0AEzXml-PAEOMsW2Sku8CQQCz_B4tH907ju6BY25IDY91sGMVPUtDjJ2jDaPVuj4k4KVbGqYa0QC2CvEnzodVr1tp1q4ErVb0xsLPcXtXcJndAkBAQ4PkP0IBpXH0U2y65W7FAO_5UjMU6cfw12Tvdjbr8xPO3InICuRoc8Wzu7Zp5TKonl2ns087cQ--2j_pklnjAkBUGw965LX8G-mmOvGQ6A1O4LMcfL0L_sy3IiuaN2LM1tFOhmByjZI4f1p70I37Y2tjRPeipeHJlov4Zj5N-QddAkEAvMM4f0H8KU-7o9I4RqnrEuW7YkRyzeprKm-BG5FcwfvncaYWp1R14z0kcuUuUEc0EcROLQvrjGdv0eUH-d-XTw
公钥加密——私钥解密
明文:

成长带走的不只是时光
还带走了当初那些不害怕失去的勇气
让自己忙一点,忙到没时间去思考无关紧要的事,很多事就能悄悄淡忘了
时间不一定能证明很多东西
但是一定能看透很多东西
坚信自己的选择,不动摇,使劲跑,明天会更好
明文大小:
312
密文:
ejXmbBRFHZe_u86zYTAmYdyOB7CufBm2e_0kTRsV70rsXMCs5vXu2zpg84iFJ9Yd8dDd7hwonXahs90K4t8yy7SIIC4jymj3EwYlpWobvyEQMt6VST0TYgTEP_DE3EkjPeyUJe_NWCmBInpQit5iHuCVMTsKdZfYfthRY1okKqJglgasCM6CFn8HsVWdDDvce6hhwllK0EphHfWoAxlmKquz0DxK_zGRdFm1uIxgxHm5dJOux512ano1em6lQRUX-X2TYgfDwTAh9EjJ_R1Utm13CYHNzP1X3vstQv9SZw3h2_zzIe2z79HpGydWYZvtOYLz7f8MvKP8QQZfcE8Lq1BFBnL5NhbEoomYSEabzi3S6tjCV0uoBtWTNABf27TqFmTwqK7tTqPhzS7JjHL2F6IVthBt3mvrobUXf1zbrtRvJBYybGDHRhoYaJsuIe7BvP_L3BQH9hizRswUWXlnjoRjuZ1S1cDhKuk6gnroz6tQY19bAGzF0qwqOjMRj53S
解密后文字: 

成长带走的不只是时光
还带走了当初那些不害怕失去的勇气
让自己忙一点,忙到没时间去思考无关紧要的事,很多事就能悄悄淡忘了
时间不一定能证明很多东西
但是一定能看透很多东西
坚信自己的选择,不动摇,使劲跑,明天会更好
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!