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. SpringBoot自动化配置

    SpringBoot自动化配置 一.SpringBoot自动化配置原理 1.SpringBoot引导类注解介绍 在SpringBoot的启动引导类上有一个@SpringBootApplication注 ...

  2. Git 简明教程(一)

    版本控制工具,早期的vss tfs svn等,这些应该是老一辈程序员常用的工具.目前 git 已经在版本控制领域占主流的地位,因为国外的github 和国内的码云 gitee 均用的是git. git ...

  3. Oracle 19c RAC 自动应用RU补丁简明版

    环境:Oracle RAC(GI 19.3 + DB 19.3) 本文应用补丁信息, 19.16 RU: p34130714_190000_Linux-x86-64.zip 本文主要演示使用opatc ...

  4. 【framework】DisplayContent简介

    1 前言 ​ DisplayContent 用于管理屏幕,一块屏幕对应一个 DisplayContent 对象,虽然手机只有一个显示屏,但是可以创建多个 DisplayContent 对象,如投屏时, ...

  5. 【OpenGL ES】绘制正方形

    1 前言 ​ [OpenGL ES]绘制三角形 中介绍了绘制三角形的方法,本文将介绍绘制正方形的方法. ​ OpenGL 以点.线段.三角形为图元,没有提供绘制正方形内部的接口.要绘制正方形内部,必须 ...

  6. SpringBoot相关注解使用

    @MapperScan注解和@Mapper @Mapper常用在相应的 *Mapper类上,但是每个类都使用相对麻烦,所以后来用@MapperScan替代 ,@MapperScan注解使用在启动类上. ...

  7. 谁说docker-compose不能水平扩展容器、服务多实例?

    ❝ 虽说我已经从docker-compose走上了docker swarm的邪门歪道,目前被迫走在k8s这条康庄大道, 但是我还是喜欢docker-compose简洁有效的部署方式. ❞ 曾其何时 d ...

  8. websocket 监听端口问题

    有用户反馈使用我们的软件时会出现 ERR_CONNECTION_CLOSED 问题 我们根据反馈排查问题发现是软件的 websocket 监听端口被另一款软件占用了,暂时的解决方法是将占用的软件关闭 ...

  9. win32-使用EnumWindows比较两个窗口的Z轴

    通过使用EnumWindows()和枚举窗口来手动确定EnumChildWindows()来直接确定哪个窗口在z轴上比另一个窗口高. struct myEnumInfo { HWND hwnd1; H ...

  10. @staticmethod/@classmethod/实例方法/@abstractmethod

    from abc import ABCMeta, abstractmethod # 定义一个抽象类 class Person(metaclass=ABCMeta): name = "泰山&q ...