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. 解决:docker开启mongo镜像

    首先通过docker pull mongo拉取mongo镜像 (如果带版本,拉取为响应版本,若不带版本则拉取最新版本) 开启 mongodb 容器 可以选择将宿主机的mongo工作目录进行共享,作为d ...

  2. MySQL中 int(11)和int(10)有没有区别!!

    结论:int(11)  int(3)  int(20)  若不勾选填充0,那么效果统统一样,若勾选了填充0:查询出来的效果 会是这样: int(11)  00000000123 int(3)  123 ...

  3. Word-批量导出Word中的图片

    当我们需要把Word文件中的图片保存起来,你是如何导出Word图片呢?右键一张张保存图片吗?这效率太低了.如果文档中有大量的图片,这个方法会浪费很多时间. 下面给大家分享word如何批量导出图片的技巧 ...

  4. FreeSWITCH在session上执行特定dialplan

    操作系统 :CentOS 7.6_x64 FreeSWITCH版本 :1.10.9 日常开发中,会遇到需要在已存在的session上执行特定拨号方案的情况,今天整理下这方面的内容,我将从以下几个方面进 ...

  5. NC14522 珂朵莉的数列

    题目链接 题目 题目描述 珂朵莉给了你一个序列,有 \(\frac{n\times(n+1)}2\) 个子区间,求出她们各自的逆序对个数,然后加起来输出 输入描述 第一行一个数 n 表示这个序列 a ...

  6. NC15976 小C的周末

    题目链接 题目 题目描述 愉快的周末到了,小C和他的N-1个朋友买了M个游戏,游戏编号从1~M.每个游戏都是多人游戏,他们打算周末一起打游戏. 小C的每个朋友都决定好了要玩哪一款游戏(会有一组人打同一 ...

  7. NVME(学习笔记三)—PMR

    PMR(Persistent Memory Region)持久性内存区域 NVM Express在2019年完成了NVMe 1.4规范的制定,新的NVMe协议带来了大量的全新特性,尤其在纠错.强化性能 ...

  8. 使用sqlmap执行SQL注入并获取数据库用户名

    Sqlmap介绍 sqlmap支持MySQL, Oracle,PostgreSQL, Microsoft SQL Server, Microsoft Access, IBM DB2, SQLite, ...

  9. GDI快速遍历位图像素

    使用DIB部分可直接快速访问像素 例如,此测试将记事本中的所有白色像素替换为绿色像素 HDC hDCScreen = GetDC(NULL); HWND hWndDest = FindWindow(L ...

  10. win32 - 使用GDI+播放gif图片

    今天做case的时候遇到一个这样的问题,故记录下来. Codeproject有类似的案例,不过是使用的MFC模板编译的. 因为我们只需要win32程序,所以就....代码如下: CodeProject ...