tft每日頭條

 > 科技

 > 非對稱加密算法怎麼用

非對稱加密算法怎麼用

科技 更新时间:2025-02-24 12:45:16

  背景 接口層做數據加密應該算是老生常談的一件事了,業界用的比較多的,不外乎是對稱加密,非對稱加密以及兩者的結合。

  對稱加密,比較有代表性的就是 AES,密鑰隻有一個,客戶端和服務端都要進行存儲,但是對客戶端來說,比較容易洩露,需要定期進行更換。

  非對稱加密,比較有代表性的就是 RSA,有公鑰和私鑰,正常是服務端生成,将私鑰保留在服務端,公鑰派發出去,然後是客戶端用公鑰進行加密,服務端用私鑰進行解密。相對于對稱加密來說,是安全了一些,但是加解密的速度會慢一些,如果要加密的内容還比較多,還要進行分段處理,比較麻煩。

  非對稱加密 對稱加密,這個應該是用的比較多的一種,做了一個折中處理,用 RSA 的公鑰加密 AES 的密鑰,然後用 AES 去加密請求數據。

  下面老黃就用幾個簡單的例子來演示一下非對稱加密這一塊。

  非對稱加密 這裡介紹的是純純的非對稱加密,還不是結合對稱加密的。

  這種情況,如果真的使用,一般是會在登錄接口,再細一點的話,就是密碼那個字段的加密。

  先來看看簡單的流程圖

  非對稱加密算法怎麼用(聊一聊非對稱加密在接口參數中的簡單實現)(1)

  後端接口處理 後端 API 接口需要提供兩個接口

  根據應用客戶端獲取公鑰(當然把公鑰寫死在客戶端代碼裡也是可以的)解密處理數據 獲取公鑰

  [HttpGet(req-pub)] public IActionResult ReqPub([FromQuery] string appId) { if(string.IsNullOrWhiteSpace(appId)) return BadRequest(invalid param // 模拟從數據庫或緩存中取數據 var publicKey = RSAKeyMapping.GetServerPublicKeyByAppId(appId); if(string.IsNullOrWhiteSpace(publicKey)) return BadRequest(invalid appId return Ok(new { data = publicKey }); }

  解密處理

  [HttpPost] public async TaskIActionResult Post([FromHeader] string appId) { if (string.IsNullOrWhiteSpace(appId)) return BadRequest(invalid appId // 這裡本可以用參數接受,不過有一些網站的登陸接口是直接傳密文 // 所以這裡也演示一下這種方式 var data = await new StreamReader(Request.Body).ReadToEndAsync(); if (string.IsNullOrWhiteSpace(data)) return BadRequest(invalid param // 模拟從數據庫或緩存中取數據 var rsaKey = RSAKeyMapping.GetByAppId(appId); if (rsaKey == null) return BadRequest(invalid appId // 解密,正常解密後會是一個 JSON 字符串,然後反序列化即可 var decData = EncryptProvider.RSADecrypt( rsaKey.ServerPrivateKey, Convert.FromBase64String(data), RSAEncryptionPadding.Pkcs1, true); return Ok($Hello, {System.Text.Encoding.UTF8.GetString(decData)} }

  前端頁面處理 前端用最原生的 HTML JavaScript 來演示,這裡需要用到 jsencryptcrypto-js

  大緻流程的話,打開頁面就從服務端獲取到公鑰,點擊按鈕,就會把文本框中的内容用公鑰去加密,然後調用服務端的解密接口。

  !DOCTYPE htmlhtml lang=head meta charset=UTF-8 meta http-equiv=X-UA-Compatible content=IE=edge meta name=viewport content=width=device-width, initial-scale=1.0 titleRSA sample/title script src=htt console.log(res) alert(res); }, error: function (e) { console.log(e) } }); } /script/headbody input type=text id=txtData button id=btnSubmitsubmit/button /body/html

  運行效果大緻如下:

  非對稱加密算法怎麼用(聊一聊非對稱加密在接口參數中的簡單實現)(2)

  非對稱加密算法怎麼用(聊一聊非對稱加密在接口參數中的簡單實現)(3)

  這個例子不算複雜,應該比較好理解。

  下面再來看看非對稱加密 對稱解密的方式。

  非對稱加密 對稱加密 這兩種加密結合的,網上其實很多例子,不過每個實現都會有一些細微的差别。

  這種相對來說,适用的場景就比較多了,基本都可以覆蓋。

  同樣看看簡單的流程圖,再看如何實現。

  非對稱加密算法怎麼用(聊一聊非對稱加密在接口參數中的簡單實現)(4)

  後端接口處理 後端 API 接口也是需要提供兩個接口,公鑰獲取和上面的是一樣的,變動的是解密這一塊,因為這裡還引入了 AES 。

  [HttpPost] public IActionResult Post([FromHeader] string appId, [FromBody] RequestDto dto) { if(string.IsNullOrWhiteSpace(appId)) return BadRequest(invalid appId // 這裡正常用實體接收,不從流讀取了 if (dto == null || string.IsNullOrWhiteSpace(dto.EP) || string.IsNullOrWhiteSpace(dto.EAK)) return BadRequest(invalid param // 模拟從數據庫或緩存中取數據 var rsaKey = RSAKeyMapping.GetByAppId(appId); if (rsaKey == null) return BadRequest(invalid appId // 解密客戶端傳過來的 AES 密鑰 var decAesKey = EncryptProvider.RSADecrypt( rsaKey.PrivateKey, Convert.FromBase64String(dto.EAK), RSAEncryptionPadding.Pkcs1, true); // 根據解密的密鑰,進行 AES 解密 var decData = EncryptProvider.AESDecrypt( dto.EP, System.Text.Encoding.UTF8.GetString(decAesKey)); return Ok($Hello, {decData} }

  前端頁面處理 前端這一塊其實變動也不會大,主要是多了一步 AES 密鑰的生成和 AES 的加密。

  $(function () { getPublicKeyFromServer(); $(#btnSubmit).click(function () { var encrypt = new JSEncrypt(); encrypt.setPublicKey(localStorage.getItem(spk // 随機生成 aes 的密鑰 var aesKey = getAesKey(); // 用公鑰去加密這個密鑰 var encAesKey = encrypt.encrypt(aesKey); // 用 aes 的密鑰去加密數據 var encData = aesEncrypt($(#txtData).val(), aesKey); sendBizReq(encData, encAesKey) }); }); function sendBizReq(data, aesKey) { $.ajax({ url: url /biz, type: post, // dataType: json, data: JSON.stringify({ ep: data, eak: aesKey }), headers: { appId: appId, Content-Typeapplication/json }, success: function (res) { console.log(res) alert(res); }, error: function (e) { console.log(e) } }); } function getAesKey() { var s = []; var hexDigits = 0123456789abcdef for (var i = 0; i i ) { s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1); } s[14] = s[19] = hexDigits.substr((s[19] & 0x3) | 0x8, 1); s[8] = s[13] = s[18] = s[23]; var uuid = s.join( return uuid; } function aesEncrypt(data, key) { var encryptedData = CryptoJS.AES.encrypt( CryptoJS.enc.Utf8.parse(data), CryptoJS.enc.Utf8.parse(key), { mode: CryptoJS.mode.ECB, padding: CryptoJS.pad.Pkcs7 }); return encryptedData.toString(); }

  非對稱加密算法怎麼用(聊一聊非對稱加密在接口參數中的簡單實現)(5)

  效果已經出來了。

  一些考慮 可能有朋友會問,前端生成的 AES 密鑰可信嗎?

  畢竟有流傳類似這樣一句話 任何客戶端傳過來的數據都是不能直接信任的

  有這種顧慮也算正常。

  這個時候就需要考慮服務端生成密鑰的方案了:

  生成其實是一件小事,傳輸是一件比較核心的事。

  首先考慮密鑰也是密文傳輸的,所以服務端和客戶端要同時擁有一對公鑰和私鑰。

  服務端在向客戶端傳輸密鑰時,要用客戶端的公鑰進行加密,然後客戶端用自己私鑰進行解密獲得,這樣才能保證密鑰的“安全性”。

  這種的話,交互邏輯會複雜一些。

  除了 RSA 算法,後面可能還要嘗試一下國密算法中的 SM2。

  ,

更多精彩资讯请关注tft每日頭條,我们将持续为您更新最新资讯!

查看全部

相关科技资讯推荐

热门科技资讯推荐

网友关注

Copyright 2023-2025 - www.tftnews.com All Rights Reserved