当前位置: 首页 > 后端技术 > PHP

我发誓这真的是关于ECDH的最后一篇文章!(API安全增强第4部分)

时间:2023-03-29 16:33:00 PHP

首先,我前段时间在公众号被批评(dui)和评论(gang),大概意思是:别乱说ECDH是一个椭圆和一个素数,你就说这个东西可以用在实际项目中,我们不想听,我们都知道而且精通,你还是个太监,你看看你是不是太监,ECDH写的上一篇显然还没有写完,结果一直到现在都没有进一步的正文。是不是太监可以说,自己也可以说。其次,其实本文的内容与ECDH无关。整篇文章都是DH(少了两个字母EC),但是在项目中实际应用中写的和推理的业务逻辑是一致的。您现在可以暂时将DH视为ECDH的“无两个字母版本”。使用DH的主要原因是什么?由于时间有限,先写了DH的公共语言库文件,目前已经可以使用了。ECDH我毛都没写过,只能用DH来演示了。最后,我想再强调一下。作为一篇正经文章,我需要再次科普一下DH是什么意思。很多人认为DH是DaemonHunter(恶魔猎手)的缩写,其实不然。恶魔猎手,本名伊利丹,是一个盲人,是法马里奥(老鹿)的弟弟。他偷偷爱上了白虎(真正的白虎)泰兰德,但是泰兰德娶了老鹿,大概就是这样。这里DH是Diffie-Hellman的缩写。之前发过两位大叔的照片,现在又要发一遍:上图告诉我们,头发的长短与职业无关。抖音上那些自以为搞定程序员短视频的人真是LOWB到一塌糊涂。在正式开始之前,我还是想说明一下使用DH的初衷是什么或者说这个东西是为了解决什么问题。然后是之前的故事(点这里):你们老板说项目很厉害,数据要加密。如果你使用强大的加密算法,你可以使用RSA非对称加密来开发和测试运行如虎添翼。然后,一上线:CPU炸了,1-5分,然后你找老板批了升级服务器费,老板给你300块钱让你大胆花,你先把RSA下线,然后偷偷下线换成AES对称加密,CPU没炸然后300块钱你偷偷把AES对称密钥放在口袋里,但是如果你把AES对称密钥写到客户端,就反过来了;如果通过服务器发送,听起来就更扯了。想了想,你和300元儿子组个局,你带钱,我带陈旭,老赵带柱子,还有大彪,正好六人局,我给你透露一个方案:谈判AES对称密钥通过非对称方法问世。DH神奇的算法可以让你的服务器和客户端在不传输对称密钥的情况下,通过默认的方式计算出一个对称密钥,并且可以相同,避免了密钥在网络上的流通,而且可以随意更改,并且设置过期时间为1分钟,极其恶毒!我们引入DH来解决上述问题。但是DH或者ECDH并不能解决中间人攻击的问题,这点需要理解。所以,在正式开始之前,首先要安装我自己写的DH库,东北客户端,巨魔和Arnit。github链接是这个。接下来,我将使用这些DH库进行demo演示。https://github.com/ti-dh(明眼人已经看出我是来骗星的)目前这个库提供纯PHP、C实现的PHP扩展、Java版本。打个表吧:先说服务器吧。整个和客户谈判的过程非常非常简单:在整个谈判过程中,只有第二步和第三步会交换数据。第二步,API向客户端发送p、g、server-num;第三步,客户端向API提交client-num数据;最后一步,已经计算出用于对称加解密的密钥,并用于生产环境。接下来,我将用世界上最好的语言来演示如何使用这个鬼东西。我们在客户端用什么来演示?客户也依然用世界上最好的语言来演示。首先,你将上面github中的库文件集成到你的API中。集成后的代码如下:APIdemo代码:dh=newDh();}//这是上图中的第二步:client访问这个API获取gp和server-numpublicfunctiongetdhbasedataAction(){$ret=$this->dh->getdhbasedata();echojson_encode($ret);}//这是上图中的第三步:客户端通过这个api提交client-num参数publicfunctionpostdhclientdataAction(){if($this->getRequest()->isPost()){if(empty($_POST['client_number'])||!is_numeric($_POST['client_number'])){exit(json_encode(array('code'=>-1,'message'=>'错误参数',)));}$ret=$this->dh->postdhclientdata($_POST);echojson_encode(array('key'=>$ret,));}}}客户端演示代码: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-numbertotheserver//那个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计算公钥K$key=gmp_powm($server_number,$client_number,$p,client-numberandp);echoPHP_EOL."DH非对称密钥交换:".PHP_EOL;echo'客户端计算的公钥:'.$key.PHP_EOL;echo'服务器计算的公钥:'.$ret['key'].PHP_EOL.PHP_EOL;客户端文件保存client.php,然后执行phpclient.php。结果,你能感觉到:是一样的吗?!计算都是一样的,对吧?!!上图中那个太长太长让人恶心呕吐的数字是API和客户端分别计算的对称加解密的密钥。请注意,在实际使用过程中,服务端一定不能使用这个数据返回给客户端,在demo中这里只是为了演示,使用的时候需要动动脑筋。然而,事情往往没有那么简单。如果在生产环境中使用,还需要继续完善一些细节。第一个问题,有些宝宝想多了会不一样,两个client算出来的key会不会一样?可能性非常非常小。第二个问题是一般客户端登录的用户都有自己的token或者uid。与客户端协商好密钥后,API可以将密钥以“token:key”的格式发送到redis中,然后给出一个有效时间,比如30分钟;客户端还将密钥保存在手机内存中,以设置30分钟的有效期限。每次使用密钥进行加密和解密时,都要验证它是否已过期。如果到期,则重新走之前的协商流程。我发誓,这是关于DH或ECDH的最后一篇文章,我再也不会写任何与它相关的文章。关于这两个英文缩写的事情,我说的是真的,我保证说到做到。欢迎来到公众号恨我打我: