栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Spring Boot使用RSA模拟简单的登录加密功能

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Spring Boot使用RSA模拟简单的登录加密功能

Spring Boot使用RSA模拟简单的登录加密功能
  • 什么是RSA?
  • RSA加密和解密的过程
  • RSA加密和解密的实现
  • 模拟简单登录加密功能

什么是RSA?

RSA是一种公钥密码算法,它的名字由三位开发者,即Ron Rivest、Adi Shamir和Leonard Adleman的姓氏的首字母组成的。

RSA被用于公钥密码和数字签名。

RSA被认为是非常安全的,不过计算速度要比DES慢很多。同DES一样,其安全性也从未被证明过,但想攻破RSA算法涉及的大数(至少200位的大数)的因子分解是一个极其困难的问题。所以,由于缺乏解决大数的因子分解的有效方法,因此,可以推测出目前没有有效的办法可以破解RSA。

RSA加密和解密的过程


通过一对密钥(公钥和私钥)实现的加密和解密,通过公钥对明文进行加密,使用时再使用私钥进行解密即可。

RSA加密和解密的实现

编写一个工具类,实现方法:创建公钥和私钥、通过公钥加密、通过私钥解密。

package cn.qhj.backtoweb.util;


import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.tomcat.util.codec.binary.base64;

import javax.crypto.Cipher;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
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;


public class RSAUtils {
    protected static final Log log = LogFactory.getLog(RSAUtils.class);
    // 加密的方式
    private static String KEY_RSA_TYPE = "RSA";
    // 转换 算法/反馈模式/填充方案    RSA/ECB/PKCS1Padding (1024, 2048)
    // 加密算法有:AES,DES,DESede(DES3)和RSA 四种
    // 模式有CBC(有向量模式)和ECB(无向量模式),向量模式可以简单理解为偏移量,使用CBC模式需要定义一个IvParameterSpec对象
    private static String KEY_RSA_TYPE_ALL = "RSA/ECB/PKCS1Padding";
    // JDK方式 RSA加密最大只有 1024位
    private static int KEY_SIZE = 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";

    
    public static Map createRSAKeys(){
        // 用来存放公钥和私钥的 base64位加密
        Map keyPairMap = new HashMap();
        try {
            // 生成公钥和私钥对——给予 RSA算法生成对象
            KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(KEY_RSA_TYPE);
            // 使用给定的随机源(以及默认参数集)初始化特定密钥大小的密钥对生成器
            keyPairGenerator.initialize(KEY_SIZE, new SecureRandom());

            // 生成密钥对
            KeyPair keyPair = keyPairGenerator.generateKeyPair();
            // 返回对此密钥对的公钥组件的引用
            RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
            // 返回对此密钥对的私钥组件的引用
            RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();

            // 得到公钥字符串和秘钥字符串
            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;
    }


    
    public static String encryptByPublicKey(String str, String publicKey){
        // base64 编码的公钥
        byte[] publicBytes = base64.decodebase64(publicKey);
        // 公钥加密——按照X509标准对其进行编码的密钥 复制数组的内容,以防随后进行修改。
        X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(publicBytes);
        // 已经加密过的数据
        List encodedDataList = new linkedList();

        // 最大加密长度 1024/8/8 - 11
        int maxEncodeSize = ENCODE_PART_SIZE - 11;
        // 所有加密的数据
        String encodebase64Result = null;
        try {
            // 密钥工厂——用于将密钥(Key类型的不透明加密密钥)转换成密钥规范(底层密钥材料的透明表示)
            KeyFactory keyFactory = KeyFactory.getInstance(KEY_RSA_TYPE);
            // 根据提供的密钥规范(密钥材料)生成公钥对象
            PublicKey publicKeys = keyFactory.generatePublic(x509EncodedKeySpec);
            // 为加密和解密提供密码功能(所传递的参数:转换)
            Cipher cipher = Cipher.getInstance(KEY_RSA_TYPE_ALL);
            // 用密钥初始化此Cipher    ENCRYPT_MODE:用于将 Cipher初始化为解密模式的常量
            cipher.init(Cipher.ENCRYPT_MODE, publicKeys);

            byte[] strBytes = str.getBytes("utf-8");
            // 获取所有被加密数据长度
            int strLen = strBytes.length;
            // 如果明文长度大于 模长-11 则要分组加密
            for (int i = 0;i < strLen;i += maxEncodeSize){
                int curPosition = strLen - i;
                int tempLen = curPosition;
                if (curPosition > maxEncodeSize){
                    tempLen = maxEncodeSize;
                }
                // 待加密分段数据
                byte[] tempBytes = new byte[tempLen];
                System.arraycopy(strBytes, i, tempBytes, 0, tempLen);
                byte[] tempEncodedData = cipher.doFinal(tempBytes);
                encodedDataList.add(tempEncodedData);
            }

            // 加密次数
            int partLen = encodedDataList.size();
            // 所有加密的长度
            int allEncodedLen = partLen * ENCODE_PART_SIZE;
            // 存放所有 RSA分段加密数据
            byte[] encodeData = new byte[allEncodedLen];
            for (int i = 0;i < partLen;i++){
                byte[] tempByteList = encodedDataList.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;
    }


    
    public static String decryptByPrivateKey(String str, String privateKey){
        byte[] privateBytes = base64.decodebase64(privateKey);
        byte[] encodeStr= base64.decodebase64(str);

        // 要解密的数据长度
        int encodePartLen = encodeStr.length / ENCODE_PART_SIZE;
        List decodeListData = new linkedList();
        // 所有解密的数据
        String decodeStrResult = null;

        // 私钥解密
        PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(privateBytes);
        try {
            // 密钥工厂——用于将密钥(Key类型的不透明加密密钥)转换成密钥规范(底层密钥材料的透明表示)
            KeyFactory keyFactory = KeyFactory.getInstance(KEY_RSA_TYPE);
            // 根据提供的密钥规范(密钥材料)生成私钥对象
            PrivateKey privateKeys = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
            // 为加密和解密提供密码功能(所传递的参数:转换)
            Cipher cipher = Cipher.getInstance(KEY_RSA_TYPE_ALL);
            // 用密钥初始化此Cipher    ENCRYPT_MODE:用于将 Cipher初始化为解密模式的常量
            cipher.init(Cipher.DECRYPT_MODE, privateKeys);

            // 初始化所有被解密数据长度
            int allDecodeByteLen = 0;
            for (int i = 0;i < encodePartLen;i++){
                // 待解密数据分段
                byte[] tempEncodedData = new byte[ENCODE_PART_SIZE];
                System.arraycopy(encodeStr, 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[] tempStrBytes = decodeListData.get(i);
                int tempStrBytesLen = tempStrBytes.length;
                System.arraycopy(tempStrBytes, 0, decodeResultBytes, curPosition, tempStrBytesLen);
                curPosition += tempStrBytesLen;
            }
            decodeStrResult = new String(decodeResultBytes, "UTF-8");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return decodeStrResult;
    }
}
模拟简单登录加密功能
  • 编写控制层

    @Controller
    public class LoginController {
        
        @RequestMapping(value = "/login")
        public String login(HttpServletRequest request, HttpServletResponse response) throws IOException {
            Map rsaKeys = RSAUtils.createRSAKeys();
            String publicKey = rsaKeys.get(RSAUtils.PUBLIC_KEY_NAME);
            System.out.println("publicKey:" + publicKey);
            String privateKey = rsaKeys.get(RSAUtils.PRIVATE_KEY_NAME);
            System.out.println("privateKey:" + privateKey);
    
            // 存入session
            HttpSession session = request.getSession();
            session.setAttribute("publicKey", publicKey);
            session.setAttribute("privateKey", privateKey);
            return "redirect:/toIndex";
        }
    
    	
    	@RequestMapping(value = "/toIndex")
        public String toIndex(){
            return "index";
        }
    
        
        @ResponseBody
        @RequestMapping(value = "/doLogin", method = RequestMethod.POST)
        public String doLogin(String username, String password, HttpServletRequest request) {
            // 获取 session中的 privateKey
            String privateKey = (String) request.getSession().getAttribute("privateKey");
    
            String decryptPwd = RSAUtils.decryptByPrivateKey(password, privateKey);
            if ("zhangsan123".equals(decryptPwd)){
                return "登录成功!";
            }
            return "登录失败!";
        }
    
    }
    
  • 编写简单页面

    
    
    
        
        模拟登录
    
    
    
    用户名:
    密码:
  • 测试登录

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/630817.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号