非对称加密之密钥交换算法-DH

非对称加密算法之DH算法

  • 1. 算法简述
  • 2. 模型分析
  • 3. 代码实现
    • 3.1 DH 算法实现
    • 3.2 DH算法使用流程

1. 算法简述

对称加密算法提高数据安全性,但是带来了密钥管理的复杂性, 如何安全地传递密钥成为棘手问题。密钥交换算法(Diffie-Hellman算法,简称DH算法)成为该问题的关键。

DH算法是第一个密钥协商算法,仅能用于密钥分配,不能用于加密和解密消息。该算法的目的在于让消息收发双方可以在安全的条件下交换密钥,以备后续加密/解密使用。

DH密钥交换算法安全性基于有限域上的离散对数难题。

2. 模型分析

DH算法过程分为密钥构建及发布、本地密钥构建和加密数据三个阶段。

  1. 密钥构建及发布
    密钥交互流程如下图所示,注意两点:1.乙方构建自己的密钥对时需要使用甲方公钥作为参数。2.甲乙双方需要事先约定好用于数据加密的对称加密算法(如AES算法)。

非对称加密之密钥交换算法-DH_第1张图片

  1. 构建本地密钥

这里本地密钥就是用于数据加密的密钥,如AES密钥。
虽然,甲乙双方使用了不同密钥构建本地密钥,但是甲乙双方得到的密钥其实是一致的。

非对称加密之密钥交换算法-DH_第2张图片

  1. 消息加密传递
    基于上面构建的本地密钥后,可按基于对称加密算法的消息传递模型完成消息传递。
    非对称加密之密钥交换算法-DH_第3张图片

总的来说,作为对称加密体制向非对称加密体制的一种过度,DH算法仅仅比一般对称加密算法多了密钥对的构建和本地密钥的构建两项操作,而真正的数据加密/解密操作还是由非对称加密算法完成的。

DH算法在Java中有实现,Java中实现细节如下面表格所示。

算法 密钥长度 密钥长度默认值 工作模式 填充方式 备注
DH 512至1024位(密钥长度为64倍数) 1024 Java6实现

3. 代码实现

按照上面的模型分析章节,具体代码实现也分为相应的几个步骤。

3.1 DH 算法实现

package com.calvin.android.secrity;

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;

/**
 * Author:cl
 * Email:[email protected]
 * Date:20-10-19
 */
public class DHCodec {
    private static final String  KEY_ALGORITHM = "DH";
    private static final String SECRET_ALGORITHM = "AES";

    //java8最小是512,否则
    //DH key size must be multiple of 64, and can only range from 512 to 8192 (inclusive).
    // The specific key size 128 is not supported
    private static final int KEY_SIZE = 512;
    private static final String PUBLIC_KEY = "DHPublicKey";
    private static final String PRIVATE_KEY = "DHPrivateKey";

    public static Map<String, Object> initKey() throws Exception{
        KeyPairGenerator kpg = KeyPairGenerator.getInstance(KEY_ALGORITHM);
        kpg.initialize(KEY_SIZE);
        KeyPair keyPair = kpg.generateKeyPair();
        DHPublicKey publicKey = (DHPublicKey)keyPair.getPublic();
        DHPrivateKey privateKey = (DHPrivateKey)keyPair.getPrivate();
        Map<String, Object> keyMap = new HashMap<>();
        keyMap.put(PUBLIC_KEY, publicKey);
        keyMap.put(PRIVATE_KEY, privateKey);
        return keyMap;
    }

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

        X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(key);
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        PublicKey pubKey = keyFactory.generatePublic(x509EncodedKeySpec);
        DHParameterSpec dhParameterSpec = ((DHPublicKey)pubKey).getParams();
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(keyFactory.getAlgorithm());
        keyPairGenerator.initialize(dhParameterSpec);

        KeyPair keyPair = keyPairGenerator.genKeyPair();
        DHPublicKey publicKey = (DHPublicKey)keyPair.getPublic();
        DHPrivateKey privateKey = (DHPrivateKey)keyPair.getPrivate();
        Map<String, Object> keyMap = new HashMap<>();
        keyMap.put(PUBLIC_KEY, publicKey);
        keyMap.put(PRIVATE_KEY, privateKey);
        return keyMap;

    }

    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);
    }

    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);
    }

    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 pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(privateKey);
        PrivateKey priKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
        KeyAgreement keyAgreement = KeyAgreement.getInstance(keyFactory.getAlgorithm());
        keyAgreement.init(priKey);
        keyAgreement.doPhase(pubKey, true);

        SecretKey secretKey = keyAgreement.generateSecret(SECRET_ALGORITHM);
        return secretKey.getEncoded();
    }

    public static byte[] getPrivateKey(Map<String, Object> keyMap) throws Exception {
        Key key = (Key) keyMap.get(PRIVATE_KEY);
        return key.getEncoded();
    }

    public static byte[] getPublicKey(Map<String, Object> keyMap) throws Exception{
        Key key = (Key)keyMap.get(PUBLIC_KEY);
        return key.getEncoded();
    }
}

3.2 DH算法使用流程

  1. 涉及的相关Key
 //Alice公钥
    private byte[] pubKey1;
    //Alice私钥匙
    private byte[] priKey1;
    //Alice本地密钥
    private byte[] key1;

    //Bob公钥
    private byte[] pubKey2;
    //Bob私钥
    private byte[] priKey2;
    //Bob本地密钥
    private byte[] key2;
  1. 构建DH算法Alice密钥对
//生成Alice密钥对
        Map<String, Object> keyMap1 = DHCodec.initKey();
        pubKey1 = DHCodec.getPublicKey(keyMap1);
        priKey1 = DHCodec.getPrivateKey(keyMap1);
        System.out.println("Alice公钥:\n "+ Base64.encodeToString(pubKey1, Base64.DEFAULT));
        System.out.println("Alice私钥:\n "+ Base64.encodeToString(priKey1, Base64.DEFAULT));
  1. 构建DH算法Bob密钥对
//由Alice公钥产生Bob密钥对
        Map<String, Object> keyMap2 = DHCodec.initKey(pubKey1);
        pubKey2 = DHCodec.getPublicKey(keyMap2);
        priKey2 = DHCodec.getPrivateKey(keyMap2);
        System.out.println("Bob公钥:\n "+ Base64.encodeToString(pubKey2, Base64.DEFAULT));
        System.out.println("Bob私钥:\n "+ Base64.encodeToString(priKey2,Base64.DEFAULT));
  1. 构建DH双方本地密钥
key1 = DHCodec.getSecretKey(pubKey2, priKey1);
        System.out.println("Alice本地密钥:\n "+ Base64.encodeToString(key1,Base64.DEFAULT));

        key2 = DHCodec.getSecretKey(pubKey1, priKey2);
        System.out.println("Bob本地密钥:\n "+ Base64.encodeToString(key2,Base64.DEFAULT));
  1. 使用DH算法对数据加密/解密处理
 @Test
    public void dhCodecTest() throws Exception{
        System.out.println("\n=====Alice向Bob发送加密数据=====");
        String input1 = "DH密钥交换算法";
        System.out.println("原文:"+input1);
        System.out.println("---使用Alice本地密钥对数据加密 ---");
        //使用Alice本地密钥对数据加密
        byte[] code1 = DHCodec.encrypt(input1.getBytes(), key1);
        System.out.println("加密: "+Base64.encodeToString(code1,Base64.DEFAULT));

        System.out.println("---使用Bob本地密钥对数据解密 ---");
        byte[] decode1 = DHCodec.decrypt(code1, key2);
        String output1 = (new String(decode1));

        System.out.println("解密:"+output1);

        assertEquals(input1, output1);

        System.out.println("\n=====Bob向Alice发送加密数据=====");

        String input2 = "DH加密算法";
        System.out.println("原文:"+input2);
        System.out.println("---使用Bob本地密钥对数据加密 ---");
        //使用Bob本地密钥对数据加密
        byte[] code2 = DHCodec.encrypt(input2.getBytes(), key2);
        System.out.println("加密: "+Base64.encodeToString(code2,Base64.DEFAULT));
        System.out.println("---使用Alice本地密钥对数据解密 ---");

        byte[] decode2 = DHCodec.decrypt(code2, key1);
        String output2 = (new String(decode2));
        System.out.println("解密:"+output2);
        assertEquals(input2, output2);
    }

相关测试结果:

2020-10-19 15:25:27.647 30438-30453/com.calvin.android.sample I/System.out: Alice公钥:
2020-10-19 15:25:27.647 30438-30453/com.calvin.android.sample I/System.out:  MIHcMIGUBgkqhkiG9w0BAwEwgYYCQQDYsh4+Ox+qshMjQNxJ2VDXoqcutzK1Hww1+dAeO4peQY9a
2020-10-19 15:25:27.647 30438-30453/com.calvin.android.sample I/System.out: 3xE6yDNxa5orta+0Eqp1oO/GMDjDrZjBItEB2aqLAkEAj0INrOOkG/HaBFwi4jeCMZ0td12CLcq9
2020-10-19 15:25:27.647 30438-30453/com.calvin.android.sample I/System.out: B4Cjpu6T7vZXaZPzBFcl/vAjYKz0dsxsYzMMR4K/ANdo8OfLbEYTUQNDAAJAE/INXXfRceTz1Sim
2020-10-19 15:25:27.648 30438-30453/com.calvin.android.sample I/System.out: xGacJaw2YG00J2T4n5eevPzwRo7ULxd+Nb3p7QJrAdvo+WU2ydihNI9z+ICKeZQXxpJktw==
2020-10-19 15:25:27.648 30438-30453/com.calvin.android.sample I/System.out: Alice私钥:
2020-10-19 15:25:27.648 30438-30453/com.calvin.android.sample I/System.out:  MIHeAgEAMIGUBgkqhkiG9w0BAwEwgYYCQQDYsh4+Ox+qshMjQNxJ2VDXoqcutzK1Hww1+dAeO4pe
2020-10-19 15:25:27.648 30438-30453/com.calvin.android.sample I/System.out: QY9a3xE6yDNxa5orta+0Eqp1oO/GMDjDrZjBItEB2aqLAkEAj0INrOOkG/HaBFwi4jeCMZ0td12C
2020-10-19 15:25:27.648 30438-30453/com.calvin.android.sample I/System.out: Lcq9B4Cjpu6T7vZXaZPzBFcl/vAjYKz0dsxsYzMMR4K/ANdo8OfLbEYTUQRCAkASZN7REnUc9Jn9
2020-10-19 15:25:27.648 30438-30453/com.calvin.android.sample I/System.out: rQccwovHgjvQIehXOKJRf5S7rDzTnvwEKm6TV0KGQag6g4bEoHlud234jFub1KTF2QY6Rm8V
2020-10-19 15:25:27.654 30438-30453/com.calvin.android.sample I/System.out: Bob公钥:
2020-10-19 15:25:27.654 30438-30453/com.calvin.android.sample I/System.out:  MIHcMIGUBgkqhkiG9w0BAwEwgYYCQQDYsh4+Ox+qshMjQNxJ2VDXoqcutzK1Hww1+dAeO4peQY9a
2020-10-19 15:25:27.654 30438-30453/com.calvin.android.sample I/System.out: 3xE6yDNxa5orta+0Eqp1oO/GMDjDrZjBItEB2aqLAkEAj0INrOOkG/HaBFwi4jeCMZ0td12CLcq9
2020-10-19 15:25:27.654 30438-30453/com.calvin.android.sample I/System.out: B4Cjpu6T7vZXaZPzBFcl/vAjYKz0dsxsYzMMR4K/ANdo8OfLbEYTUQNDAAJAEpTCKwGUiJn3uxPj
2020-10-19 15:25:27.654 30438-30453/com.calvin.android.sample I/System.out: qrm/86Mriv5/XbA/BeHBlj6CkiSIUpgAWo6+Zrbv3neqMvKeslXIxofrzndNsAz5selVEg==
2020-10-19 15:25:27.654 30438-30453/com.calvin.android.sample I/System.out: Bob私钥:
2020-10-19 15:25:27.654 30438-30453/com.calvin.android.sample I/System.out:  MIHeAgEAMIGUBgkqhkiG9w0BAwEwgYYCQQDYsh4+Ox+qshMjQNxJ2VDXoqcutzK1Hww1+dAeO4pe
2020-10-19 15:25:27.654 30438-30453/com.calvin.android.sample I/System.out: QY9a3xE6yDNxa5orta+0Eqp1oO/GMDjDrZjBItEB2aqLAkEAj0INrOOkG/HaBFwi4jeCMZ0td12C
2020-10-19 15:25:27.654 30438-30453/com.calvin.android.sample I/System.out: Lcq9B4Cjpu6T7vZXaZPzBFcl/vAjYKz0dsxsYzMMR4K/ANdo8OfLbEYTUQRCAkASztSPoLvv64A6
2020-10-19 15:25:27.654 30438-30453/com.calvin.android.sample I/System.out: PBhPUIQgA32kqiZHpP7/HJi2/k3jIN6Zp5wGGr35h8zpwGeMgmor5UXcSDGfgop+nzXkqZ2L
2020-10-19 15:25:27.659 30438-30453/com.calvin.android.sample I/System.out: Alice本地密钥:
2020-10-19 15:25:27.659 30438-30453/com.calvin.android.sample I/System.out:  Q03Fa4qkRmL8LDJml3HxVruvnrgoSbLiHg12MeHoR84=
2020-10-19 15:25:27.662 30438-30453/com.calvin.android.sample I/System.out: Bob本地密钥:
2020-10-19 15:25:27.662 30438-30453/com.calvin.android.sample I/System.out:  Q03Fa4qkRmL8LDJml3HxVruvnrgoSbLiHg12MeHoR84=
2020-10-19 15:25:27.662 30438-30453/com.calvin.android.sample I/System.out: =====Alice向Bob发送加密数据=====
2020-10-19 15:25:27.663 30438-30453/com.calvin.android.sample I/System.out: 原文:DH密钥交换算法
2020-10-19 15:25:27.663 30438-30453/com.calvin.android.sample I/System.out: ---使用Alice本地密钥对数据加密 ---
2020-10-19 15:25:27.668 30438-30453/com.calvin.android.sample I/System.out: 加密: 7EGh9wbZ5AJuxGdUBHQO4nov+k7fD+HBZzmmykGnIiE=
2020-10-19 15:25:27.668 30438-30453/com.calvin.android.sample I/System.out: ---使用Bob本地密钥对数据解密 ---
2020-10-19 15:25:27.669 30438-30453/com.calvin.android.sample I/System.out: 解密:DH密钥交换算法
2020-10-19 15:25:27.669 30438-30453/com.calvin.android.sample I/System.out: =====Bob向Alice发送加密数据=====
2020-10-19 15:25:27.670 30438-30453/com.calvin.android.sample I/System.out: 原文:DH加密算法
2020-10-19 15:25:27.670 30438-30453/com.calvin.android.sample I/System.out: ---使用Bob本地密钥对数据加密 ---
2020-10-19 15:25:27.670 30438-30453/com.calvin.android.sample I/System.out: 加密: cRi2t10DhOxtuD4NEf2yTA==
2020-10-19 15:25:27.671 30438-30453/com.calvin.android.sample I/System.out: ---使用Alice本地密钥对数据解密 ---
2020-10-19 15:25:27.672 30438-30453/com.calvin.android.sample I/System.out: 解密:DH加密算法

你可能感兴趣的:(加密安全)