RSA算法加密解密,數據傳輸,前台與后台數據交互


1、RSA算法加密解密思路。

      java后台隨機生成公鑰、私鑰。存儲於session中,告知前台js獲取公鑰。通過jsencrypt.min.js進行加密。傳輸回后台,后台通過私鑰解密。

2、RSA常見異常分解。

    問題一

Cannot find any provider supporting RSA

出現此問題,屬於JDK版本bug問題,筆者1.8.0_171遇到此問題,更換1.8.0_211之后即可解決。

問題二

DER input, Integer tag error

出現此問題,主要是公鑰,私鑰混用到至,通過斷點發現解密時,用的公鑰進行解密,哈哈。

問題三

Decryption error

出現此問題,主要是前台頁面傳參至后台,出現“+”符號被替換成“ ”空格導致無法進行解密。

 

3.代碼部分。

<script language=javascript>
var publicKey = '<%=session.getAttribute("publicKey")%>';
$(document).ready(function() {
    $('#doSearch').click(function(e) {
        var  phoneNo= $("#phoneNo").val();
        var encrypt = new JSEncrypt();
        encrypt.setPublicKey(publicKey);
        phoneNo = encrypt.encrypt(phoneNo);
        alert(phoneNo);
document.frm.submit(); }); });
</script>

 放入session部分

    @RequestMapping(value = "/index")
    public String login(Model model, HttpSession session,HttpServletRequest request) {
        Map<String, String> rsaMap = new  HashMap<String, String>();
        rsaMap = RsaUtil.createRSAKeys();
        String publicKey = rsaMap.get("publicKey");
        String privateKey = rsaMap.get("privateKey");
        session.setAttribute("publicKey", publicKey);
        session.setAttribute("niceKey", privateKey);
        return "index";
    }

 

 解析部分

    @RequestMapping(value = "/search", method = RequestMethod.POST)
    public String search(@ModelAttribute String phoneNo, HttpServletRequest request,
            HttpSession session, Model model) {
                if (phoneNo==null || "".equals(phoneNo)) {
                    model.addAttribute("returnUrl", "fail");
                    return "fail";
                }
                //RSA解密
                phoneNo = phoneNo.replace(" ", "+");
                phoneNo = RsaUtil.decode(phoneNo, session.getAttribute("niceKey").toString());
                System.out.println("phoneNo:" + phoneNo);
                
                {
                    //業務代碼
                }
        return "success";
    }

 

 

 

 RSA工具類部分

package com.thinksep.utils;

import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
 
import javax.crypto.Cipher;
 
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.tomcat.util.codec.binary.Base64;
 
/**
* @author 
* @createDate 
*/
public class RsaUtil {
    protected static final Log log = LogFactory.getLog(RsaUtil.class);
    private static String KEY_RSA_TYPE = "RSA";
    private static int KEY_SIZE = 1024;//JDK方式RSA加密最大只有1024位
    private static int ENCODE_PART_SIZE = KEY_SIZE/8;
    public static final String PUBLIC_KEY_NAME = "public";
    public static final String PRIVATE_KEY_NAME = "private";
 
    /**
     * 創建公鑰秘鑰
     * @return
     */
    public static Map<String,String> createRSAKeys(){
        Map<String,String> keyPairMap = new HashMap<>();//里面存放公私秘鑰的Base64位加密
        try {
            KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(KEY_RSA_TYPE);
            keyPairGenerator.initialize(KEY_SIZE,new SecureRandom());
            KeyPair keyPair = keyPairGenerator.generateKeyPair();
 
            //獲取公鑰秘鑰
            String publicKeyValue = Base64.encodeBase64String(keyPair.getPublic().getEncoded());
            String privateKeyValue = Base64.encodeBase64String(keyPair.getPrivate().getEncoded());
 
            //存入公鑰秘鑰,以便以后獲取
            keyPairMap.put(PUBLIC_KEY_NAME,publicKeyValue);
            keyPairMap.put(PRIVATE_KEY_NAME,privateKeyValue);
        } catch (NoSuchAlgorithmException e) {
            log.error("當前JDK版本沒找到RSA加密算法!");
            e.printStackTrace();
        }
        return keyPairMap;
    }
 
    /**
     * 公鑰加密
     * 描述:
     *     1字節 = 8位;
     *     最大加密長度如 1024位私鑰時,最大加密長度為 128-11 = 117字節,不管多長數據,加密出來都是 128 字節長度。
     * @param sourceStr
     * @param publicKeyBase64Str
     * @return
     */
    public static String encode(String sourceStr,String publicKeyBase64Str){
        byte [] publicBytes = Base64.decodeBase64(publicKeyBase64Str);
        //公鑰加密
        X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(publicBytes);
        List<byte[]> alreadyEncodeListData = new LinkedList<>();
 
        int maxEncodeSize = ENCODE_PART_SIZE - 11;
        String encodeBase64Result = null;
        try {
            KeyFactory keyFactory = KeyFactory.getInstance(KEY_RSA_TYPE);
            PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
            Cipher cipher = Cipher.getInstance(KEY_RSA_TYPE);
            cipher.init(Cipher.ENCRYPT_MODE,publicKey);
            byte[] sourceBytes = sourceStr.getBytes("utf-8");
            int sourceLen = sourceBytes.length;
            for(int i=0;i<sourceLen;i+=maxEncodeSize){
                int curPosition = sourceLen - i;
                int tempLen = curPosition;
                if(curPosition > maxEncodeSize){
                    tempLen = maxEncodeSize;
                }
                byte[] tempBytes = new byte[tempLen];//待加密分段數據
                System.arraycopy(sourceBytes,i,tempBytes,0,tempLen);
                byte[] tempAlreadyEncodeData = cipher.doFinal(tempBytes);
                alreadyEncodeListData.add(tempAlreadyEncodeData);
            }
            int partLen = alreadyEncodeListData.size();//加密次數
 
            int allEncodeLen = partLen * ENCODE_PART_SIZE;
            byte[] encodeData = new byte[allEncodeLen];//存放所有RSA分段加密數據
            for (int i = 0; i < partLen; i++) {
                byte[] tempByteList = alreadyEncodeListData.get(i);
                System.arraycopy(tempByteList,0,encodeData,i*ENCODE_PART_SIZE,ENCODE_PART_SIZE);
            }
            encodeBase64Result = Base64.encodeBase64String(encodeData);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return encodeBase64Result;
    }
 
    /**
     * 私鑰解密
     * @param sourceBase64RSA
     * @param privateKeyBase64Str
     */
    public static String decode(String sourceBase64RSA,String privateKeyBase64Str){
        byte[] privateBytes = Base64.decodeBase64(privateKeyBase64Str);
        byte[] encodeSource = Base64.decodeBase64(sourceBase64RSA);
        int encodePartLen = encodeSource.length/ENCODE_PART_SIZE;
        List<byte[]> decodeListData = new LinkedList<>();//所有解密數據
        String decodeStrResult = null;
        //私鑰解密
        PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(privateBytes);
        try {
            KeyFactory keyFactory = KeyFactory.getInstance(KEY_RSA_TYPE);
            PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
            Cipher cipher = Cipher.getInstance(KEY_RSA_TYPE);
            cipher.init(Cipher.DECRYPT_MODE,privateKey);
            int allDecodeByteLen = 0;//初始化所有被解密數據長度
            for (int i = 0; i < encodePartLen; i++) {
                byte[] tempEncodedData = new byte[ENCODE_PART_SIZE];
                System.arraycopy(encodeSource,i*ENCODE_PART_SIZE,tempEncodedData,0,ENCODE_PART_SIZE);
                byte[] decodePartData = cipher.doFinal(tempEncodedData);
                decodeListData.add(decodePartData);
                allDecodeByteLen += decodePartData.length;
            }
            byte [] decodeResultBytes = new byte[allDecodeByteLen];
            for (int i = 0,curPosition = 0; i < encodePartLen; i++) {
                byte[] tempSorceBytes = decodeListData.get(i);
                int tempSourceBytesLen = tempSorceBytes.length;
                System.arraycopy(tempSorceBytes,0,decodeResultBytes,curPosition,tempSourceBytesLen);
                curPosition += tempSourceBytesLen;
            }
            decodeStrResult = new String(decodeResultBytes,"UTF-8");
        }catch (Exception e){
            e.printStackTrace();
        }
        return decodeStrResult;
    }
}

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM