我发誓这真的是最后一篇关于ECDH的文儿API安全加强篇四

首先是前段时间我在公众号里被人批(dui)评(gang)了,大概意思就是:你别老整那ECDH又是椭圆又是素数啥的,你就说这玩意实际项目中怎么用就完了,我们不想听那些,那些我们都懂都精通,而且你还太监了,你自己看看是不是太监了,ECDH写到上一篇明显还没完,结果到现在了还没下文,你自己说是不是太监了,你自己说。 其次是实际上本篇内容实际上和ECDH没有半毛钱关系,通篇都是DH(少了EC两个字母),不过在项目中实际应用的业务逻辑写法、道理都是一样晒儿的。你现在可以暂时认为DH就是ECDH的“ 少了两个字母版本 ”。用DH的最主要原因是啥呢,因为时间有限,我优先写了DH的常用语言库文件,目前可用,ECDH的一根毛都没有写,所以只能用DH演示。 最后是再次强调一遍,作为一篇正经的文章,我需要再次科普一下DH是啥意思。 很多都以为DH是Daemon Hunter(恶魔猎手)的简称,然而并不是。Daemon Hunter是真实名称叫做伊利丹,是个瞎子同时又是法玛丽奥(就是老鹿)的兄dei。他暗恋白虎(就是那种真的白虎)泰兰德,然而泰兰德却嫁给了老鹿,事情大概就是这么一回事。 在我们这里DH则是Diffie-Hellman的简称,二位大爷的照片我以前贴过,现在不得不再贴一遍: 上图告诉我们头发长短与职业无关,douyin上那些自以为get到程序员梗的短视频真的是LOWB到一塌糊涂。 在正式开始前之前,我还是要说明一下用DH的初衷是什么或者说这个东西是来解决什么问题的。接着上篇的故事(点击这里)说: 你老板说项目非常牛逼,数据要加密,用牛逼的加密算法你就用RSA非对称加密开发测试操作猛如虎然后,一上线:CPU炸了,成绩1-5然后你找老板审批升级服务器费用,老板给了你300块并让你放心花大胆花你首先把RSA下线了,然后偷偷换成了AES对称加密,CPU不炸了然后三百块偷偷放到了自己腰包里但是AES的对称密钥你写死到客户端,被逆向就完了;如果通过服务器下发,听起来更加扯淡想了想,你拿着三百块钱组了个局儿,你带着钱,我带着陈旭,老赵带着柱子,再加上大彪,正好六人局局上我向你透露出一种方案:将AES对称密钥通过非对称方式协商出来。DH这种神奇的算法可以让你服务器和客户端在不传输该对称密钥的情况下就可以通过心有灵犀地方式各自计算出一个对称密钥,而且可以一样,避免了该密钥在网络上流通,而且你可以随意更换,过期时间定为1分钟,可谓是狠毒至极!我们引入DH就是为了解决上面的问题。然而,DH或ECDH并不能解决中间人攻击问题,这个要搞明白了。 所以,在正式开始之前,我必须先安利我和东北大嫖客还有巨蛀以及阿尼特写的DH库,github链接是这个,下面我将利用这些DH库们进行demo演示。 https://github.com/ti-dh(明眼人已经看出来我是来骗star的)目前这个库提供了纯PHP、C实现的PHP扩展、Java版,列个表格吧: 先说下服务端和客户端进行协商地整体流程,非常非常简单: 整个协商流程中,只有第二步和第三步会发生数据交互。第二步是API下发p、g、server-num给客户端;第三步是客户端向API提交client-num数据;最后一步,对称加解密用的key就已经计算出来用于生产环境了。 下面我用世界上最好的语言演示一下如何使用这个鬼东西,客户端我们用什么演示呢?客户端也依然使用世界上最好的语言来演示。首先,你们把上面github里的库文件集成到你们API里,我这里集成完毕后代码如下: API demo code:<?phpclass 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, ) ); } }}Client demo code:<?phprequire __DIR__ . '/vendor/autoload.php';use \Curl\Curl;$curl = new Curl();// 初始化客户端数据,随机一个即可~$client_number = mt_rand( 100000, 999999 );// 1、第一步,获取服务器的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'];// 2、第二步,根据服务器获取到的数据计算出client-number$process_client_number = gmp_powm( $g, $client_number, $p );// 3、第三步,将计算过后的client-number发送给服务器// 那个demo里已经有完美的演示了,多看代码$ret = $curl->post( 'https://xxxx.ooo/dh/postdhclientdata', array( 'client_number' => gmp_strval( $process_client_number ),) );$ret = json_decode( $ret, true );// 4、第四步,根据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执行一下,结果你们感受一下: ...

May 15, 2019 · 1 min · jiezi

关于PHP加解密之终扯到ECDH了API安全加强篇三

其实,前面两篇翻来覆去只为叨逼叨叨逼叨两件事情: 对称加解密,典型算法有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/loginMETHOD : POSTPROTOCOL : 将数据以JSON形式,全部放入到http body体中,key叫做mzipDATA : { 'username' => 'xitele', 'password' => 'qiangdadaoniyongyuancaibuchulaishiduoshao'}然后客户端执行登陆的伪代码如下: var username string = 'xitele'var password string = md5('123456')// 将数据生成jsonvar data = jsonize( hashMap( 'username' : username, 'password' : password) )// 用服务器公钥,将数据加密var encryptData = RSA.encrypt( '服务端的公钥', data )// 再次封装数据为jsonvar lastJson = jsonize( hashMap( 'mzip' => encryptData) )// 提交数据http.post( 'https://www.so.com/api/user/login', lastJson, function() { // ... ... do something ...} )服务器端使用世界上最好的语言来实现的,所以代码你会觉得十分眼熟: ...

May 9, 2019 · 2 min · jiezi