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

    C中: 头文件后缀名: .h 源文件后缀名: .c C++中: 头文件后缀名: .h,   .hpp,   .hxx 源文件后缀名:.cpp,   .cc,   .cxx,   .C   .c++ 现 ...

  2. 山东省第七届ACM省赛------Julyed

    Julyed Time Limit: 2000MS Memory limit: 65536K 题目描述 Julyed is preparing for her CET-6. She has N wor ...

  3. JAVA应用程序占用CPU、内存过高分析过程

    1.查看cpu占有率 top -P 2.查看进程cpu占用率 ps -mp 3749 -o THREAD,tid,time|sort -rn|head -n 20 查看占用cpu高,且占用时间长的线程 ...

  4. Uva 1630 折叠串

    题目链接:https://uva.onlinejudge.org/external/16/1630.pdf 题意:折叠串,给一个字符串,相同部分可以折叠,折叠可以嵌套.求最短长度的一种折叠方法.括号和 ...

  5. ZooKeeper测试笔记

    1. 下载ZooKeeper.官网:http://zookeeper.apache.org 下载后解压,假定zookeeper程序目录为/home/test/zookeeper,为陈述方便此目录记为 ...

  6. Android多媒体--MediaCodec 中文API文档

    *由于工作需要,需要利用MediaCodec实现Playback及Transcode等功能,故在学习过程中翻译了Google官方的MediaCodec API文档,由于作者水平限制,文中难免有错误和不 ...

  7. linux杀死jobs的正确方法

    输入命令:logout 终端显示:There are stopped jobs. 解决方法: 输入命令:jobs 终端显示:[]+ Stopped vim /etc/network/interface ...

  8. js压缩图片base64长度

    var myCanvas=$('.img-container > img').cropper('getCroppedCanvas'); (function (base64){ var image ...

  9. 两行代码搞定 JavaScript 的日期验证

    我们通常在 JavaScript 中验证日期,基本的思路大概是,先判断年月日是否有效,再判断当月是否有当日,比如一些月份没有 31 日,平年二月没有 29.30 日,闰年二月没有 30 日等等. 偶然 ...

  10. An entity object cannot be referenced by multiple instances of IEntityChangeTracker.

    如果你和我一样遇到了这个问题,那么你就要检查你要操作的Model对象查询,更新操作的数据库上下文也就是DBContext是否一致.如果不一致也就是说你用AContext去查如AContext.SET& ...