前后端分离,RSA加密传输方案

1.原理

RSA是一种非对称加密算法。通过生成密钥对,用公钥加密,用私钥解密。对于前后端分离的项目,让前端获取到公钥对敏感数据加密,发送到后端,后端用私钥对加密后的数据进行解密即可。

2.实现

RSA工具类:提供秘钥对生成、公钥获取、私钥解密的方法。

java 复制代码
public class RSAUtil {
    
   private final static Logger logger = LoggerFactory.getLogger(RSAUtil.class);
   
   private static final String RSA = "RSA";  
   private static final int KEY_SIZE = 2048; 

   private static ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); 
   // Bouncy Castle加密库提供的一个类,用于为Java提供加密服务
   private static final BouncyCastleProvider BOUNCY_CASTLE_PROVIDER = new BouncyCastleProvider();
   
   // 密钥对生成
   static void createKey() throws Exception{
      KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(RSA, BOUNCY_CASTLE_PROVIDER);
      keyPairGenerator.initialize(KEY_SIZE, new SecureRandom());
      ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
      objectOutputStream.writeObject(keyPairGenerator.generateKeyPair());
      objectOutputStream.close();
   }
   
   // 公钥获取
   public static RSAPublicKey getPublicKey() throws Exception{
      return (RSAPublicKey) getKeyPair().getPublic();
   }
   
   // 读取,有密钥对则获取公钥,无密钥对则创建密钥对再获取公钥
   static KeyPair getKeyPair()throws Exception{
      if(byteArrayOutputStream.size() == 0){
         synchronized (byteArrayOutputStream) {
            createKey();
         }
      }
      ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());  
      ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream);  
      KeyPair keyPair= (KeyPair) objectInputStream.readObject();  
      objectInputStream.close();  
      byteArrayInputStream.close();  
      return keyPair;  
    }
    
   static byte[] decryptByPrivateKey(byte[] encrypttext){
        try {
            Cipher ci = Cipher.getInstance(RSA, BOUNCY_CASTLE_PROVIDER);
            ci.init(Cipher.DECRYPT_MODE, getKeyPair().getPrivate());
            return ci.doFinal(encrypttext);
        }  catch (Exception e) {
         logger.error(e.getMessage(), e);
        }
        return null;
    }
    
   // 接收一个String类型,私钥解密
   public static String decodeString(String string){
        try {  
            byte[] input = Base64.getDecoder().decode(string); // 解码Base64字符串为字节数组  
            byte[] raw = decryptByPrivateKey(input); // 使用私钥解密数据  
            return new String(raw, StandardCharsets.UTF_8); // 直接将字节数组转换为UTF-8字符串  
        } catch (Exception e) {  
            logger.error("解析失败", e);  
            return "";  
        }
   } 
   
}

为前端提供一个获取公钥的接口

java 复制代码
@GetMapping("getRSAPublickey")
public Result<?> getRSAPublickey() {
    Map key = new HashMap();
    try {
        // 通过提供模数和公共指数,可以间接地提供公钥,同时保持安全性。
        String modulus = RSAUtil.getPublicKey().getModulus().toString(16);
        String publicExponent = RSAUtil.getPublicKey().getPublicExponent().toString(16);
        key.put("m", modulus);
        key.put("e", publicExponent);
    } catch (Exception e) {
    }
    return Result.ok(key);
}

前端需要导入一个适合前端使用的RSA加密库。利用获取到的模数和公共指数创建RSA公钥对象,对敏感数据加密。

html 复制代码
<html>
  <script src="rsa.js"></script>
  <body>
    <script>
      window.encryptStr = function (m, e, str) {
        var rsa = new RSAKey()
        rsa.setPublic(m, e)
        return rsa.encrypt(str)
      }
    </script>
  </body>
</html>

后端接收到前端利用RSA加密后的字符串后,直接调用RSAUtil进行解密,得到原文。

java 复制代码
String password = RSAUtil.decodeString(pram.getPassword());

需要注意的是,前端加密只是数据传输过程中的一部分安全措施。为了确保数据的安全性,还需要在后端服务器进行相应的安全措施,例如验证用户身份、使用HTTPS协议进行通信等。

相关推荐
怀旧诚子15 分钟前
timeshift之Fedora43设置,已在VM虚拟机验证,待真机验证。
java·服务器·数据库
1104.北光c°20 分钟前
滑动窗口HotKey探测机制:让你的缓存TTL更智能
java·开发语言·笔记·程序人生·算法·滑动窗口·hotkey
for_ever_love__1 小时前
Objective-C学习 NSSet 和 NSMutableSet 功能详解
开发语言·学习·ios·objective-c
云原生指北3 小时前
GitHub Copilot SDK 入门:五分钟构建你的第一个 AI Agent
java
似水明俊德7 小时前
02-C#.Net-反射-面试题
开发语言·面试·职场和发展·c#·.net
Leinwin7 小时前
OpenClaw 多 Agent 协作框架的并发限制与企业化规避方案痛点直击
java·运维·数据库
薛定谔的悦8 小时前
MQTT通信协议业务层实现的完整开发流程
java·后端·mqtt·struts
enjoy嚣士8 小时前
springboot之Exel工具类
java·spring boot·后端·easyexcel·excel工具类
Thera7778 小时前
C++ 高性能时间轮定时器:从单例设计到 Linux timerfd 深度优化
linux·开发语言·c++
罗超驿8 小时前
独立实现双向链表_LinkedList
java·数据结构·链表·linkedlist