DH演算法及原始碼解讀
【主流的金鑰交換方式】
敏感資料資訊保安傳輸需要對敏感資訊加密,加密的金鑰涉及到傳輸兩端的金鑰協商和交換,目前主要兩種金鑰交換的機制有:
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,
接下來主要針對keyPairGenerator、DHKeyFactory、DHKeyAgreement這幾個類的原始碼進行闡述:
keyPairGenerator形成公私鑰的key生成器:生成DHPublicKey,DHPrivateKey。
DHKeyFactory:公私鑰物件轉換器工廠類:裡面提供engineGeneratePublic(KeySpec paramKeySpec)和protected PrivateKey engineGeneratePrivate(KeySpec paramKeySpec)
從原始碼中看出會根據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次方運算,最終生成一樣的共享金鑰,完成金鑰的交換。