分析DH加密算法,一种适基于密钥一致协议的加密算法。

时间:2021-08-28 22:07:01

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



流程分析:



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

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

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



分析DH加密算法,一种适基于密钥一致协议的加密算法。

  1. 分析DH加密算法,一种适基于密钥一致协议的加密算法。
  2. 分析DH加密算法,一种适基于密钥一致协议的加密算法。

通过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加密算法,一种适基于密钥一致协议的加密算法。

分析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&lowbar;Xshell,Linux)

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

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

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

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

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

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

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

随机推荐

  1. Mybatis添加返回主键ID

    1.对应xml文件<insert id="insert" parameterType="DetectStandard"useGeneratedKeys=& ...

  2. 千万不要误用 java 中的 HashCode 方法

    刚才debug追堆栈的时候发现一个很奇怪的问题 我用IE8和Google的浏览器访问同一个地址 Action的 scope="session" 也设置了 而且两个浏览器提交的参数m ...

  3. WEB前端介绍

    1.WEB前端是神马 Web前端开发是从网页制作演变而来的,名称上有很明显的时代特征.在互联网的演化进程中,网页制作是Web1.0时代的产物,那时网站的主要内容都是静态的,用户使用网站的行为也以浏览为 ...

  4. Node填坑教程——前言

    Node是什么? Node 是一个服务器端 JavaScript 解释器,它将改变服务器应该如何工作的概念.它的目标是帮助程序员构建高度可伸缩的应用程序,编写能够处理数万条同时连接到一个(只有一个)物 ...

  5. MOSFET与MOSFET驱动电路原理及应用&lpar;转&rpar;

    源:http://www.micro-bridge.com/news/news.asp?id=258 在使用MOS管设计开关电源或者马达驱动电路的时候,大部分人都会考虑MOS的导通电阻,最大电压等,最 ...

  6. asp&period;net core 中灵活的配置方式

    asp.net core支持外部文件和命令行参数方式来配置系统运行所需要的配置信息,我们从下面两个常用场景来具体说下具体使用方法. 一.监听地址及端口配置 1,命令行方式 asp.net core系统 ...

  7. Redis-Sentinel 哨兵

    为什么需要哨兵? 一旦主节点宕机,那么需要人为修改所有应用方的主节点地址(改为新的master地址),还需要命令所有从节点复制新的主节点 那么这个问题,redis-sentinel就可以解决了 什么是 ...

  8. js实现下雪雪花特效

    两种下雪特效: 1. <script type="text/javascript"> (function($){ $.fn.snow = function(option ...

  9. 【Redis】持久化

    Redis提供了为持久化提供了两种方法:第一种是快照:他可以将存在某一时刻的所有数据都写入硬盘里面.第二种是只追加文件(AOF):它会在执行命令时,将被执行的写命令复制到硬盘里面. Redis支持持久 ...

  10. AJAX请求时status返回状态明细表(转)

    转自:http://www.cnblogs.com/wangking/p/6530904.html AJAX请求时status返回状态明细表 readyState的五种状态2010-03-04 18: ...