【主流的密钥交换方式】
敏感数据信息安全传输需要对敏感信息加密,加密的密钥涉及到传输两端的密钥协商和交换,目前主要两种密钥交换的机制有:
1. 基于非对称密钥的实现:请求方用接收方的公钥加密自己的密钥,接收方用自己的私钥解密得到请求方的密钥,反之一样,从而实现密钥的交换
2. DH密钥交换算法
【DH密钥交换算法】
双方协商用同一个大素数p和素数的原根g,各自生成随机数XA,XB。请求方将g的xA次方mod p产生数值发送给接收方,接收方再将g的XB次方mod p产生的数值发送给请求方,请求方再对接收的数值做XA次方并对p求余运算,接收方对接收的数值做XB次方并对p求余运算,最终形成共同的密钥K,以达到密钥的交换。
假如用户A和用户B希望交换一个密钥;
- 取素数p和整数g,g是p的一个原根,公开g和p
- A选择随机数XA<p,并计算YA=g^XA mod p
- B选择随机数XB<p,并计算YB=g^XB mod p
每一方都将X保密而将Y公开让另一方得到
A计算密钥的方式是:K=(YB) ^XA modp
B计算密钥的方式是:K=(YA) ^XB modp
A和B的K是相同的,K是共享秘钥
【DH算法源码解读】
主要涉及jdk中jce.jar、sunjce_provider.jar、rt.jar三个安全jar包。
主要涉及的几个类:keyPairGenerator,DHPrivateKeySpec, DHPublicKeySpec, DHPublicKey ,DHPrivateKey ,DHKeyFactory, DHKeyAgreement几个类。
接下来主要针对keyPairGenerator、DHKeyFactory、DHKeyAgreement这几个类的源码进行阐述:
keyPairGenerator形成公私钥的key生成器:生成DHPublicKey,DHPrivateKey。
DHKeyFactory:公私钥对象转换器工厂类:里面提供engineGeneratePublic(KeySpec paramKeySpec)和protected PrivateKey engineGeneratePrivate(KeySpec paramKeySpec)用来转换数据,如下是engineGeneratePrivate的源码:
从源码中看出会根据paramKeySpec不同用不同的方法生成的DHPrivateKey,为了考虑语言兼容性,统一采用PKCS8EncodedKeySpec。
接下来谈下协商的核心类:DHKeyAgreement。
首先engineInit(Key paramKey, SecureRandom paramSecureRandom)提供初始化数据,包括P,G,privateKey,下面是对应的源码,b对应P,c->G,d对应privateKey
Key engineDoPhase(Key paramKey, boolean paramBoolean)初始化publickey数据,如下是部分源码:其中e对应到的就是publicKey.
最后这个方法也就是核心方法,协商的算法byte[] engineGenerateSecret(),返回的是协商后的密钥字节数组,源码如下:接下来具体分下下面代码。
从上面源码中看到最核心的代码就一句:BigInteger localBigInteger2 = this.e.modPow(this.d, localBigInteger1);把它转成数学方式的表达式为: publicKey^privateKey mod p = sharekey。
再结合DH算法原理对上面就可以更好理解了:
DH算法:双方协商用同一个大素数p和 素数p的原根g,各自生成随机数X,Y。请求方将g的X次方mod p产生的数值发送给接收方,接收方将g的Y次方mod p产生的数值发送给请求方。请求方再对接收的数值做X次方运算,接收方对接收的数值做Y次方运算,最终生成一样的共享密钥,完成密钥的交换。