DH算法(密钥交换算法)的总结和Java实现案例

目录

概述

数学原理

实现案例

用户类

测试类

总结


概述

我们在使用AES算法的过程中,使用了相同的密钥,那么如果在实际应用中: 在网络上的两个用户之间需要传输文件时,A使用自己的密钥向B发送了加密文件,那么B就需要A的密钥来解密文件。

那么这就会出现安全隐患:

在不安全的信道上A发送的加密文件被黑客拿到了,但是由于是加密过的,所以没有什么用。但是如果被黑客拿到了密钥呢? 

要解决这个问题,就需要使用密钥交换算法: DH算法(Diffie-Hellman算法)DH算法解决了在双方不直接传递密钥的情况下完成密钥交换。

数学原理

下面是DH算法交换密钥的步骤。假设Alice,Bob双方需要传递密钥,他们可以这样:

  1. Alice首选选择一个素数p= 509,底数g = 5(任选),随机数a = 123,然后计算A = g^a mod p,结果是215,然后,Alice发送p = 509,g=5,A=215给Bob;
  2. Bob收到后,也选择一个随机数b=456,然后计算B = g^b mod p,结果是181,Bob再同时计算K = A^b mod p,结果是121;
  3. Bob把计算的B=181发给Alice,Alice计算K = B^a mod p的余数,计算结果与Bob算出的结果一样,都是121。

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

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

实现案例

用户类

用户类用于模拟收发文件的双方,以及具有生成各自的公钥私钥,计算共享密钥的方法。

生成公私钥对的方法:

  1. 创建基于DH算法的密钥对生成器;
  2. 初始化长度;
  3. 通过密钥生成器生成密钥对;
  4. getPrivate()获取私钥,getPublic()获取公钥。
 // 生成本地KeyPair:(公钥+私钥)
 public void generateKeyPair() {
     try {
         // 创建DH算法的“秘钥对”生成器
         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);
     }
 }

根据对方的公钥计算共享密钥: 

  1. 根据字节数组恢复密钥对象X509EncodedKeySpec;
  2. 创建基于DH算法的keyFactory;
  3. 通过keyFatcory将密钥对象加工成为PublicKey对象;
  4. 创建基于DH算法的密钥协议对象;
  5. 通过密钥协议对象先把自己的PrivateKey初始化进去;
  6. 调用密钥协议对象的doPhase()方法,根据对方的PublicKey;
  7. 最后调用generateSecret()方法算出共享密钥。

完整的Person类:

// 用户类
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.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);

             // 根据DH算法获取KeyFactory
             KeyFactory kf = KeyFactory.getInstance("DH");
             // 通过KeyFactory创建公钥
             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));
     }
}

测试类

双方各自通过对方的公钥计算自己的共享密钥,最后打印输出共享密钥,验证一致性。 

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加解密...
   }
}

总结

  1. DH算法是一种密钥交换协议,通信双方通过不安全的信道协商密钥,然后进行对称加密传输。
  2. 使用DH算法协商的双方,通过对方的公钥和自己的私钥计算出相等的共享密钥。
  3. 计算后的共享密钥双方相等,所以无需再传输共享密钥,就可以使用共享密钥进行安全的对称加密传输。
  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
DH交换算法是一种基于离散对数问题的公码体制,其核心思想是:双方通过交换公共信息来生成一个共享的,该只有双方知道,达到了保通信的目的。下面是C语言实现DH交换算法的代码示例: ```c #include <stdio.h> #include <stdlib.h> #include <math.h> // 定义素数p和底数g #define p 23 #define g 5 // 计算a^b mod p int mod_exp(int a, int b, int p) { int res = 1; while (b > 0) { if (b & 1) { res = (res * a) % p; } a = (a * a) % p; b >>= 1; } return res; } int main() { int alice_secret, bob_secret; // 双方的私有 int alice_public, bob_public; // 双方的公共 int shared_secret_alice, shared_secret_bob; // 双方的共享 // 双方选择各自的私有 alice_secret = 6; // 可以随机生成 bob_secret = 15; // 可以随机生成 // 计算双方的公共 alice_public = mod_exp(g, alice_secret, p); bob_public = mod_exp(g, bob_secret, p); // 双方交换公共 shared_secret_alice = mod_exp(bob_public, alice_secret, p); shared_secret_bob = mod_exp(alice_public, bob_secret, p); // 检查共享是否相同 if (shared_secret_alice == shared_secret_bob) { printf("共享为:%d\n", shared_secret_alice); } else { printf("交换失败!\n"); } return 0; } ``` 以上代码中,我们选择了一个素数p和一个底数g,双方各自选择一个私有,然后计算出自己的公共,并交换公共,最后通过计算得到共享。 需要注意的是,在实际应用中,需要使用更大的素数p和更复杂的计算方法来确保安全性。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值