前后端分离,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协议进行通信等。

相关推荐
吾日三省吾码7 分钟前
JVM 性能调优
java
stm 学习ing12 分钟前
FPGA 第十讲 避免latch的产生
c语言·开发语言·单片机·嵌入式硬件·fpga开发·fpga
湫ccc1 小时前
《Python基础》之字符串格式化输出
开发语言·python
弗拉唐1 小时前
springBoot,mp,ssm整合案例
java·spring boot·mybatis
oi772 小时前
使用itextpdf进行pdf模版填充中文文本时部分字不显示问题
java·服务器
mqiqe2 小时前
Python MySQL通过Binlog 获取变更记录 恢复数据
开发语言·python·mysql
AttackingLin2 小时前
2024强网杯--babyheap house of apple2解法
linux·开发语言·python
少说多做3432 小时前
Android 不同情况下使用 runOnUiThread
android·java