Java非对称加密算法dh

    接下来我们分析DH加密算法,一种适基于密钥一致协议的加密算法。

DH

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



流程分析:



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

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

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











通过java代码实现如下:Coder类见 Java加密技术(一)

Java代码  收藏代码

import java.security.Key; 

import java.security.KeyFactory; 

import java.security.KeyPair; 

import java.security.KeyPairGenerator; 

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; 

 

/**

* DH安全编码组件



* @author 梁栋

* @version 1.0

* @since 1.0

*/ 

public abstract class DHCoder extends Coder { 

    public static final String ALGORITHM = "DH"; 

 

    /**

     * 默认密钥字节数

     * 

     * <pre>

     * DH

     * Default Keysize 1024  

     * Keysize must be a multiple of 64, ranging from 512 to 1024 (inclusive).

     * </pre>

     */ 

    private static final int KEY_SIZE = 1024; 

 

    /**

     * DH加密下需要一种对称加密算法对数据加密,这里我们使用DES,也可以使用其他对称加密算法。

     */ 

    public static final String SECRET_ALGORITHM = "DES"; 

    private static final String PUBLIC_KEY = "DHPublicKey"; 

    private static final String PRIVATE_KEY = "DHPrivateKey"; 

 

    /**

     * 初始化甲方密钥

     * 

     * @return

     * @throws Exception

     */ 

    public static Map<String, Object> initKey() throws Exception { 

        KeyPairGenerator keyPairGenerator = KeyPairGenerator 

                .getInstance(ALGORITHM); 

        keyPairGenerator.initialize(KEY_SIZE); 

 

        KeyPair keyPair = keyPairGenerator.generateKeyPair(); 

 

        // 甲方公钥 

        DHPublicKey publicKey = (DHPublicKey) keyPair.getPublic(); 

 

        // 甲方私钥 

        DHPrivateKey privateKey = (DHPrivateKey) keyPair.getPrivate(); 

 

        Map<String, Object> keyMap = new HashMap<String, Object>(2); 

 

        keyMap.put(PUBLIC_KEY, publicKey); 

        keyMap.put(PRIVATE_KEY, privateKey); 

        return keyMap; 

    } 

 

    /**

     * 初始化乙方密钥

     * 

     * @param key

     *            甲方公钥

     * @return

     * @throws Exception

     */ 

    public static Map<String, Object> initKey(String key) throws Exception { 

        // 解析甲方公钥 

        byte[] keyBytes = decryptBASE64(key); 

        X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes); 

        KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM); 

        PublicKey pubKey = keyFactory.generatePublic(x509KeySpec); 

 

        // 由甲方公钥构建乙方密钥 

        DHParameterSpec dhParamSpec = ((DHPublicKey) pubKey).getParams(); 

 

        KeyPairGenerator keyPairGenerator = KeyPairGenerator 

                .getInstance(keyFactory.getAlgorithm()); 

        keyPairGenerator.initialize(dhParamSpec); 

 

        KeyPair keyPair = keyPairGenerator.generateKeyPair(); 

 

        // 乙方公钥 

        DHPublicKey publicKey = (DHPublicKey) keyPair.getPublic(); 

 

        // 乙方私钥 

        DHPrivateKey privateKey = (DHPrivateKey) keyPair.getPrivate(); 

 

        Map<String, Object> keyMap = new HashMap<String, Object>(2); 

 

        keyMap.put(PUBLIC_KEY, publicKey); 

        keyMap.put(PRIVATE_KEY, privateKey); 

 

        return keyMap; 

    } 

 

    /**

     * 加密<br>

     * 

     * @param data

     *            待加密数据

     * @param publicKey

     *            甲方公钥

     * @param privateKey

     *            乙方私钥

     * @return

     * @throws Exception

     */ 

    public static byte[] encrypt(byte[] data, String publicKey, 

            String privateKey) throws Exception { 

 

        // 生成本地密钥 

        SecretKey secretKey = getSecretKey(publicKey, privateKey); 

 

        // 数据加密 

        Cipher cipher = Cipher.getInstance(secretKey.getAlgorithm()); 

        cipher.init(Cipher.ENCRYPT_MODE, secretKey); 

 

        return cipher.doFinal(data); 

    } 

 

    /**

     * 解密<br>

     * 

     * @param data

     *            待解密数据

     * @param publicKey

     *            乙方公钥

     * @param privateKey

     *            乙方私钥

     * @return

     * @throws Exception

     */ 

    public static byte[] decrypt(byte[] data, String publicKey, 

            String privateKey) throws Exception { 

 

        // 生成本地密钥 

        SecretKey secretKey = getSecretKey(publicKey, privateKey); 

        // 数据解密 

        Cipher cipher = Cipher.getInstance(secretKey.getAlgorithm()); 

        cipher.init(Cipher.DECRYPT_MODE, secretKey); 

 

        return cipher.doFinal(data); 

    } 

 

    /**

     * 构建密钥

     * 

     * @param publicKey

     *            公钥

     * @param privateKey

     *            私钥

     * @return

     * @throws Exception

     */ 

    private static SecretKey getSecretKey(String publicKey, String privateKey) 

            throws Exception { 

        // 初始化公钥 

        byte[] pubKeyBytes = decryptBASE64(publicKey); 

 

        KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM); 

        X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(pubKeyBytes); 

        PublicKey pubKey = keyFactory.generatePublic(x509KeySpec); 

 

        // 初始化私钥 

        byte[] priKeyBytes = decryptBASE64(privateKey); 

 

        PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(priKeyBytes); 

        Key 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; 

    } 

 

    /**

     * 取得私钥

     * 

     * @param keyMap

     * @return

     * @throws Exception

     */ 

    public static String getPrivateKey(Map<String, Object> keyMap) 

            throws Exception { 

        Key key = (Key) keyMap.get(PRIVATE_KEY); 

 

        return encryptBASE64(key.getEncoded()); 

    } 

 

    /**

     * 取得公钥

     * 

     * @param keyMap

     * @return

     * @throws Exception

     */ 

    public static String getPublicKey(Map<String, Object> keyMap) 

            throws Exception { 

        Key key = (Key) keyMap.get(PUBLIC_KEY); 

 

        return encryptBASE64(key.getEncoded()); 

    } 







再给出一个测试类:

Java代码  收藏代码

import static org.junit.Assert.*; 

 

import java.util.Map; 

 

import org.junit.Test; 

 

/**



* @author 梁栋

* @version 1.0

* @since 1.0

*/ 

public class DHCoderTest { 

 

    @Test 

    public void test() throws Exception { 

        // 生成甲方密钥对儿 

        Map<String, Object> aKeyMap = DHCoder.initKey(); 

        String aPublicKey = DHCoder.getPublicKey(aKeyMap); 

        String aPrivateKey = DHCoder.getPrivateKey(aKeyMap); 

 

        System.err.println("甲方公钥:\r" + aPublicKey); 

        System.err.println("甲方私钥:\r" + aPrivateKey); 

         

        // 由甲方公钥产生本地密钥对儿 

        Map<String, Object> bKeyMap = DHCoder.initKey(aPublicKey); 

        String bPublicKey = DHCoder.getPublicKey(bKeyMap); 

        String bPrivateKey = DHCoder.getPrivateKey(bKeyMap); 

         

        System.err.println("乙方公钥:\r" + bPublicKey); 

        System.err.println("乙方私钥:\r" + bPrivateKey); 

         

        String aInput = "abc "; 

        System.err.println("原文: " + aInput); 

 

        // 由甲方公钥,乙方私钥构建密文 

        byte[] aCode = DHCoder.encrypt(aInput.getBytes(), aPublicKey, 

                bPrivateKey); 

 

        // 由乙方公钥,甲方私钥解密 

        byte[] aDecode = DHCoder.decrypt(aCode, bPublicKey, aPrivateKey); 

        String aOutput = (new String(aDecode)); 

 

        System.err.println("解密: " + aOutput); 

 

        assertEquals(aInput, aOutput); 

 

        System.err.println(" ===============反过来加密解密================== "); 

        String bInput = "def "; 

        System.err.println("原文: " + bInput); 

 

        // 由乙方公钥,甲方私钥构建密文 

        byte[] bCode = DHCoder.encrypt(bInput.getBytes(), bPublicKey, 

                aPrivateKey); 

 

        // 由甲方公钥,乙方私钥解密 

        byte[] bDecode = DHCoder.decrypt(bCode, aPublicKey, bPrivateKey); 

        String bOutput = (new String(bDecode)); 

 

        System.err.println("解密: " + bOutput); 

 

        assertEquals(bInput, bOutput); 

    } 

 







控制台输出:

Console代码  收藏代码

甲方公钥: 

MIHfMIGXBgkqhkiG9w0BAwEwgYkCQQD8poLOjhLKuibvzPcRDlJtsHiwXt7LzR60ogjzrhYXrgHz 

W5Gkfm32NBPF4S7QiZvNEyrNUNmRUb3EPuc3WS4XAkBnhHGyepz0TukaScUUfbGpqvJE8FpDTWSG 

kx0tFCcbnjUDC3H9c9oXkGmzLik1Yw4cIGI1TQ2iCmxBblC+eUykAgIBgANDAAJAdAWBVmIzqcko 

Ej6qFjLDL2+Y3FPq1iRbnOyOpDj71yKaK1K+FhTv04B0zy4DKcvAASV7/Gv0W+bgqdmffRkqrQ== 

 

甲方私钥: 

MIHRAgEAMIGXBgkqhkiG9w0BAwEwgYkCQQD8poLOjhLKuibvzPcRDlJtsHiwXt7LzR60ogjzrhYX 

rgHzW5Gkfm32NBPF4S7QiZvNEyrNUNmRUb3EPuc3WS4XAkBnhHGyepz0TukaScUUfbGpqvJE8FpD 

TWSGkx0tFCcbnjUDC3H9c9oXkGmzLik1Yw4cIGI1TQ2iCmxBblC+eUykAgIBgAQyAjACJRfy1LyR 

eHyD+4Hfb+xR0uoIGR1oL9i9Nk6g2AAuaDPgEVWHn+QXID13yL/uDos= 

 

乙方公钥: 

MIHfMIGXBgkqhkiG9w0BAwEwgYkCQQD8poLOjhLKuibvzPcRDlJtsHiwXt7LzR60ogjzrhYXrgHz 

W5Gkfm32NBPF4S7QiZvNEyrNUNmRUb3EPuc3WS4XAkBnhHGyepz0TukaScUUfbGpqvJE8FpDTWSG 

kx0tFCcbnjUDC3H9c9oXkGmzLik1Yw4cIGI1TQ2iCmxBblC+eUykAgIBgANDAAJAVEYSfBA+I9nr 

dWw3OBv475C+eBrWBBYqt0m6/eu4ptuDQHwV4MmUtKAC2wc2nNrdb1wmBhY1X8RnWkJ1XmdDbQ== 

 

乙方私钥: 

MIHSAgEAMIGXBgkqhkiG9w0BAwEwgYkCQQD8poLOjhLKuibvzPcRDlJtsHiwXt7LzR60ogjzrhYX 

rgHzW5Gkfm32NBPF4S7QiZvNEyrNUNmRUb3EPuc3WS4XAkBnhHGyepz0TukaScUUfbGpqvJE8FpD 

TWSGkx0tFCcbnjUDC3H9c9oXkGmzLik1Yw4cIGI1TQ2iCmxBblC+eUykAgIBgAQzAjEAqaZiCdXp 

2iNpdBlHRaO9ir70wo2n32xNlIzIX19VLSPCDdeUWkgRv4CEj/8k+/yd 

 

原文: abc  

解密: abc  

===============反过来加密解密==================  

原文: def  

解密: def  





如我所言,甲乙双方在获得对方公钥后可以对发送给对方的数据加密,同时也能对接收到的数据解密,达到了数据安全通信的目的!

Java加密技术(五)——非对称加密算法的由来DH的更多相关文章

  1. Java进阶(七)Java加密技术之非对称加密算法RSA

    Java加密技术(四)--非对称加密算法RSA 非对称加密算法--RSA 基本概念 非对称加密算法是一种密钥的保密方法. 非对称加密算法需要两个密钥:公开密钥(publickey)和私有密钥(priv ...

  2. Java加密技术

    相关链接: Java加密技术(一)——BASE64与单向加密算法MD5&SHA&MAC Java加密技术(二)——对称加密DES&AES Java加密技术(三)——PBE算法  ...

  3. Java加密技术(一)——BASE64与单向加密算法MD5&SHA&MAC

    Java加密技术(一)——BASE64与单向加密算法MD5&SHA&MAC 博客分类: Java/Security Javabase64macmd5sha     加密解密,曾经是我一 ...

  4. Java加密技术(八)——数字证书

    原文:http://snowolf.iteye.com/blog/391931 请大家在阅读本篇内容时先阅读 Java加密技术(四),预先了解RSA加密算法. 在构建Java代码实现前,我们需要完成证 ...

  5. 如何综合运用对称加密技术、非对称加密技术(公钥密码体制)和Hash函数 保证信息的保密性、完整性、可用性和不可否认性?

    一.几个问题 在提出问题之前,先创建一个使用场景,发送方(甲方)要给接收方(乙方)发送投标书.大家知道,投标书都包括发送方的标的,这个标的是不能被竞标者知晓,更不能被竞标者修改的.在传输的投标书时,提 ...

  6. Java加密技术(四)非对称加密算法RSA

    RSA      这样的算法1978年就出现了.它是第一个既能用于数据加密也能用于数字签名的算法.它易于理解和操作.也非常流行.算法的名字以发明者的名字命名:Ron Rivest, AdiShamir ...

  7. Java进阶(八)Java加密技术之对称加密 非对称加密 不可逆加密算法

    对称加密 非对称加密 不可逆加密算法 根据密钥类型不同可以将现代密码技术分为两类:对称加密算法(私钥密码体系)和非对称加密算法(公钥密码体系). 1 对称加密算法 原理 对称加密算法中,数据加密和解密 ...

  8. Java加密技术(一)——加密介绍

    from://http://blog.csdn.net/janronehoo/article/details/7590772 如基本的单向加密算法: BASE64 严格地说,属于编码格式,而非加密算法 ...

  9. JAVA加密技术-----MD5 与SHA 加密

    关于JAVA的加密技术有很多很多,这里只介绍加密技术的两种 MD5与 SHA. MD5与SHA是单向加密算法,也就是说加密后不能解密. MD5 ---信息摘要算法,广泛用于加密与解密技术,常用于文件校 ...

  10. Java加密技术(一)—— HMACSHA1 加密算法

    HMACSHA1 是从 SHA1 哈希函数构造的一种键控哈希算法,被用作 HMAC(基于哈希的消息验证代码). 此 HMAC 进程将密钥与消息数据混合,使用哈希函数对混合结果进行哈希计算,将所得哈希值 ...

随机推荐

  1. uni-app 介绍及使用

    一.什么是uni-app uni-app由dcloud公司开发的多端融合框架,是一个使用 Vue.js 开发所有前端应用的框架,开发者编写一套代码,可发布到iOS.Android.Web(响应式).以 ...

  2. ZR 七连 Day 1 游记

    ZR 七连 Day 1 游记 游记篇 赛前搞笑事件 今天是第一场正睿,还是要 好好对待 的 $ 17:59:58 $ 还在吃饭 $ 17:59:59 $ 做出重要决定,先打着比赛,有空就吃一口包子 $ ...

  3. delphi 设置一个控件 在一个窗口的 正中间 方法

    1.选中控件,右键----postion--  最下面两个 x y 坐标,center in window

  4. 【CAS学习一】CAS服务端部署

    公司要做单点登录系统,网上搜了一下目前主流方案是CAS,故部署一个试试看. 1.下载 因为最近出现log4j2远程代码执行漏洞,尽量选择新版本已修复此漏洞的,故CAS选择6.4版本.打包部署依赖JDK ...

  5. 用set做一轮无重复纯随机

    前端时间面腾讯的时候,一位老师问了一个相当有趣的问题:假设存在一个音乐播放器,里面有一个100首歌的歌单.现在需要做一个随机播放功能,要求不重复的随机播放完一百首歌.当时脑子短路了没想出来,几天突然意 ...

  6. NC15532 Happy Running

    题目链接 题目 题目描述 Happy Running, an application for runners, is very popular in CHD. In order to lose wei ...

  7. NVM Feature— Reservation(NVME 学习笔记五)

    8.8 Reservations 预订 NVMe的reservation预订功能,用于让两个或多个主机能够协调配合的访问共享namespace.使用这些功能的协议和方式超出了本规格说明书的范围.对这些 ...

  8. 【Unity3D】2D动画

    1 图片处理 ​ 通过 PS 软件将以下 gif 文件中的黑色背景删除,并将其中的 18 个图层分别保存为 png 格式图片. 2 游戏对象 ​ 1)游戏对象层级结构 ​ 2)Transform组件参 ...

  9. Java设计模式-观察者模式Observer

    介绍 观察者模式是行为设计模式之一.当您对对象的状态感兴趣并希望在任何更改时得到通知时,观察者设计模式非常有用.在观察者模式中,观察另一个对象状态的对象被称为观察者,而被观察的对象则被称为主体. 优点 ...

  10. mantis如何更改用户密码

    从MantisBT版本开始,创建用户后,必须由用户通过确认邮件进行修改密码,而管理员无权对用户的密码进行修改.这对于配置mail不成功的情况下很不方便.     以下配置就可以让管理员轻松管理用户的密 ...