当前位置: 首页 > 知识库问答 >
问题:

Java中的Diffie-Hellman密钥交换

周阳成
2023-03-14

我正在Java的一个个人项目中工作,该项目涉及通过不安全的通道发送敏感数据。我需要知道如何实现Diffie Hellman密钥交换(DHKE)在java使用其库。我知道关于它的所有密码理论,所以不需要深入细节,我只需要一个非常基本的实现,所以我可以让两个程序共享一个密钥。我从java2s.com得到了这个例子,但它并不完整:

import java.math.BigInteger;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.SecureRandom;

import javax.crypto.spec.DHParameterSpec;
import javax.crypto.spec.DHPublicKeySpec;

public class Main {
  public final static int pValue = 47;

  public final static int gValue = 71;

  public final static int XaValue = 9;

  public final static int XbValue = 14;

  public static void main(String[] args) throws Exception {
    BigInteger p = new BigInteger(Integer.toString(pValue));
    BigInteger g = new BigInteger(Integer.toString(gValue));
    BigInteger Xa = new BigInteger(Integer.toString(XaValue));
    BigInteger Xb = new BigInteger(Integer.toString(XbValue));

    int bitLength = 512; // 512 bits
    SecureRandom rnd = new SecureRandom();
    p = BigInteger.probablePrime(bitLength, rnd);
    g = BigInteger.probablePrime(bitLength, rnd);

    createSpecificKey(p, g);
  }

  public static void createSpecificKey(BigInteger p, BigInteger g) throws Exception {
    KeyPairGenerator kpg = KeyPairGenerator.getInstance("DiffieHellman");

    DHParameterSpec param = new DHParameterSpec(p, g);
    kpg.initialize(param);
    KeyPair kp = kpg.generateKeyPair();

    KeyFactory kfactory = KeyFactory.getInstance("DiffieHellman");

    DHPublicKeySpec kspec = (DHPublicKeySpec) kfactory.getKeySpec(kp.getPublic(),
        DHPublicKeySpec.class);
  }
}

我该怎么做呢?有人能帮我完成剩下的代码吗?

共有3个答案

韩博厚
2023-03-14

下面是一个工作示例:

static void main() {

    DH dh = new DH();
    byte[] myPublicKey = dh.generatePublicKey();

    /* Send myPublicKey to other party, and get hisPublicKey in return */

    byte[] sharedKey = dh.computeSharedKey(hisPublicKey)
    /* sharedKey is now 'shared' between both parties */

}

public class DH {

    private static final String TAG = "DH";

    private KeyPair keyPair;
    private KeyAgreement keyAgree;

    public byte[] generatePublicKey() {
        DHParameterSpec dhParamSpec;

        try {
            dhParamSpec = new DHParameterSpec(P, G);
            Log.i(TAG, "P = " + P.toString(16));
            KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("DiffieHellman");
            keyPairGen.initialize(dhParamSpec);
            keyPair = keyPairGen.generateKeyPair();
            Log.i(TAG, "Y = " + ((DHPublicKey) keyPair.getPublic()).getY().toString(16));
            keyAgree = KeyAgreement.getInstance("DiffieHellman");
            keyAgree.init(keyPair.getPrivate());

            BigInteger pubKeyBI = ((DHPublicKey) keyPair.getPublic()).getY();
            byte[] pubKeyBytes = pubKeyBI.toByteArray();
            Log.i(TAG, String.format(TAG, "Y [%d] = %s", pubKeyBytes.length, Utils.toHexString(pubKeyBytes)));
            return pubKeyBytes;
        } catch (Exception e) {
            Log.e(TAG, "generatePubKey(): " + e.getMessage());
            return null;
        }
    }

    public byte[] computeSharedKey(byte[] pubKeyBytes) {
        if (keyAgree == null) {
            Log.e(TAG, "computeSharedKey(): keyAgree IS NULL!!");
            return null;
        }

        try {
            KeyFactory keyFactory = KeyFactory.getInstance("DiffieHellman");
            BigInteger pubKeyBI = new BigInteger(1, pubKeyBytes);
            Log.i(TAG, "Y = " + pubKeyBI.toString(16));
            PublicKey pubKey = keyFactory.generatePublic(new DHPublicKeySpec(pubKeyBI, P, G));
            keyAgree.doPhase(pubKey, true);
            byte[] sharedKeyBytes = keyAgree.generateSecret();
            Log.i(TAG, String.format("SHARED KEY[%d] = %s", sharedKeyBytes.length, Utils.toHexString(sharedKeyBytes)));
            return sharedKeyBytes;
        } catch (Exception e) {
            Log.e(TAG, "computeSharedKey(): " + e.getMessage());
            return null;
        }
    }

    private static final byte P_BYTES[] = {
            (byte)0xF4, (byte)0x88, (byte)0xFD, (byte)0x58,
            ...
            (byte)0xE9, (byte)0x2F, (byte)0x78, (byte)0xC7
    };
    private static final BigInteger P = new BigInteger(1, P_BYTES);

    private static final BigInteger G = BigInteger.valueOf(2);
}
王亮
2023-03-14

下面的代码使用椭圆曲线Diffie-Hellman生成并共享128位密钥和AES进行加密。

import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

import javax.crypto.*;
import javax.crypto.spec.SecretKeySpec;
import java.io.IOException;
import java.security.*;

public class AESSecurityCap {

    private PublicKey publickey;
    KeyAgreement keyAgreement;
    byte[] sharedsecret;

    String ALGO = "AES";

    AESSecurityCap() {
        makeKeyExchangeParams();
    }

    private void makeKeyExchangeParams() {
        KeyPairGenerator kpg = null;
        try {
            kpg = KeyPairGenerator.getInstance("EC");
            kpg.initialize(128);
            KeyPair kp = kpg.generateKeyPair();
            publickey = kp.getPublic();
            keyAgreement = KeyAgreement.getInstance("ECDH");
            keyAgreement.init(kp.getPrivate());

        } catch (NoSuchAlgorithmException | InvalidKeyException e) {
            e.printStackTrace();
        }
    }

    public void setReceiverPublicKey(PublicKey publickey) {
        try {
            keyAgreement.doPhase(publickey, true);
            sharedsecret = keyAgreement.generateSecret();
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        }
    }

    public String encrypt(String msg) {
        try {
            Key key = generateKey();
            Cipher c = Cipher.getInstance(ALGO);
            c.init(Cipher.ENCRYPT_MODE, key);
            byte[] encVal = c.doFinal(msg.getBytes());
            return new BASE64Encoder().encode(encVal);
        } catch (BadPaddingException | InvalidKeyException | NoSuchPaddingException | IllegalBlockSizeException | NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return msg;
    }

    public String decrypt(String encryptedData) {
        try {
            Key key = generateKey();
            Cipher c = Cipher.getInstance(ALGO);
            c.init(Cipher.DECRYPT_MODE, key);
            byte[] decordedValue = new BASE64Decoder().decodeBuffer(encryptedData);
            byte[] decValue = c.doFinal(decordedValue);
            return new String(decValue);
        } catch (BadPaddingException | InvalidKeyException | NoSuchPaddingException | IllegalBlockSizeException | NoSuchAlgorithmException | IOException e) {
            e.printStackTrace();
        }
        return encryptedData;
    }

    public PublicKey getPublickey() {
        return publickey;
    }

    protected Key generateKey() {
        return new SecretKeySpec(sharedsecret, ALGO);
    }
}

扩展您自己的类以添加AES加密功能

public class Node extends AESSecurityCap {

//your class

}

最后,使用加密的方法

public class Main {

    public static void main(String[] args) throws IOException {
        Node server = new Node();
        Node client = new Node();

        server.setReceiverPublicKey(client.getPublickey());

        client.setReceiverPublicKey(server.getPublickey());

        String data = "hello";

        String enc = server.encrypt(data);

        System.out.println("hello is coverted to "+enc);

        System.out.println(enc+" is converted to "+client.decrypt(enc));

    }
}

输出:

hello is coverted to OugbNvUuylvAr9mKv//nLA==
OugbNvUuylvAr9mKv//nLA== is converted to hello

Process finished with exit code 0
洪鸿博
2023-03-14

甲骨文的官方文档呢?它们在代码中显示了DH密钥交换。

 类似资料:
  • 我试图用Java实现Diffie-Hellman密钥交换,但我很难理解规范: 根据JWA(RFC 7518),在直接密钥协商模式下,使用曲线P-256、dT和QC完成Diffie-Hellman密钥交换过程,作为本地机制,产生一对由事务ID标识的CEK(每个方向一个)。本规范版本支持的参数值为: alg: ECDH-ES "apv": SDK参考号 epk:QC,JSON Web Key(JWK)

  • 在Diffie Hellman密钥交换过程中,如果中间的人能够得到素数“p”和生成器“g”的值。他现在能破译私钥或者生成的共享秘密秘密吗?

  • 因为这是我正在生成的一个自签名证书,所以我认为我做错了什么。 我首先创建一个根CA证书,并传入私钥来签署我的证书。 方法返回true,我读到的这个值可能返回假阳性。

  • 我正在尝试将DHE_DSS实现到Go的Crypto/TLS包中。不幸的是,我似乎无法使PreMasterSecret(Z)相同,我的基本工作流程是: 提取P、G、YS 使用提供的数字签名进行验证 null 以下是我更改的一个补丁: https://08766345559465695203.googlegroups.com/attach/48587532C74B4348/crypto.patch?p

  • 本文向大家介绍迪菲-赫尔曼密钥交换(Diffie–Hellman)算法原理和PHP实现版,包括了迪菲-赫尔曼密钥交换(Diffie–Hellman)算法原理和PHP实现版的使用技巧和注意事项,需要的朋友参考一下 迪菲-赫尔曼(Diffie–Hellman)是一个可以让双方在不安全的公共信道上建立秘钥的一种算法,双方后期就可以利用这个秘钥加密(如RC4)内容。 迪菲-赫尔曼(Diffie–Hellm

  • 我有一个应用程序,它是一个SSH客户端,支持以下协商的关键算法。 diffie-hellman-group-exchange-sha1 diffie-hellman-group14-sha1 diffie-hellman-group-exchange-sha256 我没有更改SSH客户端的选项,所以我正在尝试解决SSH服务器上的问题,它正在使用Twisted。SSH服务器实际上是在Kippo蜜罐中