DH
Diffie-Hellman算法(D-H算法),密钥一致协议。是由公开密钥密码体制的奠基人Diffie和Hellman所提出的一种思想。简单的说就是允许两名用户在公开媒体上交换信息以生成"一致"的、可以共享的密钥。换句话说,就是由甲方产出一对密钥(公钥、私钥),乙方依照甲方公钥产生乙方密钥对(公钥、私钥)。以此为基线,作为数据传输保密基础,同时双方使用同一种对称加密算法构建本地密钥(SecretKey)对数据加密。这样,在互通了本地密钥(SecretKey)算法后,甲乙双方公开自己的公钥,使用对方的公钥和刚才产生的私钥加密数据,同时可以使用对方的公钥和自己的私钥对数据解密。不单单是甲乙双方两方,可以扩展为多方共享数据通讯,这样就完成了网络交互数据的安全通讯!该算法源于中国的同余定理——中国馀数定理。 



流程分析:



1.甲方构建密钥对儿,将公钥公布给乙方,将私钥保留;双方约定数据加密算法;乙方通过甲方公钥构建密钥对儿,将公钥公布给甲方,将私钥保留。

2.甲方使用私钥、乙方公钥、约定数据加密算法构建本地密钥,然后通过本地密钥加密数据,发送给乙方加密后的数据;乙方使用私钥、甲方公钥、约定数据加密算法构建本地密钥,然后通过本地密钥对数据解密。

3.乙方使用私钥、甲方公钥、约定数据加密算法构建本地密钥,然后通过本地密钥加密数据,发送给甲方加密后的数据;甲方使用私钥、乙方公钥、约定数据加密算法构建本地密钥,然后通过本地密钥对数据解密。



通过java代码实现如下:Coder类见 Java加密技术(一)

  1. import java.security.Key;
  2. import java.security.KeyFactory;
  3. import java.security.KeyPair;
  4. import java.security.KeyPairGenerator;
  5. import java.security.PublicKey;
  6. import java.security.spec.PKCS8EncodedKeySpec;
  7. import java.security.spec.X509EncodedKeySpec;
  8. import java.util.HashMap;
  9. import java.util.Map;
  10. import javax.crypto.Cipher;
  11. import javax.crypto.KeyAgreement;
  12. import javax.crypto.SecretKey;
  13. import javax.crypto.interfaces.DHPrivateKey;
  14. import javax.crypto.interfaces.DHPublicKey;
  15. import javax.crypto.spec.DHParameterSpec;
  16. /**
  17. * DH安全编码组件
  18. *
  19. * @author 梁栋
  20. * @version 1.0
  21. * @since 1.0
  22. */
  23. public abstract class DHCoder extends Coder {
  24. public static final String ALGORITHM = "DH";
  25. /**
  26. * 默认密钥字节数
  27. *
  28. * <pre>
  29. * DH
  30. * Default Keysize 1024
  31. * Keysize must be a multiple of 64, ranging from 512 to 1024 (inclusive).
  32. * </pre>
  33. */
  34. private static final int KEY_SIZE = 1024;
  35. /**
  36. * DH加密下需要一种对称加密算法对数据加密,这里我们使用DES,也可以使用其他对称加密算法。
  37. */
  38. public static final String SECRET_ALGORITHM = "DES";
  39. private static final String PUBLIC_KEY = "DHPublicKey";
  40. private static final String PRIVATE_KEY = "DHPrivateKey";
  41. /**
  42. * 初始化甲方密钥
  43. *
  44. * @return
  45. * @throws Exception
  46. */
  47. public static Map<String, Object> initKey() throws Exception {
  48. KeyPairGenerator keyPairGenerator = KeyPairGenerator
  49. .getInstance(ALGORITHM);
  50. keyPairGenerator.initialize(KEY_SIZE);
  51. KeyPair keyPair = keyPairGenerator.generateKeyPair();
  52. // 甲方公钥
  53. DHPublicKey publicKey = (DHPublicKey) keyPair.getPublic();
  54. // 甲方私钥
  55. DHPrivateKey privateKey = (DHPrivateKey) keyPair.getPrivate();
  56. Map<String, Object> keyMap = new HashMap<String, Object>(2);
  57. keyMap.put(PUBLIC_KEY, publicKey);
  58. keyMap.put(PRIVATE_KEY, privateKey);
  59. return keyMap;
  60. }
  61. /**
  62. * 初始化乙方密钥
  63. *
  64. * @param key
  65. *            甲方公钥
  66. * @return
  67. * @throws Exception
  68. */
  69. public static Map<String, Object> initKey(String key) throws Exception {
  70. // 解析甲方公钥
  71. byte[] keyBytes = decryptBASE64(key);
  72. X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
  73. KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
  74. PublicKey pubKey = keyFactory.generatePublic(x509KeySpec);
  75. // 由甲方公钥构建乙方密钥
  76. DHParameterSpec dhParamSpec = ((DHPublicKey) pubKey).getParams();
  77. KeyPairGenerator keyPairGenerator = KeyPairGenerator
  78. .getInstance(keyFactory.getAlgorithm());
  79. keyPairGenerator.initialize(dhParamSpec);
  80. KeyPair keyPair = keyPairGenerator.generateKeyPair();
  81. // 乙方公钥
  82. DHPublicKey publicKey = (DHPublicKey) keyPair.getPublic();
  83. // 乙方私钥
  84. DHPrivateKey privateKey = (DHPrivateKey) keyPair.getPrivate();
  85. Map<String, Object> keyMap = new HashMap<String, Object>(2);
  86. keyMap.put(PUBLIC_KEY, publicKey);
  87. keyMap.put(PRIVATE_KEY, privateKey);
  88. return keyMap;
  89. }
  90. /**
  91. * 加密<br>
  92. *
  93. * @param data
  94. *            待加密数据
  95. * @param publicKey
  96. *            甲方公钥
  97. * @param privateKey
  98. *            乙方私钥
  99. * @return
  100. * @throws Exception
  101. */
  102. public static byte[] encrypt(byte[] data, String publicKey,
  103. String privateKey) throws Exception {
  104. // 生成本地密钥
  105. SecretKey secretKey = getSecretKey(publicKey, privateKey);
  106. // 数据加密
  107. Cipher cipher = Cipher.getInstance(secretKey.getAlgorithm());
  108. cipher.init(Cipher.ENCRYPT_MODE, secretKey);
  109. return cipher.doFinal(data);
  110. }
  111. /**
  112. * 解密<br>
  113. *
  114. * @param data
  115. *            待解密数据
  116. * @param publicKey
  117. *            乙方公钥
  118. * @param privateKey
  119. *            乙方私钥
  120. * @return
  121. * @throws Exception
  122. */
  123. public static byte[] decrypt(byte[] data, String publicKey,
  124. String privateKey) throws Exception {
  125. // 生成本地密钥
  126. SecretKey secretKey = getSecretKey(publicKey, privateKey);
  127. // 数据解密
  128. Cipher cipher = Cipher.getInstance(secretKey.getAlgorithm());
  129. cipher.init(Cipher.DECRYPT_MODE, secretKey);
  130. return cipher.doFinal(data);
  131. }
  132. /**
  133. * 构建密钥
  134. *
  135. * @param publicKey
  136. *            公钥
  137. * @param privateKey
  138. *            私钥
  139. * @return
  140. * @throws Exception
  141. */
  142. private static SecretKey getSecretKey(String publicKey, String privateKey)
  143. throws Exception {
  144. // 初始化公钥
  145. byte[] pubKeyBytes = decryptBASE64(publicKey);
  146. KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
  147. X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(pubKeyBytes);
  148. PublicKey pubKey = keyFactory.generatePublic(x509KeySpec);
  149. // 初始化私钥
  150. byte[] priKeyBytes = decryptBASE64(privateKey);
  151. PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(priKeyBytes);
  152. Key priKey = keyFactory.generatePrivate(pkcs8KeySpec);
  153. KeyAgreement keyAgree = KeyAgreement.getInstance(keyFactory
  154. .getAlgorithm());
  155. keyAgree.init(priKey);
  156. keyAgree.doPhase(pubKey, true);
  157. // 生成本地密钥
  158. SecretKey secretKey = keyAgree.generateSecret(SECRET_ALGORITHM);
  159. return secretKey;
  160. }
  161. /**
  162. * 取得私钥
  163. *
  164. * @param keyMap
  165. * @return
  166. * @throws Exception
  167. */
  168. public static String getPrivateKey(Map<String, Object> keyMap)
  169. throws Exception {
  170. Key key = (Key) keyMap.get(PRIVATE_KEY);
  171. return encryptBASE64(key.getEncoded());
  172. }
  173. /**
  174. * 取得公钥
  175. *
  176. * @param keyMap
  177. * @return
  178. * @throws Exception
  179. */
  180. public static String getPublicKey(Map<String, Object> keyMap)
  181. throws Exception {
  182. Key key = (Key) keyMap.get(PUBLIC_KEY);
  183. return encryptBASE64(key.getEncoded());
  184. }
  185. }

再给出一个测试类:

  1. import static org.junit.Assert.*;
  2. import java.util.Map;
  3. import org.junit.Test;
  4. /**
  5. *
  6. * @author 梁栋
  7. * @version 1.0
  8. * @since 1.0
  9. */
  10. public class DHCoderTest {
  11. @Test
  12. public void test() throws Exception {
  13. // 生成甲方密钥对儿
  14. Map<String, Object> aKeyMap = DHCoder.initKey();
  15. String aPublicKey = DHCoder.getPublicKey(aKeyMap);
  16. String aPrivateKey = DHCoder.getPrivateKey(aKeyMap);
  17. System.err.println("甲方公钥:\r" + aPublicKey);
  18. System.err.println("甲方私钥:\r" + aPrivateKey);
  19. // 由甲方公钥产生本地密钥对儿
  20. Map<String, Object> bKeyMap = DHCoder.initKey(aPublicKey);
  21. String bPublicKey = DHCoder.getPublicKey(bKeyMap);
  22. String bPrivateKey = DHCoder.getPrivateKey(bKeyMap);
  23. System.err.println("乙方公钥:\r" + bPublicKey);
  24. System.err.println("乙方私钥:\r" + bPrivateKey);
  25. String aInput = "abc ";
  26. System.err.println("原文: " + aInput);
  27. // 由甲方公钥,乙方私钥构建密文
  28. byte[] aCode = DHCoder.encrypt(aInput.getBytes(), aPublicKey,
  29. bPrivateKey);
  30. // 由乙方公钥,甲方私钥解密
  31. byte[] aDecode = DHCoder.decrypt(aCode, bPublicKey, aPrivateKey);
  32. String aOutput = (new String(aDecode));
  33. System.err.println("解密: " + aOutput);
  34. assertEquals(aInput, aOutput);
  35. System.err.println(" ===============反过来加密解密================== ");
  36. String bInput = "def ";
  37. System.err.println("原文: " + bInput);
  38. // 由乙方公钥,甲方私钥构建密文
  39. byte[] bCode = DHCoder.encrypt(bInput.getBytes(), bPublicKey,
  40. aPrivateKey);
  41. // 由甲方公钥,乙方私钥解密
  42. byte[] bDecode = DHCoder.decrypt(bCode, aPublicKey, bPrivateKey);
  43. String bOutput = (new String(bDecode));
  44. System.err.println("解密: " + bOutput);
  45. assertEquals(bInput, bOutput);
  46. }
  47. }

控制台输出:

  1. 甲方公钥:
  2. MIHfMIGXBgkqhkiG9w0BAwEwgYkCQQD8poLOjhLKuibvzPcRDlJtsHiwXt7LzR60ogjzrhYXrgHz
  3. W5Gkfm32NBPF4S7QiZvNEyrNUNmRUb3EPuc3WS4XAkBnhHGyepz0TukaScUUfbGpqvJE8FpDTWSG
  4. kx0tFCcbnjUDC3H9c9oXkGmzLik1Yw4cIGI1TQ2iCmxBblC+eUykAgIBgANDAAJAdAWBVmIzqcko
  5. Ej6qFjLDL2+Y3FPq1iRbnOyOpDj71yKaK1K+FhTv04B0zy4DKcvAASV7/Gv0W+bgqdmffRkqrQ==
  6. 甲方私钥:
  7. MIHRAgEAMIGXBgkqhkiG9w0BAwEwgYkCQQD8poLOjhLKuibvzPcRDlJtsHiwXt7LzR60ogjzrhYX
  8. rgHzW5Gkfm32NBPF4S7QiZvNEyrNUNmRUb3EPuc3WS4XAkBnhHGyepz0TukaScUUfbGpqvJE8FpD
  9. TWSGkx0tFCcbnjUDC3H9c9oXkGmzLik1Yw4cIGI1TQ2iCmxBblC+eUykAgIBgAQyAjACJRfy1LyR
  10. eHyD+4Hfb+xR0uoIGR1oL9i9Nk6g2AAuaDPgEVWHn+QXID13yL/uDos=
  11. 乙方公钥:
  12. MIHfMIGXBgkqhkiG9w0BAwEwgYkCQQD8poLOjhLKuibvzPcRDlJtsHiwXt7LzR60ogjzrhYXrgHz
  13. W5Gkfm32NBPF4S7QiZvNEyrNUNmRUb3EPuc3WS4XAkBnhHGyepz0TukaScUUfbGpqvJE8FpDTWSG
  14. kx0tFCcbnjUDC3H9c9oXkGmzLik1Yw4cIGI1TQ2iCmxBblC+eUykAgIBgANDAAJAVEYSfBA+I9nr
  15. dWw3OBv475C+eBrWBBYqt0m6/eu4ptuDQHwV4MmUtKAC2wc2nNrdb1wmBhY1X8RnWkJ1XmdDbQ==
  16. 乙方私钥:
  17. MIHSAgEAMIGXBgkqhkiG9w0BAwEwgYkCQQD8poLOjhLKuibvzPcRDlJtsHiwXt7LzR60ogjzrhYX
  18. rgHzW5Gkfm32NBPF4S7QiZvNEyrNUNmRUb3EPuc3WS4XAkBnhHGyepz0TukaScUUfbGpqvJE8FpD
  19. TWSGkx0tFCcbnjUDC3H9c9oXkGmzLik1Yw4cIGI1TQ2iCmxBblC+eUykAgIBgAQzAjEAqaZiCdXp
  20. 2iNpdBlHRaO9ir70wo2n32xNlIzIX19VLSPCDdeUWkgRv4CEj/8k+/yd
  21. 原文: abc
  22. 解密: abc
  23. ===============反过来加密解密==================
  24. 原文: def
  25. 解密: def

如我所言,甲乙双方在获得对方公钥后可以对发送给对方的数据加密,同时也能对接收到的数据解密,达到了数据安全通信的目的!

分析DH加密算法,一种适基于密钥一致协议的加密算法。的更多相关文章

  1. Windows五种IO模型性能分析和Linux五种IO模型性能分析

    Windows五种IO模型性能分析和Linux五种IO模型性能分析 http://blog.csdn.net/jay900323/article/details/18141217 http://blo ...

  2. 如何在 Linux 中配置基于密钥认证的 SSH

    什么是基于 SSH 密钥的认证? 众所周知,Secure Shell,又称 SSH,是允许你通过无安全网络(例如 Internet)和远程系统之间安全访问/通信的加密网络协议.无论何时使用 SSH 在 ...

  3. Libreswan软件的密钥协商协议IKEv1主模式实现分析

    Libreswan软件的密钥协商协议IKEv1主模式实现分析 1 协商过程 IKEv1(互联网密钥交换协议第一版)是IPsec VPN隧道协商使用的标准密钥协商协议,其协商过程如下图所示. 总共来回交 ...

  4. linux net通信 基于密钥

    配置SSHD服务 SSH(Secure Shell)是一种能够以安全的方式提供远程登录的协议,也是目前远程管理 Linux 系统的首选方式.在此之前,一般使用 FTP 或 Telnet 来进行远程登录 ...

  5. sshd服务及基于密钥远程登陆(无需密码)

    上一条博客说明了用sshd服务远程登陆另一个系统,但是需要密码,如果不用密码呢?有没有简便的方法呢?下面为大家介绍一下,也就是基于密钥的安全验证:需要在本地生成”密钥对“后将公钥传送至服务端,进行公共 ...

  6. SSH服务搭建、账号密码登录远程Linux虚拟机、基于密钥的安全验证(Windows_Xshell,Linux)

    问题1:如果是两台虚拟机ping不同且其中一个虚拟机是克隆的另一个,需要更改一下MAC地址,关机状态下 一> "编辑虚拟机设置" 一>" 网络适配器" ...

  7. Netty中解码基于分隔符的协议和基于长度的协议

    在使用Netty的过程中,你将会遇到需要解码器的基于分隔符和帧长度的协议.本节将解释Netty所提供的用于处理这些场景的实现. 基于分隔符的协议 基于分隔符的(delimited)消息协议使用定义的字 ...

  8. Netty入门(十)解码分隔符和基于长度的协议

    我们需要区分不同帧的首尾,通常需要在结尾设定特定分隔符或者在首部添加长度字段,分别称为分隔符协议和基于长度的协议,本节讲解 Netty 如何解码这些协议. 一.分隔符协议 Netty 附带的解码器可以 ...

  9. 使用java做一个能赚钱的微信群聊机器人(2020年基于PC端协议最新可用版)

    前言 微信群机器人,主要用来管理群聊,提供类似天气查询.点歌.机器人聊天等用途. 由于微信将web端的协议封杀后,很多基于http协议的群聊机器人都失效了,所以这里使用基于PC端协议的插件来实现. 声 ...

随机推荐

  1. linux shell 比较文件夹内容 diff

    diff -ruNa test1 test2 > test12.diff   -r   比较子目录中的文件 -u  以合并的方式显示文件的不同 -N 比较目录时,若文件A仅出现在某个目录中,预设 ...

  2. shell生成指定范围内的随机数

    #!/bin/bash read -p "请输入起始数:" min read -p "请输入终止数:" max if [ $min -gt $max ] the ...

  3. 关于LogStash运行在AIX 64位机器上的问题与临时解决方案

    需求;logstash运行在SUSE,LINUX,PPC LINUX,AIX机器上,并监控文件发送日志到KAFKA中去, 问题:在AIX机器上,file插件总是报异常,无法完成数据的读取 NotImp ...

  4. 【小白的CFD之旅】02 江小白

    虽然已经是9月份了,但是西南地区的湿热天气依然将小白热成了狗.独自一个人来到这号称天府之国的西南城市,小白却一点都没感受到这天府之国的友好.毒辣的阳光像利剑一样照射到身上,让人感觉如在蒸笼中一样.从炎 ...

  5. 重构与模式(Refactoring to Patterns)-读书笔记

    第一章 ☛过度设计:是指代码的灵活性和复杂性超出所需. 第二章 ☛重构是一种保持行为的转换. 第三章 ☛每一个模式都是由三部分组成的规则,他表达的是某一环境,一个问题以及解决问题的方案之间的关系. ☛ ...

  6. CSS/CSS3常用样式小结

    1.强制文本单行显示: white-space:nowrap; 多行文本最后省略号: display: -webkit-box; -webkit-line-clamp:2; overflow: hid ...

  7. Tomcat7服务器删除后重新安装失败问题

    学习JSP时,需要修改conf下的配置文件,确发现无论如何修改权限都无法保存,所以决定卸载重装到D盘,卸载时又弹出一个对话框,具体内容没看,但是就是卸载不了,所以打算手动删除. 删除后,重装时安装失败 ...

  8. 有关sql server 2008无法导入数据库mdf文件的处理方法

    解决方法1:根据该博客中的引导,加上自己安装版本的细节,可以添加成功 http://www.2cto.com/database/201408/328930.html 解决方法2: 根据<数据库系 ...

  9. etl结合java的例子

    1.新建Java测试类,导出Jar包,放在kettle目录中的libext文件中 package test; public class Test{ public static final String ...

  10. iis上如何架设HTTPS网站

    对于HTTPS网站,大部分都比较陌生,觉得很难,其实只要申请好证书,只要在服务器上做下小配置就可以完成 首先,申请一个ssl证书 免费申请https://buy.wosign.com/free/Fre ...