加密与安全_探索密钥交换算法_Diffie-Hellman算法

news2024/12/24 2:13:05

文章目录

  • 概述
  • 数学理论支持
  • 使用Java实现DH算法
  • DH算法的缺点

在这里插入图片描述


概述

对称加密算法解决了数据加密的问题,例如AES加密可以有效地保护文件的安全性。然而,一个关键的挑战是如何在不安全的通信信道上安全地传输密钥

假设小明需要向路人甲发送一个加密文件,他可以先生成一个AES密钥,使用该密钥对文件进行加密,然后将加密后的文件发送给对方。但是,问题在于对方需要密钥才能解密文件,因此密钥的传输必须是安全的。

在传统的密钥传输方法中,密钥通常通过不同的方式发送,如口头告知、书面传递或者其他安全信道。然而,在不安全的通信信道上,这些方法可能会暴露密钥,导致密钥被截获或篡改,从而威胁到加密数据的安全性

为了解决这个问题,出现了密钥交换算法,例如Diffie-Hellman算法。Diffie-Hellman算法允许通信双方在不安全的通信信道上协商一个共享密钥,而不需要事先共享任何秘密信息。通过该算法,通信双方可以在不直接传输密钥的情况下安全地协商出一个共享的密钥,从而实现安全的加密通信

DH算法是一种通过数学原理实现安全密钥交换的方法,它允许通信双方在不直接传输密钥的情况下协商出一个共享的密钥

综上所述,密钥交换算法的出现弥补了传统密钥传输方法的不足,在不安全的通信信道上安全地传输密钥,为加密通信提供了更加可靠的保障。


数学理论支持

Diffie-Hellman算法是一种用于安全地交换密钥的协议,通常用于在不安全的通信信道上建立共享密钥,以便进行加密通信。这个算法允许两个对等方在没有事先共享密钥的情况下,通过公开的交换来生成共享的密钥。Diffie-Hellman算法的核心思想是利用离散对数问题的困难性,使得即使在公开的通信信道上,攻击者也无法推导出共享密钥。

简单来说,Diffie-Hellman算法的步骤如下:

  1. 选取一个大素数p和一个原根g,并将它们公开。
  2. 每个对等方选择一个私密数(称为私钥),并将其保密。
  3. 每个对等方利用p、g和自己的私钥计算出一个公开的值(称为公钥)。
  4. 对等方交换公钥。
  5. 每个对等方使用自己的私钥和对方的公钥,计算出一个共享的密钥。

我们举个例子来看

  1. 甲方首先选择一个素数p和一个原根g,例如,p=97,g=5。这些参数是公开的,双方都知道。
  2. 甲方选择一个随机数a,例如,a=123,并计算A=g^a mod p,得到A=34。
  3. 甲方将p、g和A的值发送给乙方。
  4. 乙方收到甲方发送的参数后,选择一个随机数b,例如,b=456,并计算B=g^b mod p,得到B=75。同时,乙方计算出共享密钥s = A^b mod p,得到s=22。
  5. 乙方将B的值发送给甲方。
  6. 甲方收到乙方发送的B后,计算共享密钥s = B^a mod p,得到的结果与乙方计算的结果一样,都是22。

因此,最终双方都得到了相同的共享密钥s=22。需要注意的是,通过网络传输的参数p、g、A和B无法推算出密钥s,因为实际应用中选择的素数p非常大,计算s的复杂度很高,从而保证了密钥的安全性。

通过这种方式,甲乙双方在不直接传输密钥的情况下成功完成了密钥交换,从而实现了安全的通信。

由于Diffie-Hellman算法的数学基础比较复杂,它的安全性建立在一个数学难题上,即计算离散对数的困难性。攻击者需要解决这个数学难题才能推导出共享密钥,因此Diffie-Hellman算法被广泛应用于安全通信领域。

简单的Java实现示例:

import java.math.BigInteger;
import java.security.SecureRandom;

public class DiffieHellman {
    
    // 素数p
    private static final BigInteger p = new BigInteger("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
            + "29024E088A67CC74020BBEA63B139B22514A08798E3404DD"
            + "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
            + "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED"
            + "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D"
            + "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F"
            + "83655D23DCA3AD961C62F356208552BB9ED529077096966D"
            + "670C354E4ABC9804F1746C08CA237327FFFFFFFFFFFFFFFF", 16);
    
    // 原根g
    private static final BigInteger g = BigInteger.valueOf(2);
    
    // 生成私钥
    public static BigInteger generatePrivateKey() {
        SecureRandom random = new SecureRandom();
        BigInteger privateKey = new BigInteger(p.bitLength(), random);
        // 私钥必须小于p
        return privateKey.mod(p);
    }
    
    // 计算公钥
    public static BigInteger calculatePublicKey(BigInteger privateKey) {
        return g.modPow(privateKey, p);
    }
    
    // 计算共享密钥
    public static BigInteger calculateSharedSecret(BigInteger privateKey, BigInteger otherPublicKey) {
        return otherPublicKey.modPow(privateKey, p);
    }

    public static void main(String[] args) {
        // Alice生成私钥和公钥
        BigInteger alicePrivateKey = generatePrivateKey();
        BigInteger alicePublicKey = calculatePublicKey(alicePrivateKey);
        System.out.println("Alice's Private Key: " + alicePrivateKey);
        System.out.println("Alice's Public Key: " + alicePublicKey);
        
        // Bob生成私钥和公钥
        BigInteger bobPrivateKey = generatePrivateKey();
        BigInteger bobPublicKey = calculatePublicKey(bobPrivateKey);
        System.out.println("Bob's Private Key: " + bobPrivateKey);
        System.out.println("Bob's Public Key: " + bobPublicKey);
        
        // Alice和Bob计算共享密钥
        BigInteger aliceSharedSecret = calculateSharedSecret(alicePrivateKey, bobPublicKey);
        BigInteger bobSharedSecret = calculateSharedSecret(bobPrivateKey, alicePublicKey);
        
        // 验证共享密钥是否相同
        System.out.println("Alice's Shared Secret: " + aliceSharedSecret);
        System.out.println("Bob's Shared Secret: " + bobSharedSecret);
        System.out.println("Shared Secrets Match: " + aliceSharedSecret.equals(bobSharedSecret));
    }
}

这个示例演示了两个对等方(Alice和Bob)如何使用Diffie-Hellman算法协商共享密钥。每个对等方都生成一个私钥,并计算出对应的公钥。然后,它们交换公钥,并使用自己的私钥和对方的公钥计算出共享的密钥。最后,它们验证计算得到的共享密钥是否相同


使用Java实现DH算法

package com.artisan.securityalgjava.DiffieHellman;

import java.math.BigInteger;
import java.security.*;
import java.security.spec.*;

import javax.crypto.KeyAgreement;

/**
 * @author 小工匠
 * @version 1.0
 * @mark: show me the code , change the world
 */
public class DHExample {
    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");
            // 自己的PrivateKey
            keyAgreement.init(this.privateKey);
            // 对方的PublicKey
            keyAgreement.doPhase(receivedPublicKey, true);
            // 生成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));
    }
}
    

输出

Name: Bob
Private key: 3081d202010030819706092a864886f70d010301308189024100fca682ce8e12caba26efccf7110e526db078b05edecbcd1eb4a208f3ae1617ae01f35b91a47e6df63413c5e12ed0899bcd132acd50d99151bdc43ee737592e170240678471b27a9cf44ee91a49c5147db1a9aaf244f05a434d6486931d2d14271b9e35030b71fd73da179069b32e2935630e1c2062354d0da20a6c416e50be794ca4020201800433023100d28250d0fe90e3b85afa61ada18204c97f3e4073618cfcdbeea3ca18336e42bda8d1143b976a34eac1954e94f1e26f76
Public key: 3081df30819706092a864886f70d010301308189024100fca682ce8e12caba26efccf7110e526db078b05edecbcd1eb4a208f3ae1617ae01f35b91a47e6df63413c5e12ed0899bcd132acd50d99151bdc43ee737592e170240678471b27a9cf44ee91a49c5147db1a9aaf244f05a434d6486931d2d14271b9e35030b71fd73da179069b32e2935630e1c2062354d0da20a6c416e50be794ca4020201800343000240172702a9a278c0fb05770ae3904e2002dbc3cd5fa1bb98263053c3ca871228139481cb619f3d2178ce591c7c1caf7fccb2092c3bf1fb00d2dd00f4b308c283d4
Secret key: f2b99ef3c77657dbe06e1c9b037c9e5ae0b44ee294239b2bee0166d4d6f9a05d0a9c00bf669e05562fe83d63049d23a7f6a4ac1ab3a0aae5e9169d0a4889141c
Name: Alice
Private key: 3081d202010030819706092a864886f70d010301308189024100fca682ce8e12caba26efccf7110e526db078b05edecbcd1eb4a208f3ae1617ae01f35b91a47e6df63413c5e12ed0899bcd132acd50d99151bdc43ee737592e170240678471b27a9cf44ee91a49c5147db1a9aaf244f05a434d6486931d2d14271b9e35030b71fd73da179069b32e2935630e1c2062354d0da20a6c416e50be794ca4020201800433023100a5e352efc6a8cbf155fd780fdfdac894327960cc025f71c3a17739d2fba898ab92fef6286656408265db80a4ab17d1cb
Public key: 3081df30819706092a864886f70d010301308189024100fca682ce8e12caba26efccf7110e526db078b05edecbcd1eb4a208f3ae1617ae01f35b91a47e6df63413c5e12ed0899bcd132acd50d99151bdc43ee737592e170240678471b27a9cf44ee91a49c5147db1a9aaf244f05a434d6486931d2d14271b9e35030b71fd73da179069b32e2935630e1c2062354d0da20a6c416e50be794ca40202018003430002400e8f0bee5867c4964a71ff3e1ca0b777f05a38fd7bae6255c42af346f4464465e77390254ed6dc474451b0e9a6b7e1d9c15fc2058adf4bbe64622a4e726c353b
Secret key: f2b99ef3c77657dbe06e1c9b037c9e5ae0b44ee294239b2bee0166d4d6f9a05d0a9c00bf669e05562fe83d63049d23a7f6a4ac1ab3a0aae5e9169d0a4889141c

DH算法的缺点

Diffie-Hellman(DH)算法是一种强大的密钥协商协议,但它也存在一些缺点:

  1. 中间人攻击(Man-in-the-Middle Attack): DH算法本身并未提供对通信双方身份的认证,因此受到中间人攻击的威胁。在DH密钥交换过程中,中间人可以拦截并篡改通信双方的公钥,然后将自己的公钥发送给双方,从而获取他们之间的共享密钥并进行窃听或篡改通信内容。

  2. 密钥验证问题: DH算法生成的共享密钥虽然是安全的,但双方无法确保对方是否真的持有与其公钥相对应的私钥。如果通信双方无法进行身份验证,攻击者可能会冒充其中一方,从而利用共享密钥进行欺骗或篡改通信。

  3. 密钥协商效率: DH算法的密钥协商过程需要大量的计算和通信开销,尤其是在选择较大的素数p和底数g时,计算复杂度更高。这可能会影响通信的效率和性能。

  4. 依赖于安全的素数: DH算法的安全性取决于选择的素数p和底数g的安全性。如果选择的素数不够大或者底数不够随机,可能会导致算法受到攻击。

综上所述,虽然Diffie-Hellman算法在密钥交换方面具有重要的优势,但在实际应用中,必须结合其他安全机制来解决身份认证和中间人攻击等问题,以确保通信的安全性和可靠性。

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1482162.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

代码随想录刷题笔记 DAY 37 | 动态规划理论基础 | 斐波那契数 No.509 | 爬楼梯 No.70 | 使用最小花费爬楼梯 No.746

文章目录 Day 3700. 动态规划理论基础01. 斐波那契数&#xff08;No. 509&#xff09;<1> 题目<2> 笔记<3> 代码 02. 爬楼梯&#xff08;No. 70&#xff09;<1> 题目<2> 笔记<3> 代码 03. 使用最小花费爬楼梯&#xff08;No. 746&#xff…

Project_Euler-44 题解

Project_Euler-44 题解 题目 思路 题目给出了一个性质&#xff0c;让我在对应性质的数据中找出目标值&#xff0c;这种问题首先想到的就是枚举。 我们可以枚举 P k P_k Pk​ &#xff0c;对于每一个 P k P_k Pk​ &#xff0c;我们再枚举 P j P_j Pj​&#xff0c; P j P_…

阿尔卡特Adixen ADP/ADS 系列 2 干泵使用说明

阿尔卡特Adixen ADP/ADS 系列 2 干泵使用说明

《求生之路2》服务器如何选择合适的内存和CPU核心数,以避免丢包和延迟高?

根据求生之路2服务器的实际案例分析选择合适的内存和CPU核心数以避免丢包和延迟高的问题&#xff0c;首先需要考虑游戏的类型和对服务器配置的具体要求。《求生之路2》作为一款多人在线射击游戏&#xff0c;其服务器和网络优化对于玩家体验至关重要。 首先&#xff0c;考虑到游…

Android修行手册-集成Python开发环境

Unity3D特效百例案例项目实战源码Android-Unity实战问题汇总游戏脚本-辅助自动化Android控件全解手册再战Android系列Scratch编程案例软考全系列Unity3D学习专栏蓝桥系列ChatGPT和AIGC &#x1f449;关于作者 专注于Android/Unity和各种游戏开发技巧&#xff0c;以及各种资源分…

redis实现分布式全局唯一id

目录 一、前言二、如何通过Redis设计一个分布式全局唯一ID生成工具2.1 使用 Redis 计数器实现2.2 使用 Redis Hash结构实现 三、通过代码实现分布式全局唯一ID工具3.1 导入依赖配置3.2 配置yml文件3.3 序列化配置3.4 编写获取工具3.5 测试获取工具 四、运行结果 一、前言 在很…

PySide6+VSCode Python可视化环境搭建

#记住在cmd中运行&#xff0c;不要在vscode里运行&#xff0c;否则env会装到工程目录下 python -m venv env #env\Scripts\activate.bat pip install pyside6 下载本期源码 vscode装一个PYQT Integration插件&#xff0c;设置好两个路径&#xff08;下面有个脚本用于获取路径&…

陶瓷工业5G智能制造工厂数字孪生可视化平台,推进行业数字化转型

陶瓷工业5G智能制造工厂数字孪生可视化平台&#xff0c;推进行业数字化转型。在陶瓷工业领域&#xff0c;5G智能制造工厂数字孪生可视化平台的应用正在改变着行业的传统生产模式&#xff0c;推动着数字化转型的进程。本文将围绕这一主题展开探讨&#xff0c;分析数字孪生可视化…

Socket网络编程(四)——点对点传输场景方案

目录 场景如何去获取到TCP的IP和Port&#xff1f;UDP的搜索IP地址、端口号方案UDP搜索取消实现相关的流程&#xff1a;代码实现逻辑服务端实现客户端实现UDP搜索代码执行结果 TCP点对点传输实现代码实现步骤点对点传输测试结果 源码下载 场景 在一个局域网当中&#xff0c;不知…

Win11系统安装安卓子系统教程

随着Win11系统的不断普及&#xff0c;以及硬件设备的更新换代&#xff0c;我相信很多同学都已经更新并使用到了最新的Win11系统。那么&#xff0c;Win11系统最受期待的功能“Windows Subsystem for Android”&#xff08;简称WSA&#xff09;&#xff0c;即《安卓子系统》。他可…

CAPL组装IPv4分片包的三种思路(2)

2、使用CAPL的函数自动生成一条完整的ICMPv4 Echo Request报文,然后把数据手动放入两个分片报文中 首先生成一条完整的icmp报文: ethernetPacket ppkt1;//icmpv4 echo requestbyte data[1] = {10};//icmpv4 echo request datappkt1.icmpv4.echo…

湖南湘菜 7页面 美食主题 带设计说明 美食网页设计制作 HTML美食网页成品 美食网页成品 HTML美食网页设计

湖南湘菜 7页面 美食主题 带设计说明 jquery图片轮播特效 滚动文字 aspaccess数据库注册登录留言功能 美食网页设计制作 HTML美食网页成品 美食网页成品 HTML美食网页设计制作 前端美食网页开发 热门美食特产网页制作 静态网页成品 asp/php动态网站设计制作DW定制定做 web前…

佛山50公里徒步组团|真北敏捷社区佛山敏捷DevOps社区

真北敏捷社区&佛山敏捷DevOps社区有两个宗旨&#xff0c;一是求知&#xff0c;二是连接。连接有识之士&#xff0c;同修友士之识。峨峨乎高山&#xff0c;洋洋乎流水。谈笑有鸿儒&#xff0c;往来无白丁。 《柳叶刀》上的研究显示&#xff0c;运动的情绪价值&#xff0c;相…

GitHub Copilot extension activation error: ‘No access to GitHub Copilot found‘

好不容易学生认证通过了&#xff0c;打开vscode用copilot结果一直报这个错误。我的原因是&#xff1a;还未给copilot授权&#xff0c; 通过了学生认证后要进入这里进行授权&#xff1a;

数据分析-Pandas数据探查初步圆饼图

数据分析-Pandas数据探查初步圆饼图 数据分析和处理中&#xff0c;难免会遇到各种数据&#xff0c;那么数据呈现怎样的规律呢&#xff1f;不管金融数据&#xff0c;风控数据&#xff0c;营销数据等等&#xff0c;莫不如此。如何通过图示展示数据的规律&#xff1f; 数据表&am…

PHP使用imap_open读取QQ邮箱

PHP代码&#xff1a; /** PHP使用imap_open读取QQ邮箱imap_open 官方文档&#xff1a;https://www.php.net/function.imap_open */function parse_mailstr($subject) {$a explode(?,$subject);$n count($a);$a $a[$n-2];return base64_decode($a); }function recevie_emai…

点亮城市名片丨计讯物联智慧灯杆系统在通讯基地的成功应用

项目背景 在国家新型城镇化大背景下&#xff0c;十四五规划纲要强调“加快数字化发展&#xff0c;建设数字中国”&#xff0c;明确提出“以数字化助推城乡发展和治理模式创新”&#xff0c;全面提高城市的运行效率和宜居程度。 项目概况 为满足灯杆灯光亮度的远程智能管理、对…

docker构建hyperf环境

一&#xff0c;构建hyperf 镜像 官网git https://github.com/hyperf/hyperf-docker 使用dockerfile构建镜像 根据需要这里我使用8.1 swoole版本的镜像 在/home/hyperfdocker 目录中新建一个Dockerfile文件&#xff0c;将这个git上的Dockerfile内容复制粘贴进去 docker build…

Linux--使用 Haproxy搭建Web群集

1、 案例概述 Haproxy是目前比较流行的一种群集调度工具&#xff0c;同类群集调度工具有很多&#xff0c;如LVS 和 Nginx。相比较而言&#xff0c;LVS性能最好&#xff0c;但是搭建相对复杂&#xff1a;Nginx的upstream 模块支持群集功能&#xff0c;但是对群集节点健康检查功能…

java 基础上(1)(核心知识搭配代码)

前言 java的学习分为了上部分以及下部分进行学习&#xff0c;上部分就是对于java的基础知识&#xff0c;面向对象上&#xff0c;面向对象下&#xff0c;异常操作&#xff0c;javaApi&#xff1b;下部主要是集合&#xff0c;泛型&#xff0c;反射&#xff0c;IO流&#xff0c;J…