一、背景與目標
二、方案設計
對稱加密、非對稱加密、哈希演算法、驗簽演算法
HTTPS原理概述
微信支付加解密原理
介面加解密設計思路
三、技術實作
四、常見問題
五、安全性分析
一、背景與目標
隨著網路技術的快速發展,數據安全問題日益突出。為了防止爬蟲、防請求篡改、防請求重放,以及驗證數據完整性,本方案結合HTTPS原理和微信支付加解密設計,透過對稱加密、非對稱加密、簽名等技術,為API介面提供加解密設計和落地。
二、方案設計
對稱加密、非對稱加密、哈希演算法、驗簽演算法
對稱加密: 采用相同的金鑰進行加密和解密。具有加密速度快、計算量小的優點,但金鑰的安全傳輸是問題。在本方案中,對稱加密主要用於數據的實際加密傳輸。
非對稱加密: 使用一對金鑰(公鑰和私鑰)進行加密和解密。公鑰用於加密數據,私鑰用於解密數據。非對稱加密可以確保金鑰的安全傳輸,但加密速度較慢,不適合長文本加密。在本方案中,非對稱加密主要用於對稱金鑰的加密。
哈希演算法: 無論使用者輸入什麽長度的原始數據,經過計算後輸出的密文都是固定長度的,只要原數據稍有改變,輸出的「摘要」便完全不同
簽名演算法: 一般指的是,透過私鑰對數據進行簽名,然後透過公鑰對數據進行驗簽
HTTPS原理概述
HTTPS(
Hypertext Transfer Protocol Secure
)是一種透過電腦網路進行安全通訊的傳輸協定。它利用SSL/TLS協定在HTTP套用層進行通訊加密,透過證書進行身份驗證,從而確保數據傳輸的安全性和完整性。
微信支付加解密原理
請求簽名: 透過商戶API證書私鑰,對每一次請求進行RSA-SHA256簽名,微信支付進行驗簽
回呼驗簽: 微信支付透過平台證書私鑰,對每一次回呼進行RSA-SHA256簽名,商戶接收到請求後,透過平台正式公鑰進行驗簽
回呼解密: 商戶根據配置的apiV3金鑰,對加密數據進行AES-256-GCM解密
介面加解密設計思路
金鑰交換: 客戶端使用伺服端的公鑰對對稱加密的金鑰進行加密,然後將密文金鑰發送給伺服端。伺服端使用自己的私鑰解密得到對稱加密的明文金鑰。
數據加密: 客戶端使用對稱加密的明文金鑰對介面數據進行加密,然後發送給伺服端。伺服端使用相同的對稱加密金鑰對數據進行解密。
數據哈希(簽名): 在數據發送前,客戶端計算數據的哈希值,並將哈希值作為數據的一部份發送給伺服端。伺服端收到數據後,使用相同的演算法計算哈希值,並與客戶端發送的哈希值進行比較,以驗證數據的完整性。
數據有效性校驗: 在數據發送前,客戶端將當前時間作為數據的一部份發送給伺服端。伺服端收到數據後,解密得到參數中的時間,並與伺服端當前時間進行比較,以驗證請求是否過期,防止請求重放。
三、技術實作
1、金鑰生成與管理:
透過工具生成非對稱金鑰對,伺服端負責保管私鑰。(客戶端也可以定期從伺服端獲取公鑰(傳輸過程中有泄露的風險),並保存到LocalStorage。)
2、加密演算法選擇:
對稱加密演算法可選用常用的AES,非對稱加密演算法可選用常用的RSA。哈希演算法可選用SHA-256、MD5,簽名演算法可選用RSA-SHA256等。根據Hutool加密演算法如下:
// 對稱金鑰
String key = "key";
AES aes = SecureUtil.aes(key.getBytes());
// 加密
String ciphertext = aes.encryptBase64(content);
// 解密
String result = aes.decryptStr(ciphertext);
// 非對稱公鑰
String publicKey = "xxxxxxx";
// 對稱金鑰
String key = "key";
RSA rsa = new RSA(null, publicKey);
// 對對稱金鑰進行加密
String ciphertextKey = rsa.encryptBase64(key, KeyType.PublicKey);
// 非對稱私鑰
String privateKey = "xxxxxxx";
RSA rsa2 = new RSA(privateKey, null);
// 對加密的對稱金鑰進行解密
String key = rsa2.encryptBase64(ciphertextKey, KeyType.PrivateKey);
String data = "測試";
Digester sha256 = new Digester(DigestAlgorithm.SHA256);
System.out.println(sha256.digestHex(data));
// 暫不考慮
String publicKey = "xxxxx";
String privateKey = "xxxxx";
String data = "測試";
Sign privateSign = SecureUtil.sign(SignAlgorithm.SHA256withRSA, privateKey, null);
String sign = new String(Base64.getEncoder().encode(privateSign.sign(data)));
System.out.println("簽名:" + sign);
Sign publicSign = SecureUtil.sign(SignAlgorithm.SHA256withRSA, null, publicKey);
System.out.println(publicSign.verify(data.getBytes(), Base64.getDecoder().decode(sign.getBytes())));
3、簽名規則:
等queryString和body參數加密後,將queryString、時間戳、明文對稱金鑰、body參數按順序進行拼接,然後透過SHA256演算法進行哈希得到簽名sign,然後將sign放在header中進行傳遞
4、參數傳遞:
ek(encryt-key): xxxxxxx(非對稱加密後的對稱金鑰)
ts: xxxxxxx(時間戳)
sign: xxxxxxx
將請求參數
queryString
拼成"
param1=value1¶m2=value2
"格式
將
queryString
進行對稱加密,得到"
ciphertext=xxxxx
",並重新拼接到url後面
query參數可以參考GET請求
body參數可以透過對稱加密得到base64密文,直接用body進行傳輸
例如:
url?ciphertext=xxxxx
body:xxxxxxxx
5、後端處理:
請求有效驗證: 獲取header中ts參數,得到時間戳並判斷時間戳是否超過一定時間;
解密對稱金鑰: 透過私鑰解密header中的ek參數,得到明文的對稱金鑰key;
驗簽: 將queryString、時間戳、明文對稱金鑰、body參數按順序進行拼接,然後透過SHA256演算法進行哈希得到簽名sign,與header中的sign做比較;
解密參數: 透過明文對稱金鑰,分別解密queryString、body參數;
加密響應結果: 請求完成後,將響應結果透過對稱加密得到base64密文,並返回給客戶端
四、常見問題
Q:為什麽需要參考HTTPS來設計介面加解密?
A:HTTPS結合了對稱加密和非對稱加密,安全性更高,同時也能滿足效率要求
Q:如果只使用對稱加密有什麽問題?
A:客戶端是不安全的,很容易暴露金鑰,只要一旦暴露,加密就形同虛設
Q:如果只使用非對稱加密有什麽問題?
A:
非對稱加密不支持超長文本加密(RSA只支持117字節);
非對稱加密效率太慢
Q:介面參數已經加密了,是否還有必要簽名?
A:有必要,生產環境不是每一個介面都需要加密的。但是每一個介面都需要防篡改、防重放
Q:簽名演算法為什麽沒有采用RSA-SHA256?
A:
RSA-SHA256簽名演算法只能私鑰簽名,公鑰驗簽。
客戶端存的是公鑰,如果要采用該演算法,需要再定義一套非對稱金鑰,加重了維護成本。
現在采用哈希演算法SHA256進行模擬簽名,其中混入了明文的對稱金鑰,也可以防止模擬簽名
Q:用了對稱和非對稱混合加密,非對稱公鑰保存在客戶端,還是有可能泄露,怎麽保證安全?
A:
前端程式碼壓縮、混淆;
公鑰不要直接寫到程式碼裏,分段、加密保存;
即使公鑰暴露了,對稱金鑰每次都是新生成的,抓包也拿不到本次請求的對稱金鑰,也就沒有辦法對結果解密
Q:對稱和非對稱同時使用的話,怎麽保證加解密的效率?
A:請求參數和響應結果實際還是透過對稱加密,非對稱只會對對稱金鑰進行加解密,所以效率和對稱加密差不多4
Q:該方案是否是絕對安全?如果不是,是否有絕對安全的加解密方案?
A:
不是,如果客戶端被破解了,使用者可以模擬客戶端發起請求
暫時沒有,客戶端對於互聯網都是透明的,只要客戶端被破解了,都可以模擬客戶端發起請求
五、安全性分析
本方案結合對稱加密和非對稱加密的優點,既保證了數據傳輸的安全性,又提高了加密解密的效率。但是需要考慮客戶端公鑰的安全性。
防篡改: 請求參數都進行了簽名,只要客戶端公鑰不泄露,無法修改請求參數;
防爬蟲: 請求參數進行了簽名和加密,無法模擬客戶端請求;響應結果進行了加密,即使抓包拿到了結果,也無法進行解密
防重放: 請求頭中引入時間戳,並且時間戳也進行了驗簽,可以防止篡改,每次伺服端接收到請求都會驗證時間戳的有效性。(短時間內的重放暫時阻止不了,可以考慮在後端在緩存進行驗證,但目前業務用不上)
如喜歡本文,請點選右上角,把文章分享到朋友圈
如有想了解學習的技術點,請留言給若飛安排分享
因公眾號更改推播規則,請點「在看」並加「星標」 第一時間獲取精彩技術分享
·END·
相關閱讀:
作者:Jason22
來源:https://juejin.cn/post/7358368402795692082
版權申明:內容來源網路,僅供學習研究,版權歸原創者所有。如有侵權煩請告知,我們會立即刪除並表示歉意。謝謝!
架構師
我們都是架構師!
關註 架構師(JiaGouX),添加「星標」
獲取每天技術幹貨,一起成為牛逼架構師
技術群請 加若飛: 1321113940 進架構師群
投稿、合作、版權等信箱: [email protected]