【Java小工匠聊密码学】--非对称加密--DH密钥交换算法

简介: 1、DH密钥交换概述Diffie-Hellman由Whitfield Diffie和Martin Hellman在1976年公布的一种密钥一致性算法。Diffie-Hellman是一种建立密钥的方法,而不是加密方法。

1、DH密钥交换概述

Diffie-Hellman由Whitfield Diffie和Martin Hellman在1976年公布的一种密钥一致性算法。Diffie-Hellman是一种建立密钥的方法,而不是加密方法。然而,它所产生的密钥可用于加密、进一步的密钥管理或任何其它的加密方式。Diffie-Hellman密钥交换算法及其优化首次发表的公开密钥算法出现在Diffie和Hellman的论文中,这篇影响深远的论文奠定了公开密钥密码编码学。

2、DH密钥交换算法原理

2.1、使用颜色形象描述

设想这样一个场景,Alice(A)和Bob(B),他们想在不见面的情况下秘密约定出一种颜色,但他们互相沟通的信息都会被公开,应该怎么办呢?


DH密钥交换算法

秘密在于,颜色混合是一种“不可逆”的操作,当双方交换颜色时,尽管我们知道他们交换的颜色都是由一份黄色和另一份其他颜色混合得到的,但我们还是无法或者很难得到他们的私密颜色。

2.2、数学算法

2.2.1 算法背景

乘方得逆运算称为对数运算,比如已知 7^x = 49 那么可知 x=log(7,49)=2。 对数运算非常容易,即使在数字很大的时候是,但如果是下面的情况 7^xmod13=8 。 求X的过程称为“离散对数”,就不那么容易了,在数字很大时几乎是一个不可能的运算,而DH秘钥交换就是利用了这种离散对数计算非常困难的特性来设计的。

2.2.2 取模运算规律

公式里的mod是取模运算,取模运算有几条基本的定律如下:
(a+b) mod P =(a mod P+b mod P) mod P
(a∗b) mod P = (a mod P∗b mod P) mod P
(a^b) mod P = (a mod P)^b) mod P

2.2.3 密钥交换流程

根据上面的公式,可以推导出一个非常重要的公式。
(G^(a∗b)) mod P=(G^a mod P)^b mod P=(G^b mod P)^a mod P
根据这个公式,我们可以向上面交换颜色那样设计出一个秘密交换数字的流程出来。


交换流程

最终两个人得到的秘密数字都是g^(ab) mod p,而窃听者仅从p,g,A,B四个公开信息,是无法得到这个秘密数字的!

2.2.4举例说明

第1步.爱丽丝与鲍伯协定使用p=23以及g=5.
第2步.爱丽丝选择一个秘密整数a=6, 计算A = g^a mod p并发送给鲍伯。 A = 5^6 mod 23 = 8.
第3步.鲍伯选择一个秘密整数b=15, 计算B = g^b mod p并发送给爱丽丝。
B = 5^15 mod 23 = 19.
第4步.爱丽丝计算
s = B a mod p
19^6 mod 23 = 2.
第5步.鲍伯计算s = A b mod p
8^15 mod 23 = 2.

3、DH密钥交换算用途

可以用作对称加密算法中,双方约定的加密准则的交换(对方的公钥和自己的私钥计算的到秘密整数,可以作为双方的加密准则)。交换双方可以在不共享任何秘密的情况下协商出一个密钥。

4、中间人攻击

由于密钥交换本身并没有提供通讯双方的身份验证服务,因此它很容易受到中间人攻击。 一个中间人“丙”在信道的中央进行两次迪菲-赫尔曼密钥交换,一次和甲,另一次和乙,就能够成功的向甲假装自己是乙,反之亦然。而攻击者可以解密(读取和存储)任何一个人的信息并重新加密信息,然后传递给另一个人。因此通常都需要一个能够验证通讯双方身份的机制来防止这类攻击。

5、算法实现

5.1、JDK算法实现

package lzf.cipher;

import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

import javax.crypto.KeyAgreement;
import javax.crypto.SecretKey;
import javax.crypto.interfaces.DHPublicKey;
import javax.crypto.spec.DHParameterSpec;

import org.apache.commons.codec.binary.Hex;

/**
 * @author java小工匠
 */
public class DHUtils {

    // 甲方初始化密钥对
    public static KeyPair initKey() {
        try {
            // 实例化密钥对生成器
            KeyPairGenerator generator = KeyPairGenerator.getInstance("DH");
            // 初始化密钥对生成器参数 默认1024 512-1024之间64的倍数
            generator.initialize(1024);
            // 产生密钥对
            KeyPair keyPair = generator.genKeyPair();
            return keyPair;
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException(e.getMessage(), e);
        }
    }

    // 乙方初始化密钥生成对
    public static KeyPair initKey(byte[] key) {
        try {
            // 公钥从字节数组转换为PublicKey
            X509EncodedKeySpec keySpec = new X509EncodedKeySpec(key);
            // 实例化密钥工厂
            KeyFactory keyFactory = KeyFactory.getInstance("DH");
            // 还原甲方的公钥
            DHPublicKey dhPublicKey = (DHPublicKey) keyFactory.generatePublic(keySpec);
            // 剖析甲方公钥,得到其参数
            DHParameterSpec dhParameterSpec = dhPublicKey.getParams();
            // 实例化密钥对生成器
            KeyPairGenerator generator = KeyPairGenerator.getInstance("DH");
            // 使用得到的参数,初始化密钥生成器
            generator.initialize(dhParameterSpec);
            return generator.generateKeyPair();
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage(), e);
        }
    }

    // 获取公钥
    public static byte[] getPublicKey(KeyPair keyPair) {
        byte[] bytes = keyPair.getPublic().getEncoded();
        return bytes;
    }

    // 获取公钥
    public static String getPublicKeyStr(KeyPair keyPair) {
        byte[] bytes = keyPair.getPublic().getEncoded();
        return Hex.encodeHexString(bytes);
    }

    // 获取私钥
    public static byte[] getPrivateKey(KeyPair keyPair) {
        byte[] bytes = keyPair.getPrivate().getEncoded();
        return bytes;
    }

    // 获取公钥
    public static String getPrivateKeyStr(KeyPair keyPair) {
        byte[] bytes = keyPair.getPrivate().getEncoded();
        return Hex.encodeHexString(bytes);
    }

    // 生成本地密钥
    public static byte[] getSecretKey(byte[] publicKey, byte[] privateKey) {
        try {
            // 实例化密钥工厂
            KeyFactory keyFactory = KeyFactory.getInstance("DH");
            // 将公钥从字节数组转换为PublicKey
            X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKey);
            PublicKey pubKey = keyFactory.generatePublic(keySpec);
            // 将私钥从字节数组转换为PrivateKey
            PKCS8EncodedKeySpec privateSpec = new PKCS8EncodedKeySpec(privateKey);
            PrivateKey priKey = keyFactory.generatePrivate(privateSpec);
            // 先实例化KeyAgreement
            KeyAgreement keyAgreement = KeyAgreement.getInstance("DH");
            // 用自己的私钥初始化keyAgreement
            keyAgreement.init(priKey);
            // 结合对方的公钥进行运算
            keyAgreement.doPhase(pubKey, true);
            // 开始生成本地密钥SecretKey 密钥算法为对称密码算法
            SecretKey key = keyAgreement.generateSecret("AES");
            return key.getEncoded();
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage(), e);
        }
    }

    public static void main(String[] args) {
        KeyPair keyPair1 = initKey();
        byte[] publicKey1 = getPublicKey(keyPair1);
        String publicKeyStr1 = Hex.encodeHexString(publicKey1);
        byte[] privateKey1 = getPrivateKey(keyPair1);
        String privateKeyStr1 = Hex.encodeHexString(privateKey1);
        System.out.println("甲方公钥:" + publicKeyStr1);
        System.out.println("甲方私钥:" + privateKeyStr1);
        KeyPair keyPair2 = initKey(publicKey1);
        byte[] publicKey2 = getPublicKey(keyPair2);
        String publicKeyStr2 = Hex.encodeHexString(publicKey2);
        byte[] privateKey2 = getPrivateKey(keyPair2);
        String privateKeyStr2 = Hex.encodeHexString(privateKey2);
        System.out.println("乙方公钥:" + publicKeyStr2);
        System.out.println("乙方私钥:" + privateKeyStr2);
        byte[] secrectKey1 = getSecretKey(publicKey2, privateKey1);
        byte[] secrectKey2 = getSecretKey(publicKey1, privateKey2);
        String secrectKeyStr1 = Hex.encodeHexString(secrectKey1);
        String secrectKeyStr2 = Hex.encodeHexString(secrectKey2);
        System.out.println("甲方协议密钥:"+secrectKeyStr1);
        System.out.println("乙方协议密钥:"+secrectKeyStr2);
        System.out.println("甲=乙:"+secrectKeyStr1.equals(secrectKeyStr2));

    }
}

如果读完觉得有收获的话,欢迎点赞、关注、加公众号【小工匠技术圈】

个人公众号,欢迎关注,查阅更多精彩历史!

image
相关文章
|
7天前
|
算法 JavaScript 前端开发
消息摘要算法:MD5加密
消息摘要算法:MD5加密
18 1
|
1月前
|
算法 C# 数据安全/隐私保护
|
1月前
|
算法 安全 数据安全/隐私保护
支付系统---微信支付09------数字签名,现在Bob想要给Pink写一封信,信件的内容不需要加密,怎样能够保证信息的完整性,使用信息完整性的主要手段是摘要算法,散列函数,哈希函数,H称为数据指纹
支付系统---微信支付09------数字签名,现在Bob想要给Pink写一封信,信件的内容不需要加密,怎样能够保证信息的完整性,使用信息完整性的主要手段是摘要算法,散列函数,哈希函数,H称为数据指纹
|
1月前
|
算法 安全 网络安全
支付系统,网络安全06----支付安全---,机密性,加密算法,目前最流行的加密算法,AES加密算法,目前最流行的非对称加密算法RSA,对称加密和非对称加密的优缺点,非对称加密是基于非常复杂的数学算法
支付系统,网络安全06----支付安全---,机密性,加密算法,目前最流行的加密算法,AES加密算法,目前最流行的非对称加密算法RSA,对称加密和非对称加密的优缺点,非对称加密是基于非常复杂的数学算法
|
4天前
|
SQL 安全 网络安全
数字堡垒之下:网络安全漏洞与加密技术的较量
在数字化的浪潮中,网络安全成为了保护信息资产的坚固堡垒。本文将探讨网络安全面临的挑战,特别是安全漏洞和加密技术的重要性,同时强调提升个人和企业的安全意识的必要性。我们将从网络攻击者利用安全漏洞的方式谈起,深入到加密技术如何成为防御手段的核心,最后探讨如何通过教育和实践提高安全防范能力,共同构建更安全的网络环境。
|
3天前
|
SQL 人工智能 安全
网络安全漏洞、加密技术与安全意识的探索
【8月更文挑战第16天】在数字化时代,网络安全成为维护个人隐私和企业数据的关键防线。本文将深入探讨网络安全中的漏洞问题,分析加密技术在保护信息安全中的作用,并强调培养良好的安全意识的重要性。通过案例分析和理论阐述,旨在为读者提供一套全面的网络安全知识体系,帮助其在日益复杂的网络环境中保持警惕,采取有效措施防范潜在的网络威胁。
|
3天前
|
SQL 安全 网络安全
网络安全与信息安全:漏洞、加密技术与安全意识的探讨
【8月更文挑战第16天】在数字化时代,网络安全与信息安全成为维护社会稳定和保护个人隐私的重要议题。本文将深入探讨网络安全漏洞的成因、影响及防范措施,介绍加密技术的基本原理和应用,并强调提升公众的安全意识在构建网络防线中的重要性。通过分析当前网络安全面临的挑战,提出加强技术防护和提高用户安全意识的双重策略,旨在为读者提供全面的网络安全知识分享。
21 9
|
2天前
|
安全 网络安全 数据安全/隐私保护
数字堡垒的裂缝与修复:网络安全漏洞、加密技术与安全意识
【8月更文挑战第17天】 在数字化时代,网络安全如同一座保护数据资产不受侵犯的数字堡垒。然而,这座堡垒并非无懈可击,网络攻击者不断寻找并利用安全漏洞进行破坏活动。本文将深入浅出地探讨网络安全中常见的漏洞类型、加密技术的工作原理以及提升个人和组织安全意识的重要性,旨在为读者提供一套实用的网络安全知识框架,帮助加固数字堡垒的每一砖一瓦。
|
3天前
|
SQL 安全 算法
数字堡垒:网络安全漏洞与加密技术的博弈
在数字化时代,网络安全与信息安全成为保护个人隐私和企业数据不可或缺的防线。本文将探讨网络安全的薄弱环节,分析加密技术如何作为盾牌抵御网络威胁,并强调提升安全意识的重要性。通过深入浅出的方式,我们旨在为读者揭开网络安全的神秘面纱,提供实用的防护策略,确保每个人都能在信息海洋中安全航行。
10 1
|
3天前
|
安全 网络协议 网络安全
网络安全与信息安全:关于网络安全漏洞、加密技术、安全意识等方面的知识分享
在数字化时代,网络安全和信息安全已成为我们生活中不可或缺的一部分。本文将介绍网络安全漏洞的概念、加密技术的基本原理以及提高个人和企业的安全意识的重要性。通过深入浅出的方式,帮助读者了解如何保护自己免受网络攻击,并提高对网络安全的认识。
10 1