注意:本节内容主要参考自《Java加密与解密的艺术(第2版)》第8章“高等加密算法--非对称加密算法”

11.1、非对称加密算法

特点:

  • 发送方和接收方均有一个密钥对(公钥+私钥),其中公钥传播,私钥自己保存,不需要传播
  • 私钥不需要传播的特性解决了对称加密算法中密钥传播的困难(这个困难一般通过线下传递可以解决)
  • 加密安全性极高,只用于一些电子商务网站,加解密速度远低于对称加密
  • 一般情况下,为了解决非对称加密算法加解密速度低的问题,采用非对称加密(使用公钥+私钥对对称加密的密钥进行加解密)+对称加密(加解密数据)相结合的方式。

常见算法:

  • DH(非对称加密的基石)
  • RSA(非对称加密的经典,除了可用于非对称加密,也可用于数字签名,RSA--155(512位密钥)已被破解)
  • ElGamal

11.2、DH(仅能用于密钥分配,不能加解密数据)

实现方式:

  • JDK(密钥长度:512~1024中的64的整数倍)

几个概念:

  • 密钥对:公钥+私钥
  • 本地密钥:对称加密的密钥

整个流程:

1)甲乙双方初始化各自的密钥对

甲方构建出密钥对keyPair1-->乙方使用甲方的密钥对中的公钥publicKey1构建出自己的密钥对keyPair2

2)甲乙双方构建各自的本地密钥

甲方使用自己的私钥privateKey1+乙方的公钥publicKey2构建出自己的本地密钥key1

乙方使用自己的私钥privateKey2+甲方的公钥publicKey1构建出自己的本地密钥key2

最后会发现key1==key2,这两个本地密钥将会是接下来对对称加密所使用的密钥

3)发送方(甲方或乙方均可)使用本地密钥+对称加密算法对待加密数据进行加密,传递给接收方

4)接收方使用本地密钥+对称加密算法对待解密数据进行解密

  1. 1 package com.util.dh;
  2. 2
  3. 3 import java.io.UnsupportedEncodingException;
  4. 4 import java.security.InvalidAlgorithmParameterException;
  5. 5 import java.security.InvalidKeyException;
  6. 6 import java.security.Key;
  7. 7 import java.security.KeyFactory;
  8. 8 import java.security.KeyPair;
  9. 9 import java.security.KeyPairGenerator;
  10. 10 import java.security.NoSuchAlgorithmException;
  11. 11 import java.security.PrivateKey;
  12. 12 import java.security.PublicKey;
  13. 13 import java.security.spec.InvalidKeySpecException;
  14. 14 import java.security.spec.PKCS8EncodedKeySpec;
  15. 15 import java.security.spec.X509EncodedKeySpec;
  16. 16
  17. 17 import javax.crypto.BadPaddingException;
  18. 18 import javax.crypto.Cipher;
  19. 19 import javax.crypto.IllegalBlockSizeException;
  20. 20 import javax.crypto.KeyAgreement;
  21. 21 import javax.crypto.NoSuchPaddingException;
  22. 22 import javax.crypto.interfaces.DHPublicKey;
  23. 23 import javax.crypto.spec.DHParameterSpec;
  24. 24 import javax.crypto.spec.SecretKeySpec;
  25. 25
  26. 26 import org.apache.commons.codec.binary.Base64;
  27. 27
  28. 28 /**
  29. 29 * 基于JDK的DH算法,工作模式采用ECB
  30. 30 */
  31. 31 public class DHJDK {
  32. 32 private static final String ENCODING = "UTF-8";
  33. 33 private static final String FDC_KEY_ALGORITHM = "DH";//非对称加密密钥算法
  34. 34 private static final String DC_KEY_ALGORITHM = "AES";//产生本地密钥的算法(对称加密密钥算法)
  35. 35 private static final String CIPHER_ALGORITHM = "AES/ECB/PKCS5Padding";//加解密算法 格式:算法/工作模式/填充模式 注意:ECB不使用IV参数
  36. 36 private static final int FDC_KEY_SIZE = 512;//非对称密钥长度(512~1024之间的64的整数倍)
  37. 37
  38. 38 /**
  39. 39 * 生成甲方密钥对
  40. 40 */
  41. 41 public static KeyPair initKey() throws NoSuchAlgorithmException{
  42. 42 KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(FDC_KEY_ALGORITHM);//密钥对生成器
  43. 43 keyPairGenerator.initialize(FDC_KEY_SIZE);//指定密钥长度
  44. 44 KeyPair keyPair = keyPairGenerator.generateKeyPair();//生成密钥对
  45. 45 return keyPair;
  46. 46 }
  47. 47
  48. 48 /**
  49. 49 * 生成乙方密钥对
  50. 50 * @param key 甲方公钥
  51. 51 */
  52. 52 public static KeyPair initKey(byte[] key) throws NoSuchAlgorithmException,
  53. 53 InvalidKeySpecException,
  54. 54 InvalidAlgorithmParameterException{
  55. 55 KeyFactory keyFactory = KeyFactory.getInstance(FDC_KEY_ALGORITHM);//密钥工厂
  56. 56 PublicKey publicKey = keyFactory.generatePublic(new X509EncodedKeySpec(key));//还原甲方公钥
  57. 57 DHParameterSpec dHParameterSpec = ((DHPublicKey)publicKey).getParams();
  58. 58
  59. 59 KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(keyFactory.getAlgorithm());//乙方密钥对生成器
  60. 60 keyPairGenerator.initialize(dHParameterSpec);//使用甲方公钥参数初始化乙方密钥对生成器
  61. 61 KeyPair keyPair = keyPairGenerator.generateKeyPair();//生成密钥对
  62. 62 return keyPair;
  63. 63 }
  64. 64
  65. 65 /**
  66. 66 * DH加密
  67. 67 * @param data 带加密数据
  68. 68 * @param keyByte 本地密钥,由getSecretKey(byte[] publicKey, byte[] privateKey)产生
  69. 69 */
  70. 70 public static byte[] encrypt(String data, byte[] keyByte) throws NoSuchAlgorithmException,
  71. 71 NoSuchPaddingException,
  72. 72 InvalidKeyException,
  73. 73 IllegalBlockSizeException,
  74. 74 BadPaddingException,
  75. 75 UnsupportedEncodingException {
  76. 76 Key key = new SecretKeySpec(keyByte, DC_KEY_ALGORITHM);//生成本地密钥
  77. 77
  78. 78 Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
  79. 79 cipher.init(Cipher.ENCRYPT_MODE, key);//设置加密模式并且初始化key
  80. 80 return cipher.doFinal(data.getBytes(ENCODING));
  81. 81 }
  82. 82
  83. 83 /**
  84. 84 * DH解密
  85. 85 * @param data 待解密数据为字节数组
  86. 86 * @param keyByte 本地密钥,由getSecretKey(byte[] publicKey, byte[] privateKey)产生
  87. 87 */
  88. 88 public static byte[] decrypt(byte[] data, byte[] keyByte) throws NoSuchAlgorithmException,
  89. 89 NoSuchPaddingException,
  90. 90 InvalidKeyException,
  91. 91 IllegalBlockSizeException,
  92. 92 BadPaddingException {
  93. 93 Key key = new SecretKeySpec(keyByte, DC_KEY_ALGORITHM);//生成本地密钥
  94. 94 Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
  95. 95 cipher.init(Cipher.DECRYPT_MODE, key);
  96. 96 return cipher.doFinal(data);
  97. 97 }
  98. 98
  99. 99 /**
  100. 100 * 根据本方私钥与对方公钥构建本地密钥(即对称加密的密钥)
  101. 101 * @param publicKey 对方公钥
  102. 102 * @param privateKey 本方私钥
  103. 103 */
  104. 104 public static byte[] getSecretKey(byte[] publicKey, byte[] privateKey) throws NoSuchAlgorithmException,
  105. 105 InvalidKeySpecException,
  106. 106 InvalidKeyException{
  107. 107 KeyFactory keyFactory = KeyFactory.getInstance(FDC_KEY_ALGORITHM);//密钥工厂
  108. 108 PublicKey pubkey = keyFactory.generatePublic(new X509EncodedKeySpec(publicKey));//还原公钥
  109. 109 PrivateKey prikey = keyFactory.generatePrivate(new PKCS8EncodedKeySpec(privateKey));//还原私钥
  110. 110
  111. 111 KeyAgreement keyAgreement = KeyAgreement.getInstance(keyFactory.getAlgorithm());
  112. 112 keyAgreement.init(prikey);
  113. 113 keyAgreement.doPhase(pubkey, true);
  114. 114 return keyAgreement.generateSecret(DC_KEY_ALGORITHM).getEncoded();//生成本地密钥(对称加密的密钥)
  115. 115 }
  116. 116
  117. 117 /**
  118. 118 * 获取公钥
  119. 119 */
  120. 120 public static byte[] getPublicKey(KeyPair keyPair){
  121. 121 return keyPair.getPublic().getEncoded();
  122. 122 }
  123. 123
  124. 124 /**
  125. 125 * 获取私钥
  126. 126 */
  127. 127 public static byte[] getPrivateKey(KeyPair keyPair){
  128. 128 return keyPair.getPrivate().getEncoded();
  129. 129 }
  130. 130
  131. 131 /**
  132. 132 * 测试
  133. 133 */
  134. 134 public static void main(String[] args) throws NoSuchAlgorithmException,
  135. 135 InvalidKeySpecException,
  136. 136 InvalidAlgorithmParameterException,
  137. 137 InvalidKeyException,
  138. 138 NoSuchPaddingException,
  139. 139 IllegalBlockSizeException,
  140. 140 BadPaddingException,
  141. 141 UnsupportedEncodingException {
  142. 142 byte[] pubKey1;//甲方公钥
  143. 143 byte[] priKey1;//甲方私钥
  144. 144 byte[] key1;//甲方本地密钥
  145. 145 byte[] pubKey2;//乙方公钥
  146. 146 byte[] priKey2;//乙方私钥
  147. 147 byte[] key2;//乙方本地密钥
  148. 148
  149. 149 /*********************测试是否可以正确生成以上6个key,以及key1与key2是否相等*********************/
  150. 150 KeyPair keyPair1 = DHJDK.initKey();//生成甲方密钥对
  151. 151 pubKey1 = DHJDK.getPublicKey(keyPair1);
  152. 152 priKey1 = DHJDK.getPrivateKey(keyPair1);
  153. 153
  154. 154 KeyPair keyPair2 = DHJDK.initKey(pubKey1);//根据甲方公钥生成乙方密钥对
  155. 155 pubKey2 = DHJDK.getPublicKey(keyPair2);
  156. 156 priKey2 = DHJDK.getPrivateKey(keyPair2);
  157. 157
  158. 158 key1 = DHJDK.getSecretKey(pubKey2, priKey1);//使用对方公钥和自己私钥构建本地密钥
  159. 159 key2 = DHJDK.getSecretKey(pubKey1, priKey2);//使用对方公钥和自己私钥构建本地密钥
  160. 160
  161. 161 System.out.println("甲方公钥pubKey1-->"+Base64.encodeBase64String(pubKey1)+"@@pubKey1.length-->"+pubKey1.length);
  162. 162 System.out.println("甲方私钥priKey1-->"+Base64.encodeBase64String(priKey1)+"@@priKey1.length-->"+priKey1.length);
  163. 163 System.out.println("乙方公钥pubKey2-->"+Base64.encodeBase64String(pubKey2)+"@@pubKey2.length-->"+pubKey2.length);
  164. 164 System.out.println("乙方私钥priKey2-->"+Base64.encodeBase64String(priKey2)+"@@priKey2.length-->"+priKey2.length);
  165. 165 System.out.println("甲方密钥key1-->"+Base64.encodeBase64String(key1));
  166. 166 System.out.println("乙方密钥key2-->"+Base64.encodeBase64String(key2));
  167. 167
  168. 168 /*********************测试甲方使用本地密钥加密数据向乙方发送,乙方使用本地密钥解密数据*********************/
  169. 169 System.out.println("甲方-->乙方");
  170. 170 String data = "找一个好姑娘啊!";
  171. 171 byte[] encodeStr = DHJDK.encrypt(data, key1);
  172. 172 System.out.println("甲方加密后的数据-->"+Base64.encodeBase64String(encodeStr));
  173. 173 byte[] decodeStr = DHJDK.decrypt(encodeStr, key2);
  174. 174 System.out.println("乙方解密后的数据-->"+new String(decodeStr,"UTF-8"));
  175. 175
  176. 176 /*********************测试乙方使用本地密钥加密数据向甲方发送,甲方使用本地密钥解密数据*********************/
  177. 177 System.out.println("乙方-->甲方");
  178. 178 String data2 = "找一个好姑娘啊!";
  179. 179 byte[] encodeStr2 = DHJDK.encrypt(data2, key2);
  180. 180 System.out.println("乙方加密后的数据-->"+Base64.encodeBase64String(encodeStr2));
  181. 181 byte[] decodeStr2 = DHJDK.decrypt(encodeStr, key1);
  182. 182 System.out.println("甲方解密后的数据-->"+new String(decodeStr2,"UTF-8"));
  183. 183 }
  184. 184 }

非对称加密算法--DH的更多相关文章

  1. 第十一章 非对称加密算法--DH

    注意:本节内容主要参考自<Java加密与解密的艺术(第2版)>第8章“高等加密算法--非对称加密算法” 11.1.非对称加密算法 特点: 发送方和接收方均有一个密钥对(公钥+私钥),其中公 ...

  2. 非对称加密算法DH

    特点: 发送方和接收方均有一个密钥对(公钥+私钥),其中公钥传播,私钥自己保存,不需要传播 私钥不需要传播的特性解决了对称加密算法中密钥传播的困难(这个困难一般通过线下传递可以解决) 加密安全性极高, ...

  3. DH、RSA与ElGamal非对称加密算法实现及应用

    1.对称加密与非对称加密概述 关于对称加密与非对称加密的概念这里不再多说,感兴趣可以看下我之前的几篇文章,下面说一说两者的主要区别. 对称加密算法数据安全,密钥管理复杂,密钥传递过程复杂,存在密钥泄露 ...

  4. 非对称加密算法-RSA

    注意:本节内容主要参考自<Java加密与解密的艺术(第2版)>第8章“高等加密算法--非对称加密算法” 12.1.RSA(最经典的非对称加密算法) 特点: 使用一套密钥即可完成加解密(与D ...

  5. 信息加密之非对称加密算法RSA

    前面为大家已经总结了,基于密钥交换的DH算法,现在就为大家再介绍一种基于因子分解的RSA算法,这种加密算法有两种实现形式:1.公钥加密,私钥解密:2.私钥加密,公钥解密.下面就为大家分析一下实现代码, ...

  6. 信息加密之非对称加密DH算法

    非对称加密算法是相对于对称加密算法来说的,对于对称加密算法请查阅之前的总结,今天为大家介绍一下DH算法,DH是一种密钥交换算法,接收方根据发送方加密时的密钥,生成接收方解密密钥.下面就一起来学习一下吧 ...

  7. 第十二章 非对称加密算法-RSA

    注意:本节内容主要参考自<Java加密与解密的艺术(第2版)>第8章“高等加密算法--非对称加密算法” 12.1.RSA(最经典的非对称加密算法) 特点: 使用一套密钥即可完成加解密(与D ...

  8. Java 加密解密 对称加密算法 非对称加密算法 MD5 BASE64 AES RSA

    版权声明:本文为博主原创文章,未经博主允许不得转载. [前言] 本文简单的介绍了加密技术相关概念,最后总结了java中现有的加密技术以及使用方法和例子 [最简单的加密] 1.简单的概念 明文:加密前的 ...

  9. openssl 非对称加密算法RSA命令详解

    1.非对称加密算法概述 非对称加密算法也称公开密钥算法,其解决了对称加密算法密钥分配的问题,非对称加密算法基本特点如下: 1.加密密钥和解密密钥不同 2.密钥对中的一个密钥可以公开 3.根据公开密钥很 ...

随机推荐

  1. android 获取设备拔插状态广播事件易漏掉的一行属性!

    我们都知道设备拔插的状态获取需要一个权限   <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILES ...

  2. 课堂 一些代码的叫法 JavaScript js

    ():圆括号 {} :花括号 <>:尖括号 [] :方括号

  3. [原]调试ComFriendlyWaitMtaThreadProc崩溃

    项目里安装了UIA相关的钩子来监听UIA相关事件,退出的时候偶尔会崩溃在ComFriendlyWaitMtaThreadProc中,如下  从上图可以看出 是访问到无效的地址了,用!address 0 ...

  4. Git 命令清单

    这份命令清单并不完善,后期会根据使用情况再进行更改. 操作分支项目 1 下载仓库的一个分支(baooab-patch-1)的代码 git clone -b baooab-patch-1 https:/ ...

  5. sharepoint 2013 开发环境安装

    Sharepoint 介绍 Sharepoint 可以帮助企业用户轻松完成日常工作中诸如文档审批.在线申请等业务流程,同时提供多种接口实现后台业务系统的集成,它将 Office 桌面端应用的优势结合 ...

  6. 【Spring】简单的Spring MVC入门例子

    前言 测试特性需要搭建一个简单的Spring MVC的例子,遂记录之,只是例子,只为入门者之示例. 版本说明 声明POM文件,指定需引入的JAR. <properties> <spr ...

  7. iOS的多版本配置(版本分离,多环境配置)

    前几天公司说一个客户要搞一个app,我说搞呗,跟我啥关系...他说,就是从咱的app上搞,什么都一样,就是一些logo啥的不一样.我一开始感觉,那就改改logo呗,后来一想,凑,百度推送,友盟统计,B ...

  8. iOS_XCode7_Launch Image 的初使用

    之前一直没有做笔记的习惯,后来发现很多知识不常用,容易忘了,再去网上找的,很浪费时间,现在尝试着自己写写博客,可以是自己笔记,方便以后查询,如果有纰漏,欢迎指正. 1.Xcode7中 ,assets. ...

  9. 1010. Radix (25)(未完成)

    Given a pair of positive integers, for example, 6 and 110, can this equation 6 = 110 be true? The an ...

  10. 一个简单确非常实用的javascript函数

    在写js的时候,往往会碰到字符串拼接的问题,如果简单,直接使用+号连接字符串就可以了, 但是如果复杂,+用起来就非常不爽,在.net中有,Sting.Format函数,用起来还是很爽的,于是就想着js ...