DH密钥交换算法
DH密钥交换算法:DH的全称为Diffie-Hellman ,该算法可以在需要安全传输的前提下,确定双⽅的对称密钥,该算法的核⼼在于双⽅的私钥没有进⼊⽹络传输流程,根据对⽅的公钥和⼰⽅的私钥,可以计算出同样的Key。攻击⽅即便获取到了公钥和P,G值,也⽆法计算出Key值。
公钥:会进⼊⽹络传输的密钥部分,该部分是公开的。私钥: 由端⾃⼰保存的密钥部分,该部分不允许公开。
DK:加密算法中,⽤X对敏感数据进⾏加密后,再⽤Key对X加密得到DK,然后X就被舍弃了,这⾥的X没有持久化,使⽤完内存就被销毁,攻击者需要得到敏感数据,就必须得到X,然后X已经被销毁了,破解⽅必须通过DK去破解出X,DK是通过Key来保护的,只要保证Key是安全的,敏感数据就是安全的。
Key:通过对⽅公钥和⼰⽅私钥⽣成的Key值,只要私钥不被破解,该值就是安全的。Token认证:接⼝的安全认证
SID:握⼿标识,由客户端⽣成,⽤户A和⽤户B握⼿后,双⽅需要记录握⼿成功后的SID和DH密钥交换中⽣成的Key。后续通信时,服务端通过请求header中的SID和DK来知道该如何解密敏感信息。
⼗六进制编码:字节在传输过程中,如果使⽤⼀般的编码,会导致⽹络传输后出现丢失字节的情况,这时就要使⽤到⼗六进制编码,在本⽂中,统⼀⽤S(byte[])来标⽰字符数组的⼗六进制编码处理。
AES-supports: 加密⽤的规则,请求⽅所⽀持的AES加密种类,如果⽀持多个,⽤分号分割。平台内⽀持的规则是固定的,由库中决定。AES-param: 响应⽅从请求⽅的AES-supports挑选⼀个随机的加密⽅法,作为本次加密使⽤的AES规则。
A.预备知识
整个加密流程的实现,分成客户端部分和服务端部分,对于⼤部分的服务,均需实现。传输加密前,双⽅需要通过协商,来确定加密敏感信息所⽤的密钥。每⼀次的协商,都会⽣成⼀个唯⼀的SID,⽤于双⽅后续的通信。当服务端发现SID过期时,需要返回约定好的错误码,让客户端重新发起协商和请求。
本⽂以流程为主,代码为辅,介绍了整个流程中的执⾏细节。为了保证流程的完整性,这⾥轮流写客户端和服务端的流程。B.客户端协商请求
P1.客户端⽣成P,G,PublicKeyA和PrivateKeyA。 P和G⽣成时均为BigInteger,需要调⽤⽅法toString(16)转化成字符串,后⾯使⽤的都是转换后的P和G。
P2.客户端⽣成⼀个唯⼀的会话ID,记为SID
P3.客户端⽣成客户端⽀持的加/解密规则AES-supports。
P4.客户端⽣成请求接⼝⽤的认证Token,Token的签名使⽤:SID + S(publicKey1) + P + G
P5.客户端将Token放⼊header中,将P、G、S(PublicKeyA)、SID、AES-supports字段放⼊body中,并调⽤服务端的协商接⼝。详细的参数信息见下表:
C.服务端协商处理
P1.服务端收到客户端的协商请求后,⾸先要校验字段的完整性。P2.通过完整性校验后,校验Token的有效性,其中签名同为:SID + PublicKey + P + G所有参数均为请求中的字段
P3.服务端对PublicKey⼗六进制解码得到PublicKeyA。
P4.服务端通过P,G,PublicKeyA,⽣成⾃⼰的PublicKeyB和PrivateKeyBP5.服务端从AES-supports中,选择⼀个作为本地协商的加密规则AES-param
P6.服务端⽣成⼀个协商有效时间expireTime(单位、毫秒),并缓存PublicKeyA、PublicKeyB、PrivateKeyB、expireTime、SecuSID、AES-param。
P7.服务端⽣成⼀个双向认证⽤的Token,Token的签名如下:SecuSID + S(PublicKeyB) + AES-param + expireTimeP7.返回协商结果。D.客户端协商返回处理
P1.服务端的请求返回的字段对象见下:
P2.客户端校验服务端⽣成的Token,校验⽤的签名如下:SecuSID + PublicKey + AES-param + expireTime以上参数均为请求返回的字段。
P3.客户端缓存下这些参数以及之前⽣成的P、G,其中expireTime决定了会话的过期时间,通过服务端返回的PublicKey⼗六进制解码后得到的PublicKeyB和之前⽣成的PrivateKeyA、P、G、本地加密规则AES-param,可以⽣成Key⽤于加密。SecuSID在后续数据传输中使⽤。⾄此,握⼿结束。
E.客户端数据传输请求
P1.客户端先在本地查找是否有和该地址的该服务有握⼿记录,如果有且记录未过期,则使⽤该握⼿记录中的握⼿数据,否则重新握⼿。P2. 客户端根据握⼿数据中服务端的PublicKeyB、本地的PrivateKeyA和本地加密规则AES- param,⽣成加密⽮量localIv和加密密钥localKey。
P3.客户端⽣成随机数X,⽤X和加密⽮量localIv、本地加密规则AES- param对请求body中的敏感信息加密得到A,再对A进⾏Base加密得到最终⽤于传输的密⽂。
P4.客户端⽤加密⽮量localIv、加密密钥localKey和本地加密规则AES- param对随机数X加密得到Y,并对Y进⾏⼗六进制编码得到DK。P5.客户端⽣成认证Token,⽣成Token的签名如下:SID + DK
P6.客户端向服务端发起请求,请求字段如下:
F.服务端数据传输处理
P1.服务端接受到客户端的请求,先校验Header中字段的完整性,P2.服务端校验客户端请求Token的合法性,其中Token的签名如下:SecuSID + SecuDK
P3.服务端判断该SecuSID对应的协商是否过期,如果过期,直接返回提⽰重新握⼿。
P4.服务端从该SecuSID对应的缓存中,取出之前协商的数据,通过其中的PublicKeyA和PrivateKeyB和客户端的加密规则AES-param,⽣成加密⽮量localIv和加密密钥localKey。
P5.通过对SecuDK⼗六进制解码得到Y,再通过加密⽮量localIv和加密密钥localKey以及客户端的加密规则AES- param对Y进⾏解密得到X。
P6.对body中的敏感信息密⽂进⾏Base解密得到A,再通过对X和加密⽮量localIv对A进⾏解密得到明⽂。P7.业务处理,进⼊返回敏感信息加密流程。
P8.服务端端⽣成随机数X,⽤X和加密⽮量localIv、服务端的加密规则AES-param对范围报⽂中的敏感信息加密得到A,再对A进⾏Base加密得到最终⽤于传输的密⽂。
P9.服务端⽤加密⽮量localIv、加密密钥localKey和服务端的加密规则AES-param对随机数X加密得到Y,并对Y进⾏⼗六进制编码得到DK。P10.服务端⽣成认证Token,⽣成Token的签名如下:SID + DK
P11。服务端返回结果。G.客户端数据传输返回处理
P1. 服务端的请求返回的字段对象见下:
P2.注意服务端返回的SecuDK和请求过去的SecuDK是不相同的,不能混淆。P3.校验Token的合法性,校验规则中的签名如下:SID + DK(服务端返回的)
P4.客户端先对DK⽤⼗六进制反编码出Y,再⽤加密⽮量localIv、加密密钥localKey和之前协商返回的服务端加密规则AES-param对Y解密得到X。
P5. 客户端先对传输过来的敏感信息密⽂⽤base解码成字节串,再⽤X和加密⽮量localIv、服务端加密规则AES-param对该字节串解密出明⽂。