密钥交换算法
密钥交换算法概述
在之前的对称加密算法中,基于"密钥"解决了数据加密和解密的问题,但在实际案例开发中,密钥该如何传递呢?
在不安全的信道上传递加密文件是没有问题的,因为黑客拿到加密文件没有用。但是,如何在不安全的信道上安全地传输密钥?
要解决这个问题,就需要使用密钥交换算法:DH算法(Diffie-Hellman算法)。DH算法解决了密钥在双方不直接传递密钥的情况下完成密钥交换,这个神奇的交换原理完全由数学理论的支持。
密钥交换算法的底层逻辑
在了解了密钥交换算法DH算法之后,那么它是怎么交换?怎么实现的呢?
大致可以这样理解;
在DH算法的交换中,双方的私钥和协商后的共享密钥并没有在网络上进行传输,双方传输的只是自己的公钥,而且传输过程中的p,g,A和B是无法推算出K的。所以,DH算法的本质就是双方各自生成自己的私钥和公钥,私钥仅对自己可见,然后交换公钥,并根据自己的私钥和对方的公钥,生成最终的密钥secretKey,DH算法通过数学定律保证了双方各自计算出的secretKey是相同的。
案例实现
代码如下(示例):
//DH算法
public class Work03 {
public static void main(String[] args) {
// 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() {
try {
// 创建DH算法的“秘钥对”生成器
KeyPairGenerator kpGen = KeyPairGenerator.getInstance("DH");
kpGen.initialize(512);
//生成一个密钥对
KeyPair kp = kpGen.generateKeyPair();
this.publicKey=kp.getPublic();
this.privateKey=kp.getPrivate();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
}
// 按照 "对方的公钥" => 生成"共享密钥"
public void generateSecretKey(byte[] receivedPubKeyBytes) {
try {
//从byte[]数组中恢复PublicKey
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(receivedPubKeyBytes);
//根据DH算法获取KeyFactory
KeyFactory kf = KeyFactory.getInstance("DH");
//通过KeyFactory创建公钥
PublicKey receivedPublicKey=kf.generatePublic(keySpec);
//创建密钥协议对象(用于密钥协商)
KeyAgreement keyAgreement = KeyAgreement.getInstance("DH");
keyAgreement.init(this.privateKey);//初始自己的私钥
keyAgreement.doPhase(receivedPublicKey, true);//根据对方的公钥
//生成SecretKey本地密钥(共享公钥)
this.secretKey=keyAgreement.generateSecret();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (InvalidKeySpecException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
}
}
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));
}
}
总结
- DH算法是一种密钥交换协议,通信双方通过不安全的信道协商密钥,然后进行对称加密传输。