Diffie-Hellman 鍵交換を実装する
Diffie-Hellman 鍵交換とは、他人に知られても構わない情報を 2 人が交換するだけで、
共通の秘密鍵を作り出す方法です。
IPSec では Diffie-Hellman 鍵交換を改良した方法を使用しています。
Diffie-Hellman 鍵交換の手順
[1] Alice は Bob に 2 つの素数 P と G を送信する。
[2] Alice は乱数 A を用意する。
[3] Bob は乱数 B を用意する。
[4] Alice は Bob に G^A mod P の結果を送信する。
[5] Bob は Alice に G^B mod P の結果を送信する。
[6] Alice は (G^B mod P)^A mod P を計算する。
[7] Bob は (G^A mod P)^B mod P を計算する。
Java で実装する
ここでは Diffie-Hellman 鍵交換を Java で実装する例を紹介します。
コード記述例 Alice
import java.security.*;
import java.security.spec.*;
import javax.crypto.*;
import javax.crypto.spec.*;
public class Alice {
private Bob bob_;
private SecretKey secretKey_;
public Alice(Bob bob) {
bob_ = bob;
}
public void generateSecretKey() throws Exception {
AlgorithmParameterGenerator paramGen = AlgorithmParameterGenerator
.getInstance("DH");
paramGen.init(512);
AlgorithmParameters params = paramGen.generateParameters();
DHParameterSpec dhSkipParamSpec = (DHParameterSpec)params
.getParameterSpec(DHParameterSpec.class);
KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("DH");
keyPairGen.initialize(dhSkipParamSpec);
KeyPair keyPair = keyPairGen.generateKeyPair();
KeyAgreement keyAgree = KeyAgreement.getInstance("DH");
keyAgree.init(keyPair.getPrivate());
X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(bob_
.createPublicKeyEncode(keyPair.getPublic().getEncoded()));
PublicKey destinationPubKey = KeyFactory.getInstance("DH")
.generatePublic(x509KeySpec);
keyAgree.doPhase(destinationPubKey, true);
bob_.setKeyLength(keyAgree.generateSecret().length);
keyAgree.doPhase(destinationPubKey, true);
secretKey_ = keyAgree.generateSecret("DES");
}
public SecretKey getSecretKey() {
return secretKey_;
}
}
コード記述例 Bob
import java.security.*;
import java.security.spec.*;
import javax.crypto.*;
import javax.crypto.interfaces.*;
import javax.crypto.spec.*;
public class Bob {
private SecretKey secretKey_;
private KeyAgreement keyAgree_;
private PublicKey publicKey_;
public Bob() {
}
public byte[] createPublicKeyEncode(byte[] pubKeyEnc) throws Exception {
X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(pubKeyEnc);
publicKey_ = KeyFactory.getInstance("DH").generatePublic(x509KeySpec);
DHParameterSpec dhParamSpec = ((DHPublicKey)publicKey_).getParams();
KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("DH");
keyPairGen.initialize(dhParamSpec);
KeyPair keyPair = keyPairGen.generateKeyPair();
keyAgree_ = KeyAgreement.getInstance("DH");
keyAgree_.init(keyPair.getPrivate());
return keyPair.getPublic().getEncoded();
}
public void setKeyLength(int len) throws Exception {
byte[] secret = new byte[len];
int myLen;
try {
keyAgree_.doPhase(publicKey_, true);
myLen = keyAgree_.generateSecret(secret, 1);
} catch (ShortBufferException e) {
System.out.println(e.getMessage());
}
myLen = keyAgree_.generateSecret(secret, 0);
keyAgree_.doPhase(publicKey_, true);
secretKey_ = keyAgree_.generateSecret("DES");
}
public SecretKey getSecretKey() {
return secretKey_;
}
}
コード記述例 Main
public static void main(String[] args) throws Exception {
Bob bob = new Bob();
Alice alice = new Alice(bob);
alice.generateSecretKey();
System.out.println("Alice secret: "
+ toHexString(alice.getSecretKey().getEncoded()));
System.out.println("Bob secret: "
+ toHexString(bob.getSecretKey().getEncoded()));
}
private static String toHexString(byte[] arr) {
StringBuffer buf = new StringBuffer();
for (int i = 0; i < arr.length; i++) {
buf.append(Integer.toHexString(arr[i] & 0xff));
}
return buf.toString();
}
出力結果
Alice secret: 5b3ebf61fefbea4
Bob secret: 5b3ebf61fefbea4
|