Encryption
(EC-)Diffie-Hellman 的驗證結果
我收到了 JSON 的公鑰。
例如,我有 4 個密鑰:2 個公鑰和 2 個私鑰。
public A : co2D0pNxZJIeQ4RZlCRJYBDzNXSLluETdztid0M+HGzN1uGJ4JWZsenjWgRrmkLh3yqHQqzOBMl/wHVH97A6+g== private A : TXxii5Ka8LMvuc9arHu63qTmNKxGlgti+wpR3YhBGew= public B : nUblC+OKdl94iBiWk0941wmYBiMt7C90CjOJPI2BPr8K7xGuC1XsR5DtwFCoM3Iew2BjBG+5SqrYwAPTJF7gdA== private B : sm6V7+hChvkFSeLNoR+5tItiX8gH5tT47xBkFaV6SDU=
我無法從我在 JSON 中收到的公鑰 A和私鑰 B進行****ECDH 交換。
如何驗證:(公鑰 A + 私鑰 B)==(公鑰 B + 私鑰 A)?
所以這就是我解決問題的方法:
我在字元串中的鍵:
public A : co2D0pNxZJIeQ4RZlCRJYBDzNXSLluETdztid0M+HGzN1uGJ4JWZsenjWgRrmkLh3yqHQqzOBMl/wHVH97A6+g== private A : TXxii5Ka8LMvuc9arHu63qTmNKxGlgti+wpR3YhBGew= public B : nUblC+OKdl94iBiWk0941wmYBiMt7C90CjOJPI2BPr8K7xGuC1XsR5DtwFCoM3Iew2BjBG+5SqrYwAPTJF7gdA== private B : sm6V7+hChvkFSeLNoR+5tItiX8gH5tT47xBkFaV6SDU=
獲取私鑰的函式:
public static PrivateKey getPrivateKey(byte[] encodedPrivateKey) { BigInteger s = new BigInteger(1,encodedPrivateKey); ECNamedCurveParameterSpec ecCurve = ECNamedCurveTable.getParameterSpec("secp256r1"); ECParameterSpec ecParameterSpec = new ECNamedCurveSpec("secp256r1", ecCurve.getCurve(), ecCurve.getG(), ecCurve.getN(), ecCurve.getH(), ecCurve.getSeed()); ECPrivateKeySpec privateKeySpec = new ECPrivateKeySpec(s, ecParameterSpec); try { KeyFactory keyFactory = KeyFactory.getInstance("EC"); return keyFactory.generatePrivate(privateKeySpec); } catch (NoSuchAlgorithmException | InvalidKeySpecException e) { e.printStackTrace(); return null; } } public static PublicKey rawToEncodedECPublicKey(String curveName, byte[] rawBytes) throws NoSuchAlgorithmException, InvalidKeySpecException, InvalidParameterSpecException { KeyFactory kf = KeyFactory.getInstance("EC"); byte[] x = Arrays.copyOfRange(rawBytes, 0, rawBytes.length/2); byte[] y = Arrays.copyOfRange(rawBytes, rawBytes.length/2, rawBytes.length); ECPoint w = new ECPoint(new BigInteger(1,x), new BigInteger(1,y)); return kf.generatePublic(new ECPublicKeySpec(w, ecParameterSpecForCurve(curveName))); } public static java.security.spec.ECParameterSpec ecParameterSpecForCurve(String curveName) throws NoSuchAlgorithmException, InvalidParameterSpecException { AlgorithmParameters params = AlgorithmParameters.getInstance("EC"); params.init(new ECGenParameterSpec(curveName)); return params.getParameterSpec(ECParameterSpec.class); }
我們需要通過字元串中的公鑰/私鑰創建 2 對密鑰,並檢查兩者是否相等:
byte [] cle_publique_a_decode = Base64.getDecoder().decode(cle_publique_a); byte [] cle_privee_a_decode = Base64.getDecoder().decode(cle_privee_a); byte [] cle_publique_b_decode = Base64.getDecoder().decode(cle_publique_b); byte [] cle_privee_b_decode = Base64.getDecoder().decode(cle_privee_b); try { PublicKey PublicKeyA = rawToEncodedECPublicKey("secp256r1",cle_publique_a_decode); PublicKey PublicKeyB = rawToEncodedECPublicKey("secp256r1",cle_publique_b_decode); PrivateKey PrivateKeyA = getPrivateKey(cle_privee_a_decode); PrivateKey PrivateKeyB = getPrivateKey(cle_privee_b_decode); // Secret #1 // PrivateKeyA + PublicKeyB = generateSecret KeyAgreement keyAgreement = KeyAgreement.getInstance("ECDH"); keyAgreement.init(PrivateKeyA); keyAgreement.doPhase(PublicKeyB, true); byte[] generateSecret = keyAgreement.generateSecret(); String base64_generateSecret = Base64.getEncoder().encodeToString(generateSecret); // Secret #2 // PrivateKeyB + PublicKeyA = generateSecret2 KeyAgreement keyAgreement2 = KeyAgreement.getInstance("ECDH"); keyAgreement.init(PrivateKeyB); keyAgreement.doPhase(PublicKeyA, true); byte[] generateSecret2 = keyAgreement.generateSecret(); String base64_generateSecret2 = Base64.getEncoder().encodeToString(generateSecret); // compare 2 secrets // (public key A + private key B) == (public key B + private key A) if(base64_generateSecret.equals(base64_generateSecret2)){ // Good : Secrets are same // continue.. } else{ // Not good : Secrets are differents } } catch{ throw new IllegalArgumentException(e.getMessage(), e); }
密鑰相等,我可以開始加密了。
通常(橢圓曲線)Diffie-Hellman 計算的結果稱為主機密。此主密鑰通常用作密鑰派生函式 (KDF) 的輸入密鑰材料 (IKM)。使用 KDF 可以從主密鑰派生多個密鑰。您正在尋找的東西稱為“關鍵構象”。
有多種確認對稱密鑰的方法:
- 這些密鑰之一可以用作質詢響應協議的輸入。質詢響應協議是一種對稱方法,用於驗證實體是否有權訪問正確的密鑰。
- 另一種方法是通過雙方都知道的字元串將密鑰用作 MAC 的輸入。這樣,MAC 就表明該實體可以訪問正確的密鑰。例如,TLS (1.3) 在握手的最終“Finished”消息中的整個握手過程中使用 MAC:
完成:整個握手過程中的 MAC(消息驗證碼)。此消息提供密鑰確認,將端點的身份綁定到交換的密鑰,並且在 PSK 模式下還驗證握手。
$$ Section 4.4.4 $$
- 您還可以想像,一方可以簽署生成的秘密並將簽名發送給另一方。
- 最後,當第一個經過身份驗證的消息從一方發送到另一方時,也可以隱式地確認結果密鑰和秘密相同。然而,這通常是可以避免的,因為這意味著您無法區分數據傳輸和握手錯誤;因此,它可以在協議實現中玩得開心。
筆記:
- 如果您確認一個密鑰,那麼密鑰和任何其他派生密鑰的有效性也會得到確認(除非實現錯誤)。
- DH 的(靜態)公鑰可能可以通過其他方式被信任,在這種情況下,被認證方可能不需要對生成的秘密進行額外的驗證;只有非認證方需要發送質詢-響應、MAC 或簽名值。