非对称密码之DH密钥交换算法
1、DH算法的简介
DH,全称为“Diffie-Hellman”,他是一种确保共享KEY安全穿越不安全网络的方法,也就是常说的密钥一致协议。由公开密钥密码体制的奠基人Diffie和Hellman所提出的一种思想。
![](/assets/blank.gif)
![](/assets/blank.gif)
![](/assets/blank.gif)
![](/assets/blank.gif)
![](/assets/blank.gif)
![](/assets/blank.gif)
![](/assets/blank.gif)
![](/assets/blank.gif)
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密钥交换算法相关推荐
- 从数学角度讲解DH密钥交换算法、非对称加密、数字签名
背景知识 数字可以分为两大部分: 不可再分的数:prime number质数 可以再分的数:composite number 和数 每个数字可以描述为一个"锁" 每个数字有且只有一 ...
- 密码学 专题 DH密钥交换算法
注意事项: SSL中密钥交换算法有6种:无效(没有密钥交换).RSA.匿名Diffie-Hellman.暂时Diffie-Hellman.固定Diffie-Hellman.Fortezza 生成对话密 ...
- DH密钥交换算法的python实现——Diffie–Hellman key exchange
文章目录 前言 DH交换算法简介 DH算法 Python算法的实现 后记 前言 DH交换算法简介 Deffie-Hellman(简称 DH) 密钥交换是最早的密钥交换算法之一,它使得通信的双方能在非安 ...
- java dh算法_dh密钥交换算法java
dh密钥交换算法java 迪菲-赫尔曼密钥交换(Diffie–Hellman key exchange,简称"D–H") 是一种安全协议. 它可以让双方在完全没有对方任何预先信息的 ...
- 密钥交换算法(DH算法)
背景 对称加密算法通过密钥解决了数据加密问题,但是如何安全的传输密钥成为了下一个问题.如果密钥被窃取了,那对称加密数据就没有什么意义了.密钥交换算法(Diffie-Hellman算法 or DH算法) ...
- java dh密钥交换_java-信息安全(八)-迪菲-赫尔曼(DH)密钥交换
概述 信息安全基本概念: DH(Diffie–Hellman key exchange,迪菲-赫尔曼密钥交换) DH 是一种安全协议,,一种确保共享KEY安全穿越不安全网络的方法,它是OAKLEY的一 ...
- Nodejs进阶:使用DiffieHellman密钥交换算法
简介 Diffie-Hellman(简称DH)是密钥交换算法之一,它的作用是保证通信双方在非安全的信道中安全地交换密钥.目前DH最重要的应用场景之一,就是在HTTPS的握手阶段,客户端.服务端利用DH ...
- 密钥交换算法 - Java加密与安全
密钥交换算法我们在使用对称加密算法的时候,我们用的是同一个密钥key 我们以AES加密为例,当我们需要加密明文,我们需要一个随机生成的key,作为密钥进行加解密,最后我们的问题是如何传递密钥 因为不给 ...
- Android笔记-对称与非对称加密及DH密钥交换
对称加密算法 AES:Advanced Encryption Standard,高级加密标准. 算法逻辑是这样的: 加密:C = E(K, P) 其中P为明文,K为密钥,C为密文: 解密:P = ...
- DH密钥交换在实践中的安全问题
本文提出了logjam,CVE-2015-4000,告诫我们不要兼容因为安全问题而被抛弃的旧特性. 主要内容来自论文和网络,本文为内容摘要和背景知识(当然,也算是翻译). forward secrec ...
最新文章
- 查看文件命令cat,more,less,tail,tac,nl,od---linux学习笔记
- Enabling Redo Log Transport Compression with active dataguard
- 微信公众号管理系统 RhaPHP1.2.5更新啦!
- Ogre共享骨骼与两种骨骼驱动方法
- kafka中LEO和HW
- 使用GCC生成无格式二进制文件(plain binary files)
- LeetCode 1395. 统计作战单位数(蛮力法)
- ansible基本模块-shell
- MOS管及MOS管的驱动电路设计
- 模拟新浪新闻在线聊天功能
- 抖音等多款软件涉代码抄袭,字节跳动被诉赔22.74亿元;iPhone12系统更新后性能退回3年前;Qt 6.1正式发布|极客头条...
- LeetCode 85.最大矩形
- 不知不觉,写了一个编译器(一)
- 毕业设计之 - 题目:基于LSTM的预测算法 - 股票预测 天气预测 房价预测
- python学生成绩表_通过excel表格分析学生成绩
- 【Houdini MAYA】从MAYA到Houdini入门学习笔记(三)
- QuickJS 数字字面量解析
- 关于D3D9 Stretchrect
- ffmpeg将mp4转为m4a,m4a转mp3,mp3转ogg
- 兆骑科创高层次人才引进双创平台,双创服务,赛事路演
热门文章
- 独立站卖家如何借势营销
- CIKM 2019 挑战杯「用户行为预测」冠军方案:层次GNN模型在推荐中的应用
- ubuntu进行apt-get时候出现Package xxx is not available, but is referred to by another package 错误
- 简单三招,教你做个app
- 机器人编程语言有哪些? 这5大编程语言的优缺点你都了解?
- Linux高级命令(一)
- dojo和ArcGIS
- 【前端】基于layui写的一个高级搜索(筛选)功能
- boost::geometry简介,真香
- Python爬虫入门4:使用IE浏览器获取网站访问的http信息