簡體   English   中英

Java客戶端和nodejs服務器之間的Diffie Hellman密鑰交換

[英]Diffie Hellman Key exchange between Java Client an nodejs Server

我的 android 應用程序有節點 js 服務器,我希望使用 DH 密鑰交換來保護通信。 我能夠在與nodejs相同的java中生成Prime p和Base g (如果不正確可以更正)

問題:

1.我想在客戶端和服務器端都使用秘密pg ,因為雙方都會進行加密和解密,但文檔中顯示的crypto.createDiffieHellman() nodejs 函數僅采用bitlength參數,所以我很難-在發現存在其他方法簽名后對這些參數進行編碼。 從文檔中,我知道應該只共享公鑰。 這些pg最初是在客戶端生成的

2.在下面的示例代碼中,密鑰和秘密生成在 nodejs 中運行良好,但是當我使用來自客戶端的公鑰進行測試時(使用new String(Hex.encodeHex(kp.getPublic().getEncoded())) ),我收到Error: Supplied key is too large at DiffieHellman.dhComputeSecret

在一天多的時間里,我的深入研究沒有揭示兩種不同語言之間 DH 密鑰交換的示例/演示,而是一種語言示例,其中有幾篇評論/文章討論了現有的 wiki 文檔,並且很少或沒有代碼。 我認為這是一個關於帶有 DH 密鑰的跨語言客戶端-服務器的新問題。

節點:

var crypto = require("crypto");
    var assert = require("assert");
// the prime is shared by everyone
    var p ="7287927445664946359687239486223244248530331441696747442753348226106279800740207968417650493105155177035805265358863967196769895080354517146585830093038907";
    var g="3519494160132765249824212078020429853238178237852596056897517714427148886750491954575952859563331424777669938328249242087811536189850912851560984760609308";
    let server = crypto.createDiffieHellman(Buffer.from(p,).toString("hex"),"hex",Buffer.from(g,).toString("hex"),"hex");
    let prime = server.getPrime();
    console.log("Generate Alice's keys...");
    console.log(Buffer.from(prime).toString());
    let alice = crypto.createDiffieHellman(prime);
    let alicePublicKey = alice.generateKeys();
    console.log("Generate Bob's keys...");
    let bob = crypto.createDiffieHellman(prime);
    //let bobPublicKey = bob.generateKeys();
    //THIS IS PUBLIC KEY FROM JAVA IN HEX FORMAT
    let bobPublicKey = Buffer.from("3081df30819706092a864886f70d0103013081890241008b26a5b60fd75471c366a0e8f67abe84d6f4c16b0dc97a602937420af3a658b34bb484df2d85281417a1bde4c0c51a7f97e8ac3a70fb34f092c2b1ebba01253b02404332edd9db0820ef954487cc1b327c638e2876b88a0cabc498811b42f7528af7fe58286a521f2190e9cc8785feaa5a8f019624bf88587a8b5b79854a11bcea1c02020180034300024012e116bc4fbd90542e03c1a5a130f923e579b65a50b8ed02e61f6369375f3a17ef270b3d05c52085ffe6e185ec7b19ea3cba7fe40d87e62254dc15f0e6db63b5","hex");
    console.log("Exchange and generate the secret...");
    let aliceBobSecret = alice.computeSecret(bobPublicKey);
    let bobAliceSecret = bob.computeSecret(alicePublicKey);
    // let davidAliceSecret = david.computeSecret(alicePublicKey, "latin1");
    // let aliceDavidSecret = alice.computeSecret(davidPublicKey, "latin1");
 console.log("alicePublicKey", alicePublicKey);
 console.log("bobPublicKey", bobPublicKey);
    assert.notEqual(alicePublicKey, bobPublicKey);
    console.log("alicePublicKey and bobPublicKey NOT equal");
// console.log("aliceBobSecret", aliceBobSecret.toString("latin1"));
// console.log("bobAliceSecret", bobAliceSecret.toString("latin1"));
    assert.equal(aliceBobSecret.toString("hex"), bobAliceSecret.toString("hex"));
    console.log("aliceBobSecret and bobAliceSecret equal");

爪哇:

//THIS COMMENTED CODE IS USED TO INITIALLY GENERATE p AND g
/*AlgorithmParameterGenerator paramGen = AlgorithmParameterGenerator.getInstance("DH");
    paramGen.init(512); // number of bits
    AlgorithmParameters params = paramGen.generateParameters();
    DHParameterSpec dhSpec = (DHParameterSpec) params.getParameterSpec(DHParameterSpec.class);
    BigInteger p512 = dhSpec.getP();
    BigInteger g512 = dhSpec.getG();*/
    BigInteger p512 = new BigInteger(Hex.decodeHex("008b26a5b60fd75471c366a0e8f67abe84d6f4c16b0dc97a602937420af3a658b34bb484df2d85281417a1bde4c0c51a7f97e8ac3a70fb34f092c2b1ebba01253b"));
    BigInteger g512 = new BigInteger(Hex.decodeHex("4332edd9db0820ef954487cc1b327c638e2876b88a0cabc498811b42f7528af7fe58286a521f2190e9cc8785feaa5a8f019624bf88587a8b5b79854a11bcea1c"));
//A
    KeyPairGenerator akpg = KeyPairGenerator.getInstance("DiffieHellman");
    DHParameterSpec param = new DHParameterSpec(p512, g512);
    String a = p512 + "";
    String b = g512 + "";
    System.out.println("Prime: " + new String(Hex.encodeHex(p512.toByteArray())));
    System.out.println("PrimeH: " + p512);
    System.out.println("Base: " + new String(Hex.encodeHex(g512.toByteArray())));
    System.out.println("BaseH: " + g512);
    akpg.initialize(param);
    KeyPair kp = akpg.generateKeyPair();
//B
    KeyPairGenerator bkpg = KeyPairGenerator.getInstance("DiffieHellman");
    DHParameterSpec param2 = new DHParameterSpec(p512, g512);
    System.out.println("Prime: " + p512);
    System.out.println("Base: " + g512);
    bkpg.initialize(param2);
    KeyPair kp2 = bkpg.generateKeyPair();
    KeyAgreement aKeyAgree = KeyAgreement.getInstance("DiffieHellman");
    KeyAgreement bKeyAgree = KeyAgreement.getInstance("DiffieHellman");
    aKeyAgree.init(kp.getPrivate());
    bKeyAgree.init(kp2.getPrivate());
    System.out.println("2Key: " +new String(Hex.encodeHex(kp.getPublic().getEncoded())));
    aKeyAgree.doPhase(kp2.getPublic(), true);
    bKeyAgree.doPhase(kp.getPublic(), true);
//System.out.println("Alice Secret Key: " + aKeyAgree.generateSecret());
//System.out.println("Bob's Secret Key: " + bKeyAgree.generateSecret());
    MessageDigest hash = MessageDigest.getInstance("SHA-256");
    /*byte[] ASharedSecret = hash.digest(aKeyAgree.generateSecret());
    byte[] BSharedSecret = hash.digest(bKeyAgree.generateSecret());*/
    byte[] ASharedSecret = aKeyAgree.generateSecret();
    byte[] BSharedSecret = bKeyAgree.generateSecret();
    System.out.println("Alice's Shared Secret: " + Arrays.toString(ASharedSecret));
    System.out.println("Bob's Shared Secret: " + Arrays.toString(BSharedSecret));

這是 NodeJS 和 Java 中 DH 密鑰交換的一個工作示例。

節點:

// Step 1. Generate Alice DH key in NodeJS side
let crypto = require('crypto');
let dh = crypto.getDiffieHellman('modp14');
dh.generateKeys();

let alicePublicKey = dh.getPublicKey().toString('hex');
console.log(alicePublicKey);    // 308a5cff.....e6ded9d5  ----> send to Bob

// Step 5. Check shared secret
let bobPublicKey = "00a8e459...61e210d9";     // <---- receive from Bob   
let shared = dh.computeSecret(Buffer.from(bobPublicKey, "hex"), null, 'hex');   
console.log(shared);    // dd83430d...22156ebd - must be the same as in the Java side

爪哇:

void testDH() {
    // Step 2. Configure DH params on Java side
    DHParameterSpec modp14 = modp14();

    // Step 3. Encode public key from Alice
    byte[] alicePubKeyEnc = hexStringToByteArray("308a5cff.....e6ded9d5");
    BigInteger alicePublic = new BigInteger(alicePubKeyEnc);

    KeyFactory bobKeyFactory = KeyFactory.getInstance("DH");
    DHPublicKeySpec bobPubKeySpecs = new DHPublicKeySpec(
        alicePublic,        // <---- use Alice's public
        modp14.getP(), 
        modp14.getG());        
    DHPublicKey alicePubKey = (DHPublicKey)bobKeyFactory.generatePublic(bobPubKeySpecs);

    // Step 4. Generate Bob DH key in Java side
    KeyPairGenerator bobKpairGen = KeyPairGenerator.getInstance("DH");
    bobKpairGen.initialize(modp14);
    KeyPair bobKpair = bobKpairGen.generateKeyPair();
    System.out.println("Bob public key: " 
        + bytesToHex(((DHPublicKey)bobKpair.getPublic()).getY().toByteArray()));      
    // 00a8e459...61e210d9

    // Step 6. Generates shared secret
    KeyAgreement bobKeyAgree = KeyAgreement.getInstance("DH");
    bobKeyAgree.init(bobKpair.getPrivate());
    bobKeyAgree.doPhase(alicePubKey, true);

    byte[] bobSharedSecret = new byte[alicePubKeyEnc.length];
    bobKeyAgree.generateSecret(bobSharedSecret, 0);
    System.out.println("Bob's shared secret: "
         +  bytesToHex(bobSharedSecret));     // dd83430d...22156ebd
}

public static DHParameterSpec modp14() {
    final BigInteger p =
            new BigInteger(
                    "ffffffffffffffffc90fdaa22168c234c4c6628b80dc1c" +
                            "d129024e088a67cc74020bbea63b139b22514a08798e3404" +
                            "ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c2" +
                            "45e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7" +
                            "edee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b" +
                            "3dc2007cb8a163bf0598da48361c55d39a69163fa8fd24cf" +
                            "5f83655d23dca3ad961c62f356208552bb9ed52907709696" +
                            "6d670c354e4abc9804f1746c08ca18217c32905e462e36ce" +
                            "3be39e772c180e86039b2783a2ec07a28fb5c55df06f4c52" +
                            "c9de2bcbf6955817183995497cea956ae515d2261898fa05" +
                            "1015728e5a8aacaa68ffffffffffffffff",
                    16);
    final BigInteger g = new BigInteger("2");
    return new DHParameterSpec(p, g);
}
  • 使用 NodeJS v17.0.1 和 OpenJDK 14.0.1 進行測試。
  • 看到這個關於使用modp14 問題

我試圖在 Node.JS 中模擬 java Diffie Hellman 算法

爪哇:

private static byte[] getSharedSecretKey() {
try {
        String key = "OoJcHg4+2ady0ULZJGFWK0giozYA9Je0Aacu1q9ElbU=";
        String prime = "qYsHeFZ0HlCU+Bnk3zmmtQr+ZkIkux8M/EQVSvzXFZs=";
        KeyPair generateKeyPair;
        DHParameterSpec dHParameterSpec = new DHParameterSpec(new BigInteger(1, Base64.decode(prime,2)), BigInteger.valueOf(2));
        KeyPairGenerator instance = KeyPairGenerator.getInstance("DiffieHellman");
        instance.initialize(dHParameterSpec);
        generateKeyPair = instance.generateKeyPair();
        KeyAgreement keyAgreement = KeyAgreement.getInstance("DiffieHellman");
        PrivateKey privateKey = generateKeyPair.getPrivate();

        keyAgreement.init(privateKey);

        String encodeToString3 = Base64.encodeToString(((DHPublicKey) generateKeyPair.getPublic()).getY().toByteArray(), 2);
        Log.i("pooya2",encodeToString3);
        

        PublicKey generatePublic = KeyFactory.getInstance("DiffieHellman").generatePublic(new DHPublicKeySpec(new BigInteger(1, Base64.decode(key,2)), new BigInteger(1, Base64.decode(prime,2)), BigInteger.valueOf(2)));
        keyAgreement.doPhase(generatePublic, true);
        byte[] bArr = keyAgreement.generateSecret();
        return bArr;
    }catch (Exception e)
    {
        return null;
    }
}

節點.js:

const crypto = require('crypto');

var p ="qYsHeFZ0HlCU+Bnk3zmmtQr+ZkIkux8M/EQVSvzXFZs=";
var g= "Mg==";
let diffiehellmangrp1 = crypto.createDiffieHellman(p,"base64",g,"base64");
let diffiehellmangrp2 = crypto.createDiffieHellman(p,"base64",g,"base64");


// Generating keys

let alicePublicKey = diffiehellmangrp1.generateKeys();
let bobPublicKey = diffiehellmangrp2.generateKeys();
console.log("alicePublicKey", alicePublicKey);
console.log("alicePublicKey", 
diffiehellmangrp1.getPublicKey().toString('base64'));
console.log("bobPublicKey", bobPublicKey);
const diffiehellmangrp1sc = diffiehellmangrp1.computeSecret(Buffer.from("OoJcHg4+2ady0ULZJGFWK0giozYA9Je0Aacu1q9ElbU=","base64"), null, 'base64');
console.log("aliceKey", diffiehellmangrp1sc);

const diffiehellmangrp2sc = diffiehellmangrp2.computeSecret(Buffer.from("OoJcHg4+2ady0ULZJGFWK0giozYA9Je0Aacu1q9ElbU=","base64"), null, 'base64');
console.log("bobKey", diffiehellmangrp2sc);

Node.js 代碼是否正確? 這不能正常工作

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM