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.代码部分。

引用地址:https://blog.csdn.net/qq_36827957/article/details/81563973

<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;
    }
}

原文地址:https://www.cnblogs.com/thinksep/p/10987920.html

时间: 2024-10-10 09:19:09

RSA算法加密解密,数据传输,前台与后台数据交互的相关文章

安全不安全002:C#实现RSA算法加密解密

通过前面的文章我们学会了如何生成公钥和私钥,详见这篇文章:https://blog.csdn.net/yysyangyangyangshan/article/details/80368397.那么,我们来看在C#中如何实现RSA加密解密.直接上代码,如下类是RSA算法实现的加密,加解密,签名以及签名的验证. /// <summary> /// 类名:RSACrypt /// 功能:RSA加密.解密.签名.验签 /// </summary> public sealed class R

RSA算法加密解密

该工具类中用到了BASE64,需要借助第三方类库:javabase64-1.3.1. jar 注意:RSA加密明文最大长度117字节,解密要求密文最大长度为128字节,所以在加密和解密的过程中需要分块进行. RSA加密对明文的长度是有限制的,如果加密数据过大会抛出如下异常: Exception in thread "main" javax.crypto.IllegalBlockSizeException: Data must not be longer than 117 bytes a

js前台与后台数据交互-前台调后台【转】

前台调用后台方法与变量: 方法一:通过WebService来实现 步骤: 后台 ?  首先引入命名空间(using System.Web.Services;) ?  然后定义公共的静态的方法(必须为public和static的,且静态方法不能访问外部的非静态变量,此时后台与前台相当于父类与子类的关系),并在该方法头部上加上[System.Web.Services.WebMethod],来标注方法特性. 前台 ?  添加ScriptManager服务器控件,并把其EnablePageMethods

JSP、servlet、SQL三者之间的数据传递(前台与后台数据交互)

背景: 目前业界很流行的MVC(model-view-control)开发模式,理解为 模型是Bean, 视图是 Html/Jsp, 控制是Servlet, 关联数据库的Dao web的运行机制: 数据首先在Jsp上被展示出来,用户看到页面后触发一些事件,并可能传递数据,这些数据和请求被控制器接收到,然后开始处理(往往会需要有一些数据库的操作(查询,修改数据库数据)),当这些处理结束后,我们就需要将数据反馈到JSP上显示给用户看,完成一次完整的交互过程. 正文: 根据背景所述的顺序,我们依次介绍

基于RSA的加密/解密示例C#代码

在C#程序中,大家可能比较熟悉的方式是md5加密解密方式,对RSA可能并不是很熟悉, 下面就说一下RSA加密和解密的算法: using System;using System.Security.Cryptography;using System.Text;class RSACSPSample{    static void Main()    {        try        {            string str_Plain_Text = "How are you?How are

浅谈webform开发时前台请求后台数据的方法

说到前台请求后台数据,我们一般都是用到AJAX(异步JavaScript和XML) .AJAX 通过在后台与服务器进行少量数据交换,AJAX 可以使网页实现异步更新.这意味着可以在不重新加载整个网页的情况下,我们可以对网页的某部分进行更新.在这里,主要浅谈一下在.net的webform开发时,前台请求后台的两种方式. 1.使用AjaxPro2.dll  (1)AjaxPro2.dll文件可以去网上下载,下载后引用到项目中. (2)引用到项目之后,在web.config里面的<system.web

[email&#160;protected]$http服务与后台数据交互

1.httpBasic.html: <!DOCTYPE HTML><html ng-app="app"><head>    <title>$http与后台数据交互</title>    <meta charset="utf-8">        <link rel="stylesheet" href="../css/bootstrap.css">

MUI框架-09-MUI 与后台数据交互

MUI框架-09-MUI 与后台数据交互 本篇介绍使用 art-template 和原生 MUI 的数据交互 mui.ajax 来实现 我们大家都知道,想要数据交互就要有数据,每次当我们发送请求,我们要清楚,怎么发,发给谁,返回的数据是什么内容,格式 先放一张图,给大家学习的动力: 然后今天呢,介绍的是调用 API,API 是什么呢,就是一个接口,比如知乎日报的API ,我们可以通过这个 API 获取到知乎上最新的消息,并且是 json 格式,我们就不用再去找数据了,其他类型 API 还有 百度

UMI学习-10 Dva 与后台数据交互

明天在线办公没时间学习了,今天晚上再更新一篇 代码提交一次:https://github.com/zhaogaojian/jgdemo 1.src下创建services目录 创建文件userSrv.ts export async function query(): Promise<any> { return request('user/getuserinfo'); } import axios from "axios" export default async functi