1、DH算法的简介

DH,全称为“Diffie-Hellman”,他是一种确保共享KEY安全穿越不安全网络的方法,也就是常说的密钥一致协议。由公开密钥密码体制的奠基人Diffie和Hellman所提出的一种思想。

简单的说就是允许两名用户在公开媒体上交换信息以生成“一致”的、可以共享的密钥。也就是由甲方产出一对密钥(公钥、私钥),乙方依照甲方公钥产生乙方密钥对(公钥、私钥)。
 以此为基线,作为数据传输保密基础,同时双方使用同一种对称加密算法构建本地密钥(SecretKey)对数据加密。这样,在互通了本地密钥(SecretKey)算法后,甲乙双方公开自己的公钥,使用对方的公钥和刚才产生的私钥加密数据,同时可以使用对方的公钥和自己的私钥对数据解密。不单单是甲乙双方两方,可以扩展为多方共享数据通讯,这样就完成了网络交互数据的安全通讯!
2、DH算法的通信模型
    2.1  甲方将自己的公钥发给乙方
   
    2.2  乙方根据甲方发来的公钥,生成自己的公钥和私钥
   
    2.3  乙方将自己的公钥发送给甲方
    
    2.4  甲方和乙方,生成一样的秘钥。用于加密数据
 
3、DH算法的数学原理
4、JDK实现
5、DH算法的编程步骤
5.1  生成密钥对
5.2  使用公钥私钥生成本地密钥
6、DH算法的实现
DHUtil.java
import java.security.InvalidKeyException;
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 java.util.HashMap;
import java.util.Map;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.KeyAgreement;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.interfaces.DHPrivateKey;
import javax.crypto.interfaces.DHPublicKey;
import javax.crypto.spec.DHParameterSpec;public class DHUtil {/*** 定义加密方式*/private static final String KEY_DH = "DH";public static final String PUBLIC_KEY = "DHPublicKey";public static final String PRIVATE_KEY = "DHPrivateKey";// 开始生成本地密钥SecretKey 密钥算法为对称密码算法// 可以为 DES DES AESpublic static final String KEY_DH_DES = "DES";/*** 甲方初始化并返回密钥对* * @return*/public static Map<String, Object> initKey() {try {// 实例化密钥对生成器KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(KEY_DH);// 初始化密钥对生成器 默认是1024 512-1024 & 64的倍数keyPairGenerator.initialize(1024);// 生成密钥对KeyPair keyPair = keyPairGenerator.generateKeyPair();// 得到甲方公钥DHPublicKey publicKey = (DHPublicKey) keyPair.getPublic();// 得到甲方私钥DHPrivateKey privateKey = (DHPrivateKey) keyPair.getPrivate();// 将公钥和私钥封装在Map中, 方便之后使用Map<String, Object> keyMap = new HashMap<String, Object>();keyMap.put(PUBLIC_KEY, publicKey);keyMap.put(PRIVATE_KEY, privateKey);return keyMap;} catch (Exception e) {throw new RuntimeException(e);}}/*** 乙方根据甲方公钥初始化并返回密钥对* * @param key*            甲方的公钥* @return*/public static Map<String, Object> initKey(byte[] key) {try {// 将甲方公钥从字节数组转换为PublicKeyX509EncodedKeySpec keySpec = new X509EncodedKeySpec(key);// 实例化密钥工厂KeyFactory keyFactory = KeyFactory.getInstance(KEY_DH);// 产生甲方公钥pubKeyDHPublicKey dhPublicKey = (DHPublicKey) keyFactory.generatePublic(keySpec);// 剖析甲方公钥,得到其参数DHParameterSpec dhParameterSpec = dhPublicKey.getParams();// 实例化密钥对生成器KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(KEY_DH);// 用甲方公钥初始化密钥对生成器keyPairGenerator.initialize(dhParameterSpec);// 产生密钥对KeyPair keyPair = keyPairGenerator.generateKeyPair();// 得到乙方公钥DHPublicKey publicKey = (DHPublicKey) keyPair.getPublic();// 得到乙方私钥DHPrivateKey privateKey = (DHPrivateKey) keyPair.getPrivate();// 将公钥和私钥封装在Map中, 方便之后使用Map<String, Object> keyMap = new HashMap<String, Object>();keyMap.put(PUBLIC_KEY, publicKey);keyMap.put(PRIVATE_KEY, privateKey);return keyMap;} catch (Exception e) {throw new RuntimeException(e);}}/*** 根据对方的公钥和自己的私钥生成 本地密钥,返回的是SecretKey对象的字节数组* * @param publicKey*            公钥* @param privateKey*            私钥* @return*/public static byte[] getSecretKeyBytes(byte[] publicKey, byte[] privateKey) {try {// 实例化密钥工厂KeyFactory keyFactory = KeyFactory.getInstance(KEY_DH);// 将公钥从字节数组转换为PublicKeyX509EncodedKeySpec pubKeySpec = new X509EncodedKeySpec(publicKey);PublicKey pubKey = keyFactory.generatePublic(pubKeySpec);// 将私钥从字节数组转换为PrivateKeyPKCS8EncodedKeySpec priKeySpec = new PKCS8EncodedKeySpec(privateKey);PrivateKey priKey = keyFactory.generatePrivate(priKeySpec);// 准备根据以上公钥和私钥生成本地密钥SecretKey// 先实例化KeyAgreementKeyAgreement keyAgreement = KeyAgreement.getInstance(KEY_DH);// 用自己的私钥初始化keyAgreementkeyAgreement.init(priKey);// 结合对方的公钥进行运算keyAgreement.doPhase(pubKey, true);// 开始生成本地密钥SecretKey 密钥算法为对称密码算法SecretKey secretKey = keyAgreement.generateSecret(KEY_DH_DES);return secretKey.getEncoded();} catch (Exception e) {throw new RuntimeException(e);}}/*** 根据对方的公钥和自己的私钥生成 本地密钥,返回的是SecretKey对象* * @param publicKey*            公钥* @param privateKey*            私钥* @return*/public static SecretKey getSecretKey(byte[] publicKey, byte[] privateKey) {try {// 实例化密钥工厂KeyFactory keyFactory = KeyFactory.getInstance(KEY_DH);// 将公钥从字节数组转换为PublicKeyX509EncodedKeySpec pubKeySpec = new X509EncodedKeySpec(publicKey);PublicKey pubKey = keyFactory.generatePublic(pubKeySpec);// 将私钥从字节数组转换为PrivateKeyPKCS8EncodedKeySpec priKeySpec = new PKCS8EncodedKeySpec(privateKey);PrivateKey priKey = keyFactory.generatePrivate(priKeySpec);// 准备根据以上公钥和私钥生成本地密钥SecretKey// 先实例化KeyAgreementKeyAgreement keyAgreement = KeyAgreement.getInstance(KEY_DH);// 用自己的私钥初始化keyAgreementkeyAgreement.init(priKey);// 结合对方的公钥进行运算keyAgreement.doPhase(pubKey, true);// 开始生成本地密钥SecretKey 密钥算法为对称密码算法SecretKey secretKey = keyAgreement.generateSecret(KEY_DH_DES);return secretKey;} catch (Exception e) {throw new RuntimeException(e);}}/*** 从 Map 中取得公钥* * @param keyMap* @return*/public static byte[] getPublicKey(Map<String, Object> keyMap) {DHPublicKey key = (DHPublicKey) keyMap.get(PUBLIC_KEY);return key.getEncoded();}/*** 从 Map 中取得私钥* * @param keyMap* @return*/public static byte[] getPrivateKey(Map<String, Object> keyMap) {DHPrivateKey key = (DHPrivateKey) keyMap.get(PRIVATE_KEY);return key.getEncoded();}/*** DH 加密* * @param data*            带加密数据* @param publicKey*            甲方公钥* @param privateKey*            乙方私钥* @return*/public static byte[] encryptDH(byte[] data, byte[] publicKey,byte[] privateKey) {byte[] bytes = null;try {//SecretKey secretKey = getSecretKey(publicKey, privateKey);// 数据加密Cipher cipher = Cipher.getInstance(secretKey.getAlgorithm());cipher.init(Cipher.ENCRYPT_MODE, secretKey);bytes = cipher.doFinal(data);} catch (NoSuchAlgorithmException e) {e.printStackTrace();} catch (NoSuchPaddingException e) {e.printStackTrace();} catch (InvalidKeyException e) {e.printStackTrace();} catch (BadPaddingException e) {e.printStackTrace();} catch (IllegalBlockSizeException e) {e.printStackTrace();}return bytes;}/*** DH 解密* * @param data*            待解密数据* @param publicKey*            乙方公钥* @param privateKey*            甲方私钥* @return*/public static byte[] decryptDH(byte[] data, byte[] publicKey,byte[] privateKey) {byte[] bytes = null;try {//SecretKey secretKey = getSecretKey(publicKey, privateKey);// 数据加密Cipher cipher = Cipher.getInstance(secretKey.getAlgorithm());cipher.init(Cipher.DECRYPT_MODE, secretKey);bytes = cipher.doFinal(data);} catch (NoSuchAlgorithmException e) {e.printStackTrace();} catch (NoSuchPaddingException e) {e.printStackTrace();} catch (InvalidKeyException e) {e.printStackTrace();} catch (BadPaddingException e) {e.printStackTrace();} catch (IllegalBlockSizeException e) {e.printStackTrace();}return bytes;}}

字节数组转16进制

public class BytesToHex {public static String fromBytesToHex(byte[] resultBytes) {StringBuilder builder = new StringBuilder();for (int i = 0; i < resultBytes.length; i++) {if (Integer.toHexString(0xFF & resultBytes[i]).length() == 1) {builder.append("0").append(Integer.toHexString(0xFF & resultBytes[i]));} else {builder.append(Integer.toHexString(0xFF & resultBytes[i]));}}return builder.toString();}}

测试代码

import java.util.Map;public class Test {// 待加密的明文public static final String DATA = "test";public static void main(String[] args) throws Exception {/* Test DH */// 甲方公钥byte[] publicKey1;// 甲方私钥byte[] privateKey1;// 甲方本地密钥byte[] secretKey1;// 乙方公钥byte[] publicKey2;// 乙方私钥byte[] privateKey2;// 乙方本地密钥byte[] secretKey2;// 初始化密钥 并生成甲方密钥对Map<String, Object> keyMap1 = DHUtil.initKey();publicKey1 = DHUtil.getPublicKey(keyMap1);privateKey1 = DHUtil.getPrivateKey(keyMap1);System.out.println("DH 甲方公钥 : " + BytesToHex.fromBytesToHex(publicKey1));System.out.println("DH 甲方私钥 : "+ BytesToHex.fromBytesToHex(privateKey1));// 乙方根据甲方公钥产生乙方密钥对Map<String, Object> keyMap2 = DHUtil.initKey(publicKey1);publicKey2 = DHUtil.getPublicKey(keyMap2);privateKey2 = DHUtil.getPrivateKey(keyMap2);System.out.println("DH 乙方公钥 : " + BytesToHex.fromBytesToHex(publicKey2));System.out.println("DH 乙方私钥 : "+ BytesToHex.fromBytesToHex(privateKey2));// 对于甲方, 根据其私钥和乙方发过来的公钥, 生成其本地密钥secretKey1secretKey1 = DHUtil.getSecretKeyBytes(publicKey2, privateKey1);System.out.println("DH 甲方 本地密钥 : "+ BytesToHex.fromBytesToHex(secretKey1));// 对于乙方, 根据其私钥和甲方发过来的公钥, 生成其本地密钥secretKey2secretKey2 = DHUtil.getSecretKeyBytes(publicKey1, privateKey2);System.out.println("DH 乙方 本地密钥 : "+ BytesToHex.fromBytesToHex(secretKey2));// ---------------------------// 测试数据加密和解密System.out.println("加密前的数据" + DATA);// 甲方进行数据的加密// 用的是甲方的私钥和乙方的公钥byte[] encryptDH = DHUtil.encryptDH(DATA.getBytes(), publicKey2,privateKey1);System.out.println("加密后的数据 字节数组转16进制显示"+ BytesToHex.fromBytesToHex(encryptDH));// 乙方进行数据的解密// 用的是乙方的私钥和甲方的公钥byte[] decryptDH = DHUtil.decryptDH(encryptDH, publicKey1, privateKey2);System.out.println("解密后数据:" + new String(decryptDH));}
}

非对称密码之DH密钥交换算法相关推荐

  1. 从数学角度讲解DH密钥交换算法、非对称加密、数字签名

    背景知识 数字可以分为两大部分: 不可再分的数:prime number质数 可以再分的数:composite number 和数 每个数字可以描述为一个"锁" 每个数字有且只有一 ...

  2. 密码学 专题 DH密钥交换算法

    注意事项: SSL中密钥交换算法有6种:无效(没有密钥交换).RSA.匿名Diffie-Hellman.暂时Diffie-Hellman.固定Diffie-Hellman.Fortezza 生成对话密 ...

  3. DH密钥交换算法的python实现——Diffie–Hellman key exchange

    文章目录 前言 DH交换算法简介 DH算法 Python算法的实现 后记 前言 DH交换算法简介 Deffie-Hellman(简称 DH) 密钥交换是最早的密钥交换算法之一,它使得通信的双方能在非安 ...

  4. java dh算法_dh密钥交换算法java

    dh密钥交换算法java 迪菲-赫尔曼密钥交换(Diffie–Hellman key exchange,简称"D–H") 是一种安全协议. 它可以让双方在完全没有对方任何预先信息的 ...

  5. 密钥交换算法(DH算法)

    背景 对称加密算法通过密钥解决了数据加密问题,但是如何安全的传输密钥成为了下一个问题.如果密钥被窃取了,那对称加密数据就没有什么意义了.密钥交换算法(Diffie-Hellman算法 or DH算法) ...

  6. java dh密钥交换_java-信息安全(八)-迪菲-赫尔曼(DH)密钥交换

    概述 信息安全基本概念: DH(Diffie–Hellman key exchange,迪菲-赫尔曼密钥交换) DH 是一种安全协议,,一种确保共享KEY安全穿越不安全网络的方法,它是OAKLEY的一 ...

  7. Nodejs进阶:使用DiffieHellman密钥交换算法

    简介 Diffie-Hellman(简称DH)是密钥交换算法之一,它的作用是保证通信双方在非安全的信道中安全地交换密钥.目前DH最重要的应用场景之一,就是在HTTPS的握手阶段,客户端.服务端利用DH ...

  8. 密钥交换算法 - Java加密与安全

    密钥交换算法我们在使用对称加密算法的时候,我们用的是同一个密钥key 我们以AES加密为例,当我们需要加密明文,我们需要一个随机生成的key,作为密钥进行加解密,最后我们的问题是如何传递密钥 因为不给 ...

  9. Android笔记-对称与非对称加密及DH密钥交换

    对称加密算法 AES:Advanced Encryption Standard,高级加密标准. 算法逻辑是这样的: 加密:C = E(K, P)    其中P为明文,K为密钥,C为密文: 解密:P = ...

  10. DH密钥交换在实践中的安全问题

    本文提出了logjam,CVE-2015-4000,告诫我们不要兼容因为安全问题而被抛弃的旧特性. 主要内容来自论文和网络,本文为内容摘要和背景知识(当然,也算是翻译). forward secrec ...

最新文章

  1. 查看文件命令cat,more,less,tail,tac,nl,od---linux学习笔记
  2. Enabling Redo Log Transport Compression with active dataguard
  3. 微信公众号管理系统 RhaPHP1.2.5更新啦!
  4. Ogre共享骨骼与两种骨骼驱动方法
  5. kafka中LEO和HW
  6. 使用GCC生成无格式二进制文件(plain binary files)
  7. LeetCode 1395. 统计作战单位数(蛮力法)
  8. ansible基本模块-shell
  9. MOS管及MOS管的驱动电路设计
  10. 模拟新浪新闻在线聊天功能
  11. 抖音等多款软件涉代码抄袭,字节跳动被诉赔22.74亿元;iPhone12系统更新后性能退回3年前;Qt 6.1正式发布|极客头条...
  12. LeetCode 85.最大矩形
  13. 不知不觉,写了一个编译器(一)
  14. 毕业设计之 - 题目:基于LSTM的预测算法 - 股票预测 天气预测 房价预测
  15. python学生成绩表_通过excel表格分析学生成绩
  16. 【Houdini MAYA】从MAYA到Houdini入门学习笔记(三)
  17. QuickJS 数字字面量解析
  18. 关于D3D9 Stretchrect
  19. ffmpeg将mp4转为m4a,m4a转mp3,mp3转ogg
  20. 兆骑科创高层次人才引进双创平台,双创服务,赛事路演

热门文章

  1. 独立站卖家如何借势营销
  2. CIKM 2019 挑战杯「用户行为预测」冠军方案:层次GNN模型在推荐中的应用
  3. ubuntu进行apt-get时候出现Package xxx is not available, but is referred to by another package 错误
  4. 简单三招,教你做个app
  5. 机器人编程语言有哪些? 这5大编程语言的优缺点你都了解?
  6. Linux高级命令(一)
  7. dojo和ArcGIS
  8. 【前端】基于layui写的一个高级搜索(筛选)功能
  9. boost::geometry简介,真香
  10. Python爬虫入门4:使用IE浏览器获取网站访问的http信息