java dh算法_https密钥交换DH算法

我们来看DH算法交换密钥的步骤。假设甲乙双方需要传递密钥,他们之间可以这么做:

甲首选选择一个素数p,例如509,底数g,任选,例如5,随机数a,例如123,然后计算A=g^a mod p,结果是215,然后,甲发送p=509,g=5,A=215给乙;

乙方收到后,也选择一个随机数b,例如,456,然后计算B=g^b mod p,结果是181,乙再同时计算s=A^b mod p,结果是121;

乙把计算的B=181发给甲,甲计算s=B^a mod p的余数,计算结果与乙算出的结果一样,都是121。

所以最终双方协商出的密钥s是121。注意到这个密钥s并没有在网络上传输。而通过网络传输的p,g,A和B是无法推算出s的,因为实际算法选择的素数是非常大的。

所以,更确切地说,DH算法是一个密钥协商算法,双方最终协商出一个共同的密钥,而这个密钥不会通过网络传输。

如果我们把a看成甲的私钥,A看成甲的公钥,b看成乙的私钥,B看成乙的公钥,DH算法的本质就是双方各自生成自己的私钥和公钥,私钥仅对自己可见,然后交换公钥,并根据自己的私钥和对方的公钥,生成最终的密钥secretKey,DH算法通过数学定律保证了双方各自计算出的secretKey是相同的。

使用Java实现DH算法的代码如下:

import java.math.BigInteger;

import java.security.*;

import java.security.spec.*;

import javax.crypto.KeyAgreement;

public class Main {

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();

// 双方的SecretKey相同,后续通信将使用SecretKey作为密钥进行AES加解密...

}

}

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 {

KeyPairGenerator kpGen = KeyPairGenerator.getInstance("DH");

kpGen.initialize(512);

KeyPair kp = kpGen.generateKeyPair();

this.privateKey = kp.getPrivate();

this.publicKey = kp.getPublic();

} catch (GeneralSecurityException e) {

throw new RuntimeException(e);

}

}

public void generateSecretKey(byte[] receivedPubKeyBytes) {

try {

// 从byte[]恢复PublicKey:

X509EncodedKeySpec keySpec = new X509EncodedKeySpec(receivedPubKeyBytes);

KeyFactory kf = KeyFactory.getInstance("DH");

PublicKey receivedPublicKey = kf.generatePublic(keySpec);

// 生成本地密钥:

KeyAgreement keyAgreement = KeyAgreement.getInstance("DH");

keyAgreement.init(this.privateKey); // 自己的PrivateKey

keyAgreement.doPhase(receivedPublicKey, true); // 对方的PublicKey

// 生成SecretKey密钥:

this.secretKey = keyAgreement.generateSecret();

} catch (GeneralSecurityException e) {

throw new RuntimeException(e);

}

}

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));

}

}

参考文献

https://www.liaoxuefeng.com/wiki/1252599548343744/1304227905273889

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值