一、概述

1、与对称加密算法的主要差别在于,加密和解密的密钥不相同,一个公开(公钥),一个保密(私钥)。主要解决了对称加密算法密钥分配管理的问题,提高了算法安全性。

2、非对称加密算法的加密、解密的效率比较低。在算法设计上,非对称加密算法对待加密的数据长度有着苛刻的要求。例如RSA算法要求待加密的数据不得大于53个字节。

3、非对称加密算法主要用于 交换对称加密算法的密钥,而非数据交换

4、java6提供实现了DH和RSA两种算法。Bouncy Castle提供了E1Gamal算法支持。除了上述三种算法还有一个ECC算法,目前没有相关的开源组件提供支持

二、模型分析

我们还是以甲乙双方发送数据为模型进行分析

1、甲方(消息发送方,下同)构建密钥对(公钥+私钥),甲方公布公钥给乙方(消息接收方,下同)

2、乙方以甲方发送过来的公钥作为参数构造密钥对(公钥+私钥),将构造出来的公钥公布给甲方

3、甲方用“甲方的私钥+乙方的公钥”构造本地密钥

4、乙方用“乙方的私钥+甲方的公钥”构造本地的密钥

5、这个时候,甲乙两方本地新构造出来的密钥应该一样。然后就可以使用AES这类对称加密算法结合密钥进行数据的安全传送了。传送过程参考AES的相关算法

三、代码分析

package com.ca.test;
import java.security.Key;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;
import javax.crypto.Cipher;
import javax.crypto.KeyAgreement;
import javax.crypto.SecretKey;
import javax.crypto.interfaces.DHPrivateKey;
import javax.crypto.interfaces.DHPublicKey;
import javax.crypto.spec.DHParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.binary.Base64;
/*** 非对称加密算法DH算法组件* 非对称算法一般是用来传送对称加密算法的密钥来使用的,所以这里我们用DH算法模拟密钥传送* 对称加密AES算法继续做我们的数据加解密* @author kongqz* */
public class DHCoder {//非对称密钥算法public static final String KEY_ALGORITHM="DH";//本地密钥算法,即对称加密算法。可选des,aes,desedepublic static final String SECRET_ALGORITHM="AES";/*** 密钥长度,DH算法的默认密钥长度是1024* 密钥长度必须是64的倍数,在512到1024位之间* */private static final int KEY_SIZE=512;//公钥private static final String PUBLIC_KEY="DHPublicKey";//私钥private static final String PRIVATE_KEY="DHPrivateKey";/*** 初始化甲方密钥* @return Map 甲方密钥的Map* */public static Map<String,Object> initKey() throws Exception{//实例化密钥生成器KeyPairGenerator keyPairGenerator=KeyPairGenerator.getInstance(KEY_ALGORITHM);//初始化密钥生成器keyPairGenerator.initialize(KEY_SIZE);//生成密钥对KeyPair keyPair=keyPairGenerator.generateKeyPair();//甲方公钥DHPublicKey publicKey=(DHPublicKey) keyPair.getPublic();//甲方私钥DHPrivateKey privateKey=(DHPrivateKey) keyPair.getPrivate();//将密钥存储在map中Map<String,Object> keyMap=new HashMap<String,Object>();keyMap.put(PUBLIC_KEY, publicKey);keyMap.put(PRIVATE_KEY, privateKey);return keyMap;}/*** 初始化乙方密钥* @param key 甲方密钥(这个密钥是通过第三方途径传递的)* @return Map 乙方密钥的Map* */public static Map<String,Object> initKey(byte[] key) throws Exception{//解析甲方的公钥//转换公钥的材料X509EncodedKeySpec x509KeySpec=new X509EncodedKeySpec(key);//实例化密钥工厂KeyFactory keyFactory=KeyFactory.getInstance(KEY_ALGORITHM);//产生公钥PublicKey pubKey=keyFactory.generatePublic(x509KeySpec);//由甲方的公钥构造乙方密钥DHParameterSpec dhParamSpec=((DHPublicKey)pubKey).getParams();//实例化密钥生成器KeyPairGenerator keyPairGenerator=KeyPairGenerator.getInstance(keyFactory.getAlgorithm());//初始化密钥生成器keyPairGenerator.initialize(dhParamSpec);//产生密钥对KeyPair keyPair=keyPairGenerator.genKeyPair();//乙方公钥DHPublicKey publicKey=(DHPublicKey)keyPair.getPublic();//乙方私钥DHPrivateKey privateKey=(DHPrivateKey)keyPair.getPrivate();//将密钥存储在Map中Map<String,Object> keyMap=new HashMap<String,Object>();keyMap.put(PUBLIC_KEY, publicKey);keyMap.put(PRIVATE_KEY, privateKey);return keyMap;}/*** 加密* @param data待加密数据* @param key 密钥* @return byte[] 加密数据* */public static byte[] encrypt(byte[] data,byte[] key) throws Exception{//生成本地密钥SecretKey secretKey=new SecretKeySpec(key,SECRET_ALGORITHM);//数据加密Cipher cipher=Cipher.getInstance(secretKey.getAlgorithm());cipher.init(Cipher.ENCRYPT_MODE, secretKey);return cipher.doFinal(data);}/*** 解密* @param data 待解密数据* @param key 密钥* @return byte[] 解密数据* */public static byte[] decrypt(byte[] data,byte[] key) throws Exception{//生成本地密钥SecretKey secretKey=new SecretKeySpec(key,SECRET_ALGORITHM);//数据解密Cipher cipher=Cipher.getInstance(secretKey.getAlgorithm());cipher.init(Cipher.DECRYPT_MODE, secretKey);return cipher.doFinal(data);}/*** 构建密钥* @param publicKey 公钥* @param privateKey 私钥* @return byte[] 本地密钥* */public static byte[] getSecretKey(byte[] publicKey,byte[] privateKey) throws Exception{//实例化密钥工厂KeyFactory keyFactory=KeyFactory.getInstance(KEY_ALGORITHM);//初始化公钥//密钥材料转换X509EncodedKeySpec x509KeySpec=new X509EncodedKeySpec(publicKey);//产生公钥PublicKey pubKey=keyFactory.generatePublic(x509KeySpec);//初始化私钥//密钥材料转换PKCS8EncodedKeySpec pkcs8KeySpec=new PKCS8EncodedKeySpec(privateKey);//产生私钥PrivateKey priKey=keyFactory.generatePrivate(pkcs8KeySpec);//实例化KeyAgreement keyAgree=KeyAgreement.getInstance(keyFactory.getAlgorithm());//初始化keyAgree.init(priKey);keyAgree.doPhase(pubKey, true);//生成本地密钥SecretKey secretKey=keyAgree.generateSecret(SECRET_ALGORITHM);return secretKey.getEncoded();}/*** 取得私钥* @param keyMap 密钥map* @return byte[] 私钥* */public static byte[] getPrivateKey(Map<String,Object> keyMap){Key key=(Key)keyMap.get(PRIVATE_KEY);return key.getEncoded();}/*** 取得公钥* @param keyMap 密钥map* @return byte[] 公钥* */public static byte[] getPublicKey(Map<String,Object> keyMap) throws Exception{Key key=(Key) keyMap.get(PUBLIC_KEY);return key.getEncoded();}/*** @param args* @throws Exception */public static void main(String[] args) throws Exception {//生成甲方的密钥对Map<String,Object> keyMap1=DHCoder.initKey();//甲方的公钥byte[] publicKey1=DHCoder.getPublicKey(keyMap1);//甲方的私钥byte[] privateKey1=DHCoder.getPrivateKey(keyMap1);System.out.println("甲方公钥:/n"+Base64.encodeBase64String(publicKey1));System.out.println("甲方私钥:/n"+Base64.encodeBase64String(privateKey1));//由甲方的公钥产生的密钥对Map<String,Object> keyMap2=DHCoder.initKey(publicKey1);byte[] publicKey2=DHCoder.getPublicKey(keyMap2);byte[] privateKey2=DHCoder.getPrivateKey(keyMap2);System.out.println("乙方公钥:/n"+Base64.encodeBase64String(publicKey2));System.out.println("乙方私钥:/n"+Base64.encodeBase64String(privateKey2));//组装甲方的本地加密密钥,由乙方的公钥和甲方的私钥组合而成byte[] key1=DHCoder.getSecretKey(publicKey2, privateKey1);System.out.println("甲方的本地密钥:/n"+Base64.encodeBase64String(key1));//组装乙方的本地加密密钥,由甲方的公钥和乙方的私钥组合而成byte[] key2=DHCoder.getSecretKey(publicKey1, privateKey2);System.out.println("乙方的本地密钥:/n"+Base64.encodeBase64String(key2));System.out.println("================密钥对构造完毕,开始进行加密数据的传输=============");String str="密码交换算法";System.out.println("/n===========甲方向乙方发送加密数据==============");System.out.println("原文:"+str);System.out.println("===========使用甲方本地密钥对进行数据加密==============");//甲方进行数据的加密byte[] code1=DHCoder.encrypt(str.getBytes(), key1);System.out.println("加密后的数据:"+Base64.encodeBase64String(code1));System.out.println("===========使用乙方本地密钥对数据进行解密==============");//乙方进行数据的解密byte[] decode1=DHCoder.decrypt(code1, key2);System.out.println("乙方解密后的数据:"+new String(decode1)+"/n/n");System.out.println("===========反向进行操作,乙方向甲方发送数据==============/n/n");str="乙方向甲方发送数据DH";System.out.println("原文:"+str);//使用乙方本地密钥对数据进行加密byte[] code2=DHCoder.encrypt(str.getBytes(), key2);System.out.println("===========使用乙方本地密钥对进行数据加密==============");System.out.println("加密后的数据:"+Base64.encodeBase64String(code2));System.out.println("=============乙方将数据传送给甲方======================");System.out.println("===========使用甲方本地密钥对数据进行解密==============");//甲方使用本地密钥对数据进行解密byte[] decode2=DHCoder.decrypt(code2, key1);System.out.println("甲方解密后的数据:"+new String(decode2));}
}控制台输出结果:
甲方公钥:
MIHgMIGXBgkqhkiG9w0BAwEwgYkCQQD8poLOjhLKuibvzPcRDlJtsHiwXt7LzR60ogjzrhYXrgHz
W5Gkfm32NBPF4S7QiZvNEyrNUNmRUb3EPuc3WS4XAkBnhHGyepz0TukaScUUfbGpqvJE8FpDTWSG
kx0tFCcbnjUDC3H9c9oXkGmzLik1Yw4cIGI1TQ2iCmxBblC+eUykAgIBgANEAAJBALk1l11UT5Y1
evJv1sLQAXo7Yj/olsPMVJ/7zOx503CRcovA5Q+k2OyIZsl5H2qGCnqi+Da0/9zZx0go8Y/j5B4=
甲方私钥:
MIHRAgEAMIGXBgkqhkiG9w0BAwEwgYkCQQD8poLOjhLKuibvzPcRDlJtsHiwXt7LzR60ogjzrhYX
rgHzW5Gkfm32NBPF4S7QiZvNEyrNUNmRUb3EPuc3WS4XAkBnhHGyepz0TukaScUUfbGpqvJE8FpD
TWSGkx0tFCcbnjUDC3H9c9oXkGmzLik1Yw4cIGI1TQ2iCmxBblC+eUykAgIBgAQyAjB0haXhPoDW
gLMF79N1ZZGu1dtHWAObe9obKAh4hGH0HsAsSY8qy17ZE0IyiOwYPXA=
乙方公钥:
MIHgMIGXBgkqhkiG9w0BAwEwgYkCQQD8poLOjhLKuibvzPcRDlJtsHiwXt7LzR60ogjzrhYXrgHz
W5Gkfm32NBPF4S7QiZvNEyrNUNmRUb3EPuc3WS4XAkBnhHGyepz0TukaScUUfbGpqvJE8FpDTWSG
kx0tFCcbnjUDC3H9c9oXkGmzLik1Yw4cIGI1TQ2iCmxBblC+eUykAgIBgANEAAJBAOWqgUur2jDR
057ohEH4eb3KwOdmcbsv4GnvIlCVzwpBKVlUk0MMIeV8APLz/xIjjoOnNZx3rNknaO/+v85tG3g=
乙方私钥:
MIHRAgEAMIGXBgkqhkiG9w0BAwEwgYkCQQD8poLOjhLKuibvzPcRDlJtsHiwXt7LzR60ogjzrhYX
rgHzW5Gkfm32NBPF4S7QiZvNEyrNUNmRUb3EPuc3WS4XAkBnhHGyepz0TukaScUUfbGpqvJE8FpD
TWSGkx0tFCcbnjUDC3H9c9oXkGmzLik1Yw4cIGI1TQ2iCmxBblC+eUykAgIBgAQyAjB+/HgBYVlO
e2eAeU0HoWQyYsHt0tSPUZUqCyY9mWEK/7soxsR/6pfAb1npaaI1NO0=
甲方的本地密钥:
+E068E5KSWvLYrB5o1ryIY1VFt6WcUnBrXvlBYN++/M=
乙方的本地密钥:
+E068E5KSWvLYrB5o1ryIY1VFt6WcUnBrXvlBYN++/M=
================密钥对构造完毕,开始进行加密数据的传输=============
===========甲方向乙方发送加密数据==============
原文:密码交换算法
===========使用甲方本地密钥对进行数据加密==============
加密后的数据:1PUMKnkyfKauO6kTG5UDtA==
===========使用乙方本地密钥对数据进行解密==============
乙方解密后的数据:密码交换算法===========反向进行操作,乙方向甲方发送数据==============原文:乙方向甲方发送数据DH
===========使用乙方本地密钥对进行数据加密==============
加密后的数据:VGLdXmtGyBaE87NiSoHX+yvwyUkAx/qYKYWv+jEwkBY=
=============乙方将数据传送给甲方======================
===========使用甲方本地密钥对数据进行解密==============
甲方解密后的数据:乙方向甲方发送数据DH

四、总结

1、非对称加密算法主要用来传递密钥的,而且性能较低。但是安全性超强。非对称加密算法能加密的数据长度也受限

2、用非对称加密算法算出甲乙双方本地的密钥后,可以选择DES/AES/DESede这些对称加密算法进行数据的传送了

转载于:https://my.oschina.net/abcijkxyz/blog/722260

非对称加密算法-DH算法相关推荐

  1. JAVA加密解密→术语、密码分类、OSI与TCP/IP安全体系、Base64、消息摘要算法MD/SHA/MAC、对称加密算法DES/AES/PBE、非对称加密算法DH/RSA/EIGamaI

    术语 密码分类 OSI与TCP/IP安全体系 JAVA安全 Base64算法 消息摘要算法MD 消息摘要算法MD图解 消息摘要算法SHA 消息摘要算法SHA图解 消息摘要算法MAC 消息摘要算法MAC ...

  2. elgamal加密算法 java_JAVA加解密17-非对称加密算法-ElGamal算法

    一.概述 1.ElGamal算法和ECC算法基于离散对数问题 2.这个是一个单向的过程.虽然密钥对构造简单,但是只是乙方向另外一方单向传送数据进行加解密,不能反向操作 3.这里只有"公钥加密 ...

  3. 可逆与不可逆算法,对称加密与非对称加密算法总结

    文章目录 1. 加密算法的种类 2. 不可逆加密算法 ①:MD5 ②:HMAC系列 ③:SHA系列 3. 可逆加密算法 1. 对称加密 ①:DES ②:3DES ③:AES 2. 非对称加密 ①:RS ...

  4. 数字签名、数字证书、对称加密算法、非对称加密算法、单向加密(散列算法)...

    2019独角兽企业重金招聘Python工程师标准>>> 数字签名是什么? 1. 鲍勃有两把钥匙,一把是公钥,另一把是私钥. 2. 鲍勃把公钥送给他的朋友们----帕蒂.道格.苏珊-- ...

  5. 数字签名、数字证书、对称加密算法、非对称加密算法、单向加密(散列算法)

    数字签名是什么? 1. 鲍勃有两把钥匙,一把是公钥,另一把是私钥. 2. 鲍勃把公钥送给他的朋友们--帕蒂.道格.苏珊--每人一把. 3. 苏珊给鲍勃写信,写完后用鲍勃的公钥加密,达到保密的效果. 4 ...

  6. 数字签名、数字证书、对称加密算法、非对称加密算法、单向加密(散列算法)——Web网络系列学习笔记

    数字签名是什么? 1. 鲍勃有两把钥匙,一把是公钥,另一把是私钥. 2. 鲍勃把公钥送给他的朋友们--帕蒂.道格.苏珊--每人一把. 3. 苏珊给鲍勃写信,写完后用鲍勃的公钥加密,达到保密的效果. 4 ...

  7. 数据传输加密——非对称加密算法RSA+对称算法AES(适用于java,android和Web)

    本篇文章已授权微信公众号 guolin_blog (郭霖)独家发布 转载请注明出处:http://blog.csdn.net/chay_chan/article/details/58605605 数据 ...

  8. 数据传输加密非对称加密算法以及对称算法-RSA+AES

    转载:http://blog.csdn.net/chay_chan/article/details/58605605 源码:https://github.com/Javen205/IJPay 数据传输 ...

  9. 算法2_非对称加密算法之ECDSA(椭圆曲线数字签名算法)

    ECDSA(椭圆曲线数字签名算法) AES(高级加密标准): =>对称加密 ​ 对业务数据进行加密,防止他人可以看见 ECDSA(椭圆曲线数字签名算法):=>非对称加密算法(公钥和私钥) ...

最新文章

  1. 2019年上半年收集到的人工智能深度学习方向干货文章
  2. 99. Recover Binary Search Tree (Tree; DFS)
  3. 使用关指定中断解决资源冲突问题
  4. linux大小写敏感和windows大小写不敏感(忽略大小写)导致的直接拷贝文件文件名冲突问题(需要打tar包再分享)
  5. C#new出来的结构体内存分配在堆上
  6. Apache + Tomcat 配置多个应用
  7. Opencv--Mat图像基本操作
  8. 爬虫python入门_python爬虫入门教程有哪些?适合的只有这三个
  9. 在线等比数列项数生成器
  10. Java String to InputStream
  11. ARM汇编书写格式及符号(symbol)和表达式(expr)
  12. 阶段3 2.Spring_05.基于XML的IOC的案例1_4 注解IOC案例-把自己编写的类使用注解配置...
  13. 三菱5uplc伺服电机指令_【工控无忧原创】三菱FX3U PLC如何控制松下伺服
  14. 用C语言实现:输入某年某月某日,判断这一天是这一年的第几天
  15. 解决java下载文件中文文件名乱码问题(ie,谷歌,火狐)
  16. Windows AMD 安装 PyTorch
  17. 【vue】mint-ui中navbar下划线不显示的问题
  18. 微信推送封面尺寸_微信公众平台图片尺寸是多少 如何设置
  19. python pygame 游戏实践: 俄罗斯方块(Tetris Game)第一步
  20. Linux 高级调试工具-pstack和strace

热门文章

  1. timesten mysql_Timesten(TT)和ORACLE执行效率测试
  2. QCM学习—基于QT自制上位机(多线程)
  3. Go语言圣经阅读-第二周
  4. 树莓派PICO三种按键方式实现点灯!
  5. 计算机408王道考研资料、笔记分享 ~ ~
  6. 树莓派3配置局域网打印服务器惠普打印机HP1108
  7. 武士与魔王游戏v1.0
  8. 输入字符串按ASCⅡ大小排序
  9. 分支过程灭绝概率matlab,分支过程
  10. Win11使用串口转换USB失败问题处理