首先是前段時間我在公衆號裏被人批(dui)評(gang)了,大概意思就是:你別老整那ECDH又是橢圓又是素數啥的,你就說這玩意實際項目中怎麼用就完了,咱們不想聽那些,那些咱們都懂都精通,並且你還太監了,你本身看看是否是太監了,ECDH寫到上一篇明顯還沒完,結果到如今了還沒下文,你本身說是否是太監了,你本身說。php
其次是實際上本篇內容實際上和ECDH沒有半毛錢關係,通篇都是DH(少了EC兩個字母),不過在項目中實際應用的業務邏輯寫法、道理都是同樣曬兒的。你如今能夠暫時認爲DH就是ECDH的「 少了兩個字母版本 」。用DH的最主要緣由是啥呢,由於時間有限,我優先寫了DH的經常使用語言庫文件,目前可用,ECDH的一根毛都沒有寫,因此只能用DH演示。node
最後是再次強調一遍,做爲一篇正經的文章,我須要再次科普一下DH是啥意思。git
不少都覺得DH是Daemon Hunter(惡魔獵手)的簡稱,然而並非。Daemon Hunter是真實名稱叫作伊利丹,是個瞎子同時又是法瑪麗奧(就是老鹿)的兄dei。他暗戀白虎(就是那種真的白虎)泰蘭德,然而泰蘭德卻嫁給了老鹿,事情大概就是這麼一回事。
在咱們這裏DH則是Diffie-Hellman的簡稱,二位大爺的照片我之前貼過,如今不得再也不貼一遍:程序員
上圖告訴咱們頭髮長短與職業無關,douyin上那些自覺得get到程序員梗的短視頻真的是LOWB到一塌糊塗。github
在正式開始前以前,我仍是要說明一下用DH的初衷是什麼或者說這個東西是來解決什麼問題的。接着上篇的故事(點擊這裏)說:redis
咱們引入DH就是爲了解決上面的問題。然而,DH或ECDH並不能解決中間人攻擊問題,這個要搞明白了。算法
因此,在正式開始以前,我必須先安利我和東北大嫖客還有巨蛀以及阿尼特寫的DH庫,github連接是這個,下面我將利用這些DH庫們進行demo演示。json
https://github.com/ti-dh
(明眼人已經看出來我是來騙star的)
目前這個庫提供了純PHP、C實現的PHP擴展、Java版,列個表格吧:api
先說下服務端和客戶端進行協商地總體流程,很是很是簡單:服務器
整個協商流程中,只有第二步和第三步會發生數據交互。第二步是API下發p、g、server-num給客戶端;第三步是客戶端向API提交client-num數據;最後一步,對稱加解密用的key就已經計算出來用於生產環境了。
下面我用世界上最好的語言演示一下如何使用這個鬼東西,客戶端咱們用什麼演示呢?客戶端也依然使用世界上最好的語言來演示。首先,大家把上面github裏的庫文件集成到大家API裏,我這裏集成完畢後代碼以下:
<?php class DhController extends BaseController{ private $dh = null; // 將DH庫初始化進來呀... public function init() { $this->dh = new Dh(); } // 這就是上圖中的第二步:客戶端訪問這個API獲取g p 和 server-num public function getdhbasedataAction() { $ret = $this->dh->getdhbasedata(); echo json_encode( $ret ); } // 這就是上圖中的第三步:客戶端經過這個api提交client-num參數 public function postdhclientdataAction() { if ( $this->getRequest()->isPost() ) { if ( empty( $_POST['client_number'] ) || !is_numeric( $_POST['client_number'] ) ) { exit( json_encode( array( 'code' => -1, 'message' => 'wrong parameters', ) ) ); } $ret = $this->dh->postdhclientdata( $_POST ); echo json_encode( array( 'key' => $ret, ) ); } } }
<?php require __DIR__ . '/vendor/autoload.php'; use \Curl\Curl; $curl = new Curl(); // 初始化客戶端數據,隨機一個便可~ $client_number = mt_rand( 100000, 999999 ); // 一、第一步,獲取服務器的p、g和server_number $ret = $curl->get( 'https://xxxx.ooo/dh/getdhbasedata' ); $ret = json_decode( $ret, true ); $p = $ret['p']; $g = $ret['g']; $server_number = $ret['server_number']; // 二、第二步,根據服務器獲取到的數據計算出client-number $process_client_number = gmp_powm( $g, $client_number, $p ); // 三、第三步,將計算事後的client-number發送給服務器 // 那個demo裏已經有完美的演示了,多看代碼 $ret = $curl->post( 'https://xxxx.ooo/dh/postdhclientdata', array( 'client_number' => gmp_strval( $process_client_number ), ) ); $ret = json_decode( $ret, true ); // 四、第四步,根據server-number,client-number和p 計算出公共密鑰K $key = gmp_powm( $server_number, $client_number, $p ); echo PHP_EOL."DH非對稱密鑰產生交換:".PHP_EOL; echo 'client計算出的public key : '.$key.PHP_EOL; echo 'server計算出的public key : '.$ret['key'].PHP_EOL.PHP_EOL;
客戶端文件保存client.php,而後php client.php執行一下,結果大家感覺一下:
同樣有沒有?!計算出來的都同樣,有沒有?!!
上圖中那麼一坨長的不能整的讓人看了就以爲噁心嘔吐的數字就是API和客戶端分別計算出來的對稱加解密的密鑰了,請注意實際使用過程當中,服務器千萬不要把這個數據返回給客戶端,demo裏這麼作就是爲了演示而已,用的時候本身也須要動動腦子的。
然而,事情每每不會說就是這麼簡單就能夠了,若是在生產環境使用,仍是須要繼續完善一些細節的。
我發誓,這是關於DH或ECDH的最後一篇文章了,之後我不再會寫任何與這兩個英文縮寫相關的東西了,我說都是真的,我保證說到作到。