RSA加密算法的实现


前言

由于在银行方面工作对数据安全性要求比较高,需要对前后端通信的数据进行加密,因此编写一个简易的RSA加密算法工具类,可以提高前后端传送数据时的安全性。再次罗列下来,希望自己能有一个更好的理解以及帮助到有需要的小伙伴!有问题的小伙伴可以底部留言,我抽空都会帮忙解答一下,一起加油,共同进步!

一、第一步使用generatorKeyPair产生公私钥

首先创建generatorKeyPair对象(传入要加密的算法)并初始化(传入加密位数),使用其产生keyPair,接着从其其中取出公私钥,最后放到map中进行打包返回。
 /**
     * 通过KeyPairGenerator产生公私钥
     * @return
     * @throws NoSuchAlgorithmException
     */
    public static Map<String ,Object> generetorKeyPair() throws NoSuchAlgorithmException {
    
    

        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(KEY_ALGORITHM);

        keyPairGenerator.initialize(INITIALIZE_LENGTH);

        KeyPair keyPair = keyPairGenerator.generateKeyPair();

        RSAPublicKey rsaPublicKey = (RSAPublicKey) keyPair.getPublic();

        RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) keyPair.getPrivate();

        HashMap<String, Object> map = new HashMap<>();

        map.put("RSAPublicKey",rsaPublicKey);

        map.put("RSAPrivateKey",rsaPrivateKey);

        return map;


    }


二、取出公私钥字符串

手动创建两个方法,分别对公私钥进行base64加密字符串(此处采用 java.util.Base64或者commons.codec下的Base64都是可以的),有效提高公私钥的安全性。

/**
     * 拿到RSA公钥字符串
     * @param map
     * @return
     */
    public static String getRSAPublicKey(Map<String ,Object> map) {
    
    

        Key rsaPublicKey = (Key) map.get(PUBLIC_KEY);

        return Base64.getEncoder().encodeToString(rsaPublicKey.getEncoded());


    }

    /**
     *拿到RSA私钥字符串
     * @param map
     * @return
     */
    public static String getRSAPriateKey(Map<String ,Object> map) {
    
    


        Key rsaPrivateKey = (Key) map.get(PRIVATE_KEY);

        return Base64.getEncoder().encodeToString(rsaPrivateKey.getEncoded());

    }



三、加解密算法

通过Cipher加解密类实现RSA的加密解密,加密和解密的过程类似,是一个可逆的过程。加密公钥采用的是X509EncodedKeySpec 产生一个实例作为参数传入KeyFactory中产生一个公钥。后面直接把公钥以及数据作为参数传入Cipher中即可实现加密。这里如果需要加密的数据长度较小可以采用一次加密。否则可以采用分段加密,代码中有详细解释,这里不多做阐述。解密的过程类似,但采用PKCS8EncodedKeySpec 产生实例,并把其传入KeyFactory中产生私钥,下面解密与加密类似可以一次性解密就直接解密,否则就分段解密。


 /**
     * 使用公钥进行加密
     * @param data
     * @param publicKey
     * @return
     * @throws Exception
     */
    public static byte[] encryptByPublic( byte[] data,String publicKey ) throws Exception {
    
    

        byte[] decode = Base64.getDecoder().decode(publicKey);

        X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(decode);

        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        PublicKey publicK = keyFactory.generatePublic(x509EncodedKeySpec);

        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        cipher.init(Cipher.ENCRYPT_MODE,publicK);

        //如果加密明文长度小于规定的最大长度,如下直接加密就好,否则需要分段加密
        //cipher.doFinal(data);


        //以下为分段加密

        int length = data.length;
        int i=0;
        int offset=0;
        byte[] cache = null;
        ByteArrayOutputStream baos = new ByteArrayOutputStream();

        while (length-offset>0) {
    
    
            if (length-offset>MAX_ENCRYPT_BLOCK) {
    
    

                cache = cipher.doFinal(data, offset, MAX_ENCRYPT_BLOCK);
            }else {
    
    
                cache = cipher.doFinal(data,offset,length-offset);
            }

            baos.write(cache,0,cache.length);
            i++;
            offset = i * MAX_ENCRYPT_BLOCK;
        }
        byte[] encryptData = baos.toByteArray();
        baos.close();
        return encryptData;

    }

    /**
     * 使用私钥进行解密
     * @param data
     * @param privateKey
     * @return
     * @throws Exception
     */
    public static byte[] decryptByPrivateKey( byte[] data,String privateKey ) throws Exception {
    
    

        byte[] decode = Base64.getDecoder().decode(privateKey);

        PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(decode);

        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        PrivateKey publicK = keyFactory.generatePrivate(pkcs8EncodedKeySpec);

        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        cipher.init(Cipher.DECRYPT_MODE,publicK);

        //如果解密明文长度小于规定的最大长度,如下直接解密就好,否则需要分段解密
        //cipher.doFinal(data);

        //以下为分段解密

        int length = data.length;
        int i=0;
        int offset=0;
        byte[] cache = null;
        ByteArrayOutputStream baos = new ByteArrayOutputStream();

        while (length-offset>0) {
    
    
            if (length-offset>MAX_DECRYPT_BLOCK) {
    
    

                cache = cipher.doFinal(data, offset, MAX_DECRYPT_BLOCK);

            }else {
    
    
                cache = cipher.doFinal(data,offset,length-offset);
            }
            baos.write(cache,0,cache.length);
            i++;
            offset = i * MAX_DECRYPT_BLOCK;
        }
        byte[] decryptData = baos.toByteArray();
        baos.close();
        return decryptData;

    }



该处使用的url网络请求的数据。


四、测试(附全码)

下面我们简单测试一下,随便传句话,试下效果。各位小伙伴们,如下所示:

package com.trs.util;

import jdk.nashorn.internal.runtime.RewriteException;
import org.omg.CORBA.PUBLIC_MEMBER;

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.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.Base64;
import java.util.HashMap;
import java.util.Map;

/**
 * Demo class
 *一个简易版本的RSA加密算法的实现
 * @author crazy-water
 * @date 10/21/2021 6:43 PM
 */
public class RSAUtil {
    
    

    //加密算法
    public static final  String KEY_ALGORITHM = "RSA";

    //RSA公钥
    public static final   String PUBLIC_KEY = "RSAPublicKey";

    //RSA私钥
    public static final String PRIVATE_KEY = "RSAPrivateKey";

    //1024位最大加密长度
    public static final int MAX_ENCRYPT_BLOCK = 117;

    //1024位最大解密长度
    public static final int MAX_DECRYPT_BLOCK = 128;

    //加密位数
    public static final int INITIALIZE_LENGTH = 1024;



    /**
     * 通过KeyPairGenerator产生公私钥
     * @return
     * @throws NoSuchAlgorithmException
     */
    public static Map<String ,Object> generetorKeyPair() throws NoSuchAlgorithmException {
    
    

        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(KEY_ALGORITHM);

        keyPairGenerator.initialize(INITIALIZE_LENGTH);

        KeyPair keyPair = keyPairGenerator.generateKeyPair();

        RSAPublicKey rsaPublicKey = (RSAPublicKey) keyPair.getPublic();

        RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) keyPair.getPrivate();

        HashMap<String, Object> map = new HashMap<>();

        map.put("RSAPublicKey",rsaPublicKey);

        map.put("RSAPrivateKey",rsaPrivateKey);

        return map;


    }


    /**
     * 拿到RSA公钥字符串
     * @param map
     * @return
     */
    public static String getRSAPublicKey(Map<String ,Object> map) {
    
    

        Key rsaPublicKey = (Key) map.get(PUBLIC_KEY);

        return Base64.getEncoder().encodeToString(rsaPublicKey.getEncoded());


    }

    /**
     *拿到RSA私钥字符串
     * @param map
     * @return
     */
    public static String getRSAPriateKey(Map<String ,Object> map) {
    
    


        Key rsaPrivateKey = (Key) map.get(PRIVATE_KEY);

        return Base64.getEncoder().encodeToString(rsaPrivateKey.getEncoded());

    }

    /**
     * 使用公钥进行加密
     * @param data
     * @param publicKey
     * @return
     * @throws Exception
     */
    public static byte[] encryptByPublic( byte[] data,String publicKey ) throws Exception {
    
    

        byte[] decode = Base64.getDecoder().decode(publicKey);

        X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(decode);

        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        PublicKey publicK = keyFactory.generatePublic(x509EncodedKeySpec);

        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        cipher.init(Cipher.ENCRYPT_MODE,publicK);

        //如果加密明文长度小于规定的最大长度,如下直接加密就好,否则需要分段加密
        //cipher.doFinal(data);


        //以下为分段加密

        int length = data.length;
        int i=0;
        int offset=0;
        byte[] cache = null;
        ByteArrayOutputStream baos = new ByteArrayOutputStream();

        while (length-offset>0) {
    
    
            if (length-offset>MAX_ENCRYPT_BLOCK) {
    
    

                cache = cipher.doFinal(data, offset, MAX_ENCRYPT_BLOCK);
            }else {
    
    
                cache = cipher.doFinal(data,offset,length-offset);
            }

            baos.write(cache,0,cache.length);
            i++;
            offset = i * MAX_ENCRYPT_BLOCK;
        }
        byte[] encryptData = baos.toByteArray();
        baos.close();
        return encryptData;

    }

    /**
     * 使用私钥进行解密
     * @param data
     * @param privateKey
     * @return
     * @throws Exception
     */
    public static byte[] decryptByPrivateKey( byte[] data,String privateKey ) throws Exception {
    
    

        byte[] decode = Base64.getDecoder().decode(privateKey);

        PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(decode);

        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        PrivateKey publicK = keyFactory.generatePrivate(pkcs8EncodedKeySpec);

        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        cipher.init(Cipher.DECRYPT_MODE,publicK);

        //如果解密明文长度小于规定的最大长度,如下直接解密就好,否则需要分段解密
        //cipher.doFinal(data);

        //以下为分段解密

        int length = data.length;
        int i=0;
        int offset=0;
        byte[] cache = null;
        ByteArrayOutputStream baos = new ByteArrayOutputStream();

        while (length-offset>0) {
    
    
            if (length-offset>MAX_DECRYPT_BLOCK) {
    
    

                cache = cipher.doFinal(data, offset, MAX_DECRYPT_BLOCK);

            }else {
    
    
                cache = cipher.doFinal(data,offset,length-offset);
            }
            baos.write(cache,0,cache.length);
            i++;
            offset = i * MAX_DECRYPT_BLOCK;
        }
        byte[] decryptData = baos.toByteArray();
        baos.close();
        return decryptData;

    }


    /**
     * 主函数测试
     * @param args
     * @throws Exception
     */
    public static void main(String[] args) throws Exception {
    
    


        Map<String, Object> map = generetorKeyPair();

        String rsaPublicKey = getRSAPublicKey(map);
        String rsaPriateKey = getRSAPriateKey(map);
        String  oldData = "各位小伙伴,新的一天继续加油哦";
        System.out.println("加密前的数据-----------"+oldData);
        byte[] encryptData = encryptByPublic(oldData.getBytes(), rsaPublicKey);
        byte[] decryptData = decryptByPrivateKey(encryptData, rsaPriateKey);

        System.out.println("解密后的数据-----------"+new String(decryptData));


    }


}

在这里插入图片描述测试结果图,如图所见,结果正确无误。小伙伴们,星光不负赶路人,抓紧搞起来吧。

猜你喜欢

转载自blog.csdn.net/fengzi_big/article/details/120894012