DH算法是一种密钥交换协议,通信双方通过不安全的信道协商密钥,然后进行对称加密传输。
(1)秘钥交换算法DH
import java.math.BigInteger;
import java.security.InvalidKeyException;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.X509EncodedKeySpec;
import javax.crypto.KeyAgreement;
public class Main {
public static void main(String[] args) throws NoSuchAlgorithmException, InvalidKeyException, InvalidKeySpecException {
// Bob和Alice:
Person bob = new Person("Bob");
Person alice = new Person("Alice");
// 各自生成KeyPair: 公钥+私钥
bob.generateKeyPair();
alice.generateKeyPair();
// 双方交换各自的PublicKey(公钥):
// Bob根据Alice的PublicKey生成自己的本地密钥(共享公钥):
bob.generateSecretKey(alice.publicKey.getEncoded());
// Alice根据Bob的PublicKey生成自己的本地密钥(共享公钥):
alice.generateSecretKey(bob.publicKey.getEncoded());
// 查看双方的本地密钥是否相同:
bob.printKeys();
alice.printKeys();
}
}
//用户类
class Person {
public final String name; // 姓名
// 密钥
public PublicKey publicKey; // 公钥
private PrivateKey privateKey; // 私钥
private byte[] secretKey; // 本地秘钥(共享密钥)
// 构造方法
public Person(String name) {
this.name = name;
}
// 生成本地KeyPair:(公钥+私钥)
public void generateKeyPair() throws NoSuchAlgorithmException {
//创建DH算法的“秘钥对”生成器
KeyPairGenerator kpg = KeyPairGenerator.getInstance("DH");
kpg.initialize(512);
//生产一个秘钥对
KeyPair kp = kpg.generateKeyPair();
this.privateKey = kp.getPrivate();//私钥
this.publicKey = kp.getPublic();//公钥
}
// 按照 "对方的公钥" => 生成"共享密钥"
public void generateSecretKey(byte[] receivedPubKeyBytes) throws NoSuchAlgorithmException, InvalidKeySpecException, InvalidKeyException {
//从byte[]中获取对方公钥的字节数据
X509EncodedKeySpec encodedKeySpec = new X509EncodedKeySpec(receivedPubKeyBytes);
//根据DH算法获取KeyFactory
KeyFactory kf = KeyFactory.getInstance("DH");
//通过KeyFactory恢复公钥
PublicKey pk = kf.generatePublic(encodedKeySpec);
//创建共享密钥
KeyAgreement ka = KeyAgreement.getInstance("DH");
ka.init(this.privateKey);//初始化自己的私钥
ka.doPhase(pk, true);//加入对方的公钥
//生成共享密钥
this.secretKey= ka.generateSecret();
}
//输出
public void printKeys() {
System.out.printf("Name: %s\n", this.name);
System.out.printf("Private key: %x\n", new BigInteger(1, this.privateKey.getEncoded()));
System.out.printf("Public key: %x\n", new BigInteger(1, this.publicKey.getEncoded()));
System.out.printf("Secret key: %x\n", new BigInteger(1, this.secretKey));
}
}