DH密钥交换算法(加密通信基础)

一、参数介绍

1.1 用户甲

A a s
甲的公钥 甲的私钥 密钥

1.2 用户乙

B b s
乙的公钥 乙的私钥 密钥

1.3 公共参数

g p
底数(大于1) 质数,(尽量大,防破解)

二、算法介绍

2.1 初始化过程

  • a与b为自动生成的随机数,尽量大,保证安全性
  • 用户初始化时,调用A=pow(g,a)%p,生成公钥与私钥,持久化存储
  • 用户初始化时,调用B=pow(g,b)%p,生成公钥与私钥,持久化存储

2.2 密钥交换过程

  • 甲向乙发送信息的携带甲的公钥
  • 同理乙向甲发送信息的时候携带乙的公钥

2.3 加解密过程

  • 实现原理:s=pow(A,b)%p=pow(B,a)%p,s为密钥
  • 通过以上方式算出密钥s后,对发送/接收的消息使用对称加密的方式进行加解密

三、Java方式简易实现

@Getter
@Setter
public class Person {
private String name;
// 公钥
private PublicKey publicKey;
// 私钥
private PrivateKey privateKey;
// 密钥
private byte[] secretKey;

public Person(String name) {
this.name = name;
// 生成共私钥
try {
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("DH");
keyGen.initialize(512);
KeyPair keyPair = keyGen.generateKeyPair();
this.setPrivateKey(keyPair.getPrivate());
this.setPublicKey(keyPair.getPublic());
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
}

// 计算私钥
public void generateSecretKey(byte[] pubKeys) {
X509EncodedKeySpec encodedKeySpec = new X509EncodedKeySpec(pubKeys);
try {
// 从byte中恢复公钥
KeyFactory factory = KeyFactory.getInstance("DH");
PublicKey publicKey = factory.generatePublic(encodedKeySpec);
// 生成本地密钥
KeyAgreement keyAgreement = KeyAgreement.getInstance("DH");
// 自己的私钥
keyAgreement.init(this.privateKey);
// 对方的公钥
keyAgreement.doPhase(publicKey, true);
// 生成私钥
this.secretKey = keyAgreement.generateSecret();
} catch (GeneralSecurityException e) {
e.printStackTrace();
}
}

@Override
public String toString() {
System.out.println(this.getName());
System.out.println("私钥:" + new BigInteger(1, this.getPrivateKey().getEncoded()));
System.out.println("公钥:" + new BigInteger(1, this.getPublicKey().getEncoded()));
System.out.println("密钥:" + new BigInteger(1, this.getSecretKey()));
return "";
}


public static void main(String[] args) {
long start = System.currentTimeMillis();
// 密钥交换
Person xiaoming = new Person("小明");
Person xiaohong = new Person("小红");
xiaoming.generateSecretKey(xiaohong.getPublicKey().getEncoded());
xiaohong.generateSecretKey(xiaoming.getPublicKey().getEncoded());
xiaoming.toString();
xiaohong.toString();
long end = System.currentTimeMillis();
System.out.println("耗时:" + (end - start));
System.out.println();
}
}