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. backup, file manipulation operations (such as ALTER DATABASE ADD FILE) and encryption changes on a database must be serialized.

    昨天在检查YourSQLDba备份时,发现有台数据库做备份时出现了下面错误信息,如下所示: <Exec>   <ctx>yMaint.ShrinkLog</ctx> ...

  2. [python]爬虫学习(一)

    要学习Python爬虫,我们要学习的共有以下几点(python2): Python基础知识 Python中urllib和urllib2库的用法 Python正则表达式 Python爬虫框架Scrapy ...

  3. JAVA JVM虚拟机选项:Xms Xmx PermSize MaxPermSize 区别

    Xms : 是指设定程序启动时占用内存大小.一般该值设置大的会使程序启动快,但是可能会使本机暂时变慢. Xmx : 是指设定程序运行期间最大可占用的内存大小,如果程序运行需要占用更多的内存,超出这个 ...

  4. JS中误用/g导致的正则test()无法正确重复执行

    一个简单的利用正则判断输入是否为数字: input1 = '0281234567';input2 = '0282345678';var reg = /^\d+$/g; reg.test(input1) ...

  5. JavaScript 基础回顾——对象

    JavaScript是基于对象的解释性语言,全部数据都是对象.在 JavaScript 中并没有 class 的概念,但是可以通过对象和类的模拟来实现面向对象编程. 1.对象 在JavaScript中 ...

  6. Codeforces Round #378 (Div. 2)

    A: 思路: 水题,没啥意思; B: 思路: 暴力,也没啥意思; C: 思路: 思维,可以发现从前往后和为b[i]的分成一块,然后这一块里面如果都相同就没法开始吃,然后再暴力找到那个最大的且能一开始就 ...

  7. 第二章 spring

    一.Bean作用域 spring容器创建的时候,会将所有配置的bean对象创建出来,默认bean都是单例的.代码通过getBean()方法从容器获取指定的bean实例,容器首先会调用Bean类的无参构 ...

  8. BZOJ 1797: [Ahoi2009]Mincut 最小割

    1797: [Ahoi2009]Mincut 最小割 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 2076  Solved: 885[Submit] ...

  9. AFNetWorking3.0源码分析

    分析: AFNetWorking(3.0)源码分析(一)——基本框架 AFNetworking源码解析 AFNetworking2.0源码解析<一> end

  10. 导出本地和远程SVN项目, Export remote SVN repository

    在有服务器控制权的情况下, 源服务器上 sudo svnadmin dump ironbank/ > ~/ironbank.svn.dump 在目的服务器上 sudo svnadmin crea ...