摘要:很明顯,非對稱加密的極大的消耗成了一種瓶頸。其中,利用非對稱加密的方案大概就是我前面說的那樣,偽代碼已經展示過了。
其實,前面兩篇翻來覆去只為叨逼叨叨逼叨兩件事情:
對稱加解密,典型算法有AES、DES、3DES等等
非對稱加解密,典型的算法有RSA、DSA、ECDH等等
但是,我知道大家最討厭在看這種文章的時候冒出來的一坨“橢圓曲線”、“素數”、“質數”等等這樣的玩意,反正看也看不懂,理解也理解不了,背也背不過,所以我索性就不寫這些玩意,一點兒都不寫,不裝任何逼(然而實際上我背過了,我最近一直在搞線性代數,所以對數學比原來稍微敏感了一些)。
寫到這里后,就有刁民、php泥腿子自以為已經掌握了高科技,隨便從github上扒兩個庫下來跑了跑test就開始四處裝逼,聲稱自己精通對稱加密算法和非對稱加密算法,尤其是在面試的時候,上去就是跟面試官一頓糊弄,糊弄住了就要5萬,糊弄不了要5千。然而我要告訴你的是,你應該接繼續往下看,這樣的話你在面試的時候,糊弄住了就可以張口要8萬,糊弄不了也能最低要8千!比原來要5000整整多了3000!而且我提供的這份裝逼指南還是免費的!
今天我們從一個實際需求作為出發點,比如你是API開發人員(當然了,作為只有十來個人的小公司,你還得兼職運維,不過工資只按開發算,運維的活兒算是你友情贊助給老板的),然后老板兼PM向你提出了一個比較嚴峻的問題,大概意思就是“公司的項目是個非常牛逼的項目,一年后公司是要上市的,你必須要加密了數據,讓BAT和TMD都無法抄襲我們!然后你就能買車買房!”,你表示十分認可。由于你已經看過了我前面兩篇文章,再加上老板一再強調“我們這個是牛逼的項目,遲早要上市”,所以你就準備用高安全性的非對稱加密來解決這個問題。
具體做法就是服務器生成一對公私鑰,然后再生成一對公私鑰給所有客戶端公用。比如用戶登陸API,接口文檔大概如下:
API : https://www.so.com/api/user/login METHOD : POST PROTOCOL : 將數據以JSON形式,全部放入到http body體中,key叫做mzip DATA : { "username" => "xitele", "password" => "qiangdadaoniyongyuancaibuchulaishiduoshao" }
然后客戶端執行登陸的偽代碼如下:
var username string = "xitele" var password string = md5("123456") // 將數據生成json var data = jsonize( hashMap( "username" : username, "password" : password ) ) // 用服務器公鑰,將數據加密 var encryptData = RSA.encrypt( "服務端的公鑰", data ) // 再次封裝數據為json var lastJson = jsonize( hashMap( "mzip" => encryptData ) ) // 提交數據 http.post( "https://www.so.com/api/user/login", lastJson, function() { // ... ... do something ... } )
服務器端使用世界上最好的語言來實現的,所以代碼你會覺得十分眼熟:
prepare( "select * from user where username=:username" ); $sth->bindParam( ":username", $aDecryptData["username"], PARAM_STR ); $pdo->execute(); $aUser = $pdo->fetch(); if ( $aUser["password"] != $aDecryptData["password"] ) { echo json_encode( array( "code" => 0, "msg" => "登陸成功" ) ); } else { echo json_encode( array( "code" => 10002, "msg" => "登陸失敗" ) ); }
上線后,發現倒也沒啥大問題了,就是明顯服務器CPU負載特別高,客戶端也感覺有點兒卡。很明顯,非對稱加密的CPU極大的消耗成了一種瓶頸。于是你找老板申請服務區費用,老板當場表示非常理解,大手一揮就給你批了300塊錢并表示隨意揮霍,把服務器升級成最牛逼的服務器。
當然了,都跟我學習了這么久了你應該馬上就意味到300塊代表著什么,300塊頂多代表能組兩個局兒... ...
當然了,API那里也好交代,全線降級為AES對稱,CPU瞬間就下來了,又不是不能用.. ...
當然了,300塊組個五人局兒應該還是可以的,除了你和我,再拉上柱子跟老趙,最后再帶上陳旭,局兒上除了吃飯,就額外討論一下關于這個問題的解決方案。
局兒后,我神神秘秘地告訴你說“這特么簡單,我給你講,你服務器先隨機生成一個AES對稱加密用的密鑰,然后利用客戶端的RSA公鑰加密后傳給客戶端,客戶端再通過自己的RSA私鑰解密得到這個AES對稱密鑰,然后再用這個AES對稱密鑰進行后續的加解密即可,然后你可以給這個AES密鑰設定一個有效期,比如五分鐘,當過期后,就再次利用上面的流程申請新的AES密鑰即可!這樣,不僅保證了AES密鑰的安全,還能解決了性能問題!”
鋪墊這么長,終于能扯出來今天的討論關鍵點了:密鑰協商/交換!這就是我們今天的核心話題了。
先說下為什么會出現密鑰協商和交換這種玩意,其實就是為了避免密鑰在網絡上的傳輸被劫持導致的安全問題,前兩句話的潛臺詞就是“這個世界上存在著一種即便我不告訴你,你也能知道我想告訴你什么的心有靈犀解決方案”。
密鑰協商交換一般常用的有如下幾種方案:
利用RSA等非對稱加密技術進行交換,也就是300塊的局兒上那個方案
利用專門伺候密鑰交換需求的交換算法,比如DH算法,全稱叫做Diffie-Hellman密鑰交換。Diffie和Hellman分別是兩個大叔的名字(注意,此二位是數學家),是他們合伙搞出來的這個算法,DH算法先于RSA出現。
其中,利用非對稱加密的方案大概就是我前面說的那樣,偽代碼已經展示過了。那么DH到底是個什么玩意呢?
下面我們玩一個比較簡單的數字游戲:
1、元首和古德里安都同時選擇100這個數字,其他人知不知道無所謂 2、元首隨機出了一個數字9,然后將9乘以數字100,得到900,其他人能不能知道無所謂 3、古德里安隨機出了一個數3,然后將3乘以數字100,得到300,其他人能不能知道無所謂 4、元首將900扔給古德里安 5、古德里安將300扔給元首 到這里后,元首手里有的數據有100、9、300,古德里安手里的數據有100、3、900,然后兩個人此時只需要默默地做下面這一步: 元首:9 * 300 = 2700 古德里安:3 * 900 = 2700 OK了,就2700了
雙方都在僅僅是遠遠地確認了一下眼神,說了一句話(彼此交換300和900),就已經同時得到2700這個相同的數字。辣么,2700就是雙方后面進行通信時候對數據進行加密的密鑰了。同樣,雙方可以為這個密鑰算一個過期時間,比如五分鐘后,然后過期后重新協商出一個新的即可!而且,即便有其他人知道了雙方選擇的是100,也知道了元首給古德里安傳了900,也知道了古德里安給元首穿了300,然而并沒有什么卵用,因為他還是不知道對方最終使用的密鑰(也就是2700)是多少。
當然了,現實中真正的DH算法選擇公共數字、隨機數字可不是這么簡單的,而且雙方最終計算這個密鑰的時候也不會像上面那個例子中那么輕松簡單做一下乘法而已。
具體人家怎么算得,我就不寫了,反正網上到處都有,而且無論我寫出來還是不寫出來,反正你們都不看,畢竟,這玩意是數學家要搞的玩意。
RSA的庫前面我從github上扒過,也test過了,所以RSA就不演示了。然而,DH的咱們一起從github上扒一個下來玩玩來驗證一下我們剛才講的簡單理論。
PHP的一個DH庫,GITHUB鏈接:https://github.com/jcink/diff...
將上述代碼保存為index.php,然后php index.php 32執行一下,結果如下,你們感受一下:
我們看到這個庫順帶打印了一坨log,作為從來不研究底層的廣大泥腿子來說,我們只需要關注最后一行“Shared Key : 101451040”,這個就是服務端和客戶端協商出來的密鑰了,也就是意味著后面API的通信過程中使用101451040對數據加解密即可。
好了,以上是DH算法。其實,圈里那些仁兄在看到今天標題中含有DH的時候心里就應該有數了,這傻逼天天在微信群里安利ECDH,今兒特么終于看到DH兩個字母了,總算有點兒眉毛了。辣么,我天天在群里安利的ECDH到底是什么玩意。
具體原理怎么回事,反正我這次是真是連背都背不過了,不過,你可以簡單認為ECDH是DH的升級版本,畢竟多了兩個字母。其實ECDH是ECC算法和DH算法二合一體,媽蛋,又特么冒出來一個ECC,好了好了,就當我沒說。
然后還是老套路,我們從github上扒一個庫下來簡單跑一下test,這樣以后就可以出去裝逼要8萬工資了,傳送門:https://github.com/Querdos/EC...
computeSecret( $gudelian->getPublic() ); $gudelian->computeSecret( $xitele->getPublic() ); // shareKey1 和 shareKey2 就是協商出來的密鑰 $shareKey1 = $xitele->getSecret(); echo $shareKey1.PHP_EOL; $shareKey2 = $gudelian->getSecret(); echo $shareKey2.PHP_EOL; // 我們用gmp cmp來對比是否為同一個密鑰 if ( 0 == gmp_cmp( $shareKey1, $shareKey2 ) ) { echo "一樣".PHP_EOL; } else { echo "不一樣".PHP_EOL; } // 除此之外,這個ecdh庫比dh那個庫多了一個驗證數據簽名驗證,可以檢驗數據是否被篡改! $msg = "hello world"; $signature = $xitele->signMessage( $msg ); if ( $gudelian->verifySignature( $signature, $xitele->getPublic(), $msg ) ) { echo "驗證數據簽名成功".PHP_EOL; } else { echo "驗證數據簽名失敗".PHP_EOL; } exit;將代碼保存為index.php,然后php index.php執行結果如下圖所示:
通過上面代碼我們可以看出來,可以直接背誦一個結論,就是DH和ECDH都可以實現密鑰協商交換,但是ECDH還可以對數據進行簽名,另一方可以對數據進行驗簽,從而可以判斷出數據在傳輸過程中是否被篡改!
好了,念念已久的ECDH終于入講了!以后我不會再在群里再叨叨這個了,祝你們幸福。
最近開了一個微信公眾號:高性能API社區,所有文章都先發這里
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/31422.html
摘要:這種神奇的算法可以讓你服務器和客戶端在不傳輸該對稱密鑰的情況下就可以通過心有靈犀地方式各自計算出一個對稱密鑰,而且可以一樣,避免了該密鑰在網絡上流通,而且你可以隨意更換,過期時間定為分鐘,可謂是狠毒至極我們引入就是為了解決上面的問題。 首先是前段時間我在公眾號里被人批(dui)評(gang)了,大概意思就是:你別老整那ECDH又是橢圓又是素數啥的,你就說這玩意實際項目中怎么用就完了,我...
摘要:這種神奇的算法可以讓你服務器和客戶端在不傳輸該對稱密鑰的情況下就可以通過心有靈犀地方式各自計算出一個對稱密鑰,而且可以一樣,避免了該密鑰在網絡上流通,而且你可以隨意更換,過期時間定為分鐘,可謂是狠毒至極我們引入就是為了解決上面的問題。 首先是前段時間我在公眾號里被人批(dui)評(gang)了,大概意思就是:你別老整那ECDH又是橢圓又是素數啥的,你就說這玩意實際項目中怎么用就完了,我...
摘要:由于密鑰被暴露了,所以必須換新的密鑰,元首這會兒只能走途徑告訴古德里安新的密鑰,這會兒逗逼的事情來了,如何對密鑰進行加密。但是,有一點是值得說明,那就是無論是對稱加密還是非對稱加密,都頂不住用機器是強行暴力猜解私鑰。 懶漢 入門 這兩點就足以說明這篇文章不想要著有什么高端大氣的技術內容,我跟你講,全是水。不可能有什么質數素數、橢圓曲線加密、迪菲-赫爾曼什么的,不可能有的。 首先我不...
摘要:實際上這一篇和上一篇均可以看作是關于加解密的懶漢入門篇安全加強篇一的后續,只不過側重點在于安全上。回到上篇結果提到的問題,就是對稱加密的安全性要人命,非對稱加密的性能非常要人命。元首作為高智商罪犯,這種低級錯誤是不可能犯的。 為什么標題總是要帶上API安全關鍵字呢?因為我想我樂意。 實際上這一篇和上一篇均可以看作是《關于PHP加解密的懶漢入門篇(API安全加強篇一)》》)的后續,只不過...
摘要:實際上這一篇和上一篇均可以看作是關于加解密的懶漢入門篇安全加強篇一的后續,只不過側重點在于安全上。回到上篇結果提到的問題,就是對稱加密的安全性要人命,非對稱加密的性能非常要人命。元首作為高智商罪犯,這種低級錯誤是不可能犯的。 為什么標題總是要帶上API安全關鍵字呢?因為我想我樂意。 實際上這一篇和上一篇均可以看作是《關于PHP加解密的懶漢入門篇(API安全加強篇一)》》)的后續,只不過...
閱讀 486·2019-08-30 15:44
閱讀 901·2019-08-30 10:55
閱讀 2731·2019-08-29 15:16
閱讀 930·2019-08-29 13:17
閱讀 2804·2019-08-26 13:27
閱讀 572·2019-08-26 11:53
閱讀 2123·2019-08-23 18:31
閱讀 1890·2019-08-23 18:23