实现前后端分离:RSA加密传输方案的详解

目录

1.原理

2.实现


1.原理

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

2.实现

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

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

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

@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>
  <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进行解密,得到原文。

String password = RSAUtil.decodeString(pram.getPassword());

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

  • 45
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值