【问题标题】:How to implement DH keyagreement referring these Java codes?如何参考这些 Java 代码实现 DH 密钥协议?
【发布时间】:2021-10-25 08:00:45
【问题描述】:

我已经用Java写了X25519 DH keyagreement,但是我必须使用nodejs重新实现这个,这样我才能在js客户端和java后端之间进行keyagreement。

我使用了node crypto模块,但是java实现的共享密钥长度不一样。

这是我的 Java 代码,任何人都可以帮我展示 nodejs 代码。谢谢。

package com.demo;

import java.util.Base64;

import javax.crypto.KeyAgreement;
import java.security.*;
import java.security.spec.ECGenParameterSpec;
import java.security.spec.X509EncodedKeySpec;

public class Main {

    public static void main(String[] args) {
    // write your code here
        System.out.println("Hello world");

        String peerPub = "MCowBQYDK2VuAyEAfMePklV88QMhq8qlVxLI6RK1pV4cFUrMwJgPmrXLyVU=";
        try {
            buildSecret(peerPub);
        }
        catch (Exception e) {

        }

    }

    public static void buildSecret(String peerPub) throws Exception {
        KeyPairGenerator kpgen = KeyPairGenerator.getInstance("XDH");
        kpgen.initialize(new ECGenParameterSpec("X25519"));
        KeyPair myKP = kpgen.generateKeyPair();

        byte[] pp = Base64.getDecoder().decode(peerPub);
        PublicKey peerKey = bytesToPublicKey(pp);

        KeyAgreement ka = KeyAgreement.getInstance("XDH");
        ka.init(myKP.getPrivate());
        ka.doPhase(peerKey, true);

//        System.out.println( myKP.getPublic().getEncoded().length );
        String publicKey = Base64.getEncoder().encodeToString(myKP.getPublic().getEncoded());

//        System.out.println( ka.generateSecret().length );
        String sharedKey = Base64.getEncoder().encodeToString(ka.generateSecret());

        System.out.println(publicKey);
        System.out.println(sharedKey);
    }

    private static PublicKey bytesToPublicKey(byte[] data) throws Exception {
        KeyFactory kf = KeyFactory.getInstance("X25519");
        return kf.generatePublic(new X509EncodedKeySpec(data));
    }
}

nodejs 代码如下(不工作):

const crypto = require('crypto');

const ecdhKeyagreement = () => {
  const CURVE = 'x25519';
  let m_privateKey;
  let m_publicKey;
  let m_sharedKey;

  const generatePublicAndPrivateKeys = () => {

    const {publicKey, privateKey} = crypto.generateKeyPairSync('x25519', {
      modulusLength: 4096,
      publicKeyEncoding: {
        type: 'spki',
        format: 'pem'
      },
      privateKeyEncoding: {
        type: 'pkcs8',
        format: 'pem'
      }
    })

    m_privateKey = privateKey
    m_publicKey = publicKey

  }

  const computeSharedKey = (peerPub) => {
    // console.log(m_publicKey)
    // console.log(m_privateKey)

    const bob = crypto.createDiffieHellman(512)
    bob.setPrivateKey(m_privateKey)
    m_sharedKey = bob.computeSecret(peerPub).toString('base64')

    console.log(m_sharedKey)

  };


  return {
    generatePublicAndPrivateKeys,
    computeSharedKey,
  };
};

const my_obj = ecdhKeyagreement();
my_obj.generatePublicAndPrivateKeys()

const peerPub = "MCowBQYDK2VuAyEAME2NXThH2T+PMTV2R2YGo5hYiVFhu7nbQGY0R89aYFE="

my_obj.computeSharedKey(peerPub)

【问题讨论】:

    标签: java node.js encryption cryptojs diffie-hellman


    【解决方案1】:

    您没有显示您的 nodejs 代码(假定的)问题所在,这是 StackOverflow 上公认的做法,但既然您来了一半:

    使用您的 Java 代码,修改(仅)以使用我的一个测试(静态)密钥对的公共部分,并在 j16 上运行,因为 11-15 显然会产生一个带有违反 RFC8410 并被 OpenSSL 拒绝的参数的 algid 和因此使用 OpenSSL 的 nodejs 加密,以及使用相应私钥的以下简单 js 代码(在 v14.15.5 上运行),我得到与 Java 完全相同的协议结果:

    const crypto = require('crypto'), fs = require('fs')
    const peerb64 = "MCowBQYDK2VuAyEAZWJZEjPzc6E4UUSyOcMmxj2cRqqmDhE4/VfyPyfe7j4="
    console.log("sRbfKaWmO9u2eKWSfY25i8Z2YFNNiLYeVcoh6DOI2ik=") // expected agreement
    const myprv = crypto.createPrivateKey(fs.readFileSync('n:certx/x2.pem'))
    const peerpub = crypto.createPublicKey({key:Buffer.from(peerb64,'base64'),format:'der',type:'spki'})
    console.log( crypto.diffieHellman({privateKey:myprv,publicKey:peerpub}) .toString('base64') )
    

    【讨论】:

    • 非常感谢。您的解决方案完全解决了我的问题。此外,很抱歉没有发布我的 nodejs 代码,因为我确定它不起作用,我已将其添加到上面的问题描述中。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-05-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多