如何使用 bouncy castle 在 Java 中进行三重 Diffie-Hellman(3 - DH) 密钥协商?

发布于 2025-01-10 16:10:45 字数 966 浏览 0 评论 0原文

有很多关于如何进行 Diffie-Hellman 密钥协商来计算共享密钥的示例。但是,我找不到任何关于如何使用 bouncy castle 在 java 中执行 3DH 的示例(或者老实说提供的任何安全性)。我发现、阅读的所有内容都是抽象理论,而不是实际的实现/示例。

更具体地说,如何将三个单独计算的 DH 协议结合起来? Signal 的 x3dh 协议协议 是一个很好的参考来源:

伪代码

    DH1 = DH(IKA, SPKB)
    DH2 = DH(EKA, IKB)
    DH3 = DH(EKA, SPKB)
    SK = KDF(DH1 || DH2 || DH3)

或者:

KeyAgreement ka1 = KeyAgreement.getInstance("X448",BouncyCastleProvider.PROVIDER_NAME); ka1.init(iPrivKey); //initator Private Key
ka1.doPhase(rPubKey, true); //recipient Public Key
byte[] secret1 = ka1.generateSecret();
... 

byte[] secret2 = ka2.generateSecret(); 
...

byte[] secret3 = ka3.generateSecret(); 

为了准确地说明我正在寻找的内容,如何在已经计算出 DH1 的情况下执行 SK = KDF(DH1 || DH2 || DH3)充气城堡里的DH2和DH3? IE 如何组合secret1、secret2 和secret3 作为HKDFParameters 的输入密钥材料或种子?

There are ample examples on how to do Diffie-Hellman key agreement to compute a shared secret. However, I could not find any example on how to do 3DH in java using bouncy castle(or any security provided to be honest). All of what I am finding, reading is abstract theory, and not actual real implementation/example.

More specifically, how can the three individually computed DH agreements be combined?
A good source of reference could be Signal's x3dh agreement protocol :

pseudo code

    DH1 = DH(IKA, SPKB)
    DH2 = DH(EKA, IKB)
    DH3 = DH(EKA, SPKB)
    SK = KDF(DH1 || DH2 || DH3)

or alternatively:

KeyAgreement ka1 = KeyAgreement.getInstance("X448",BouncyCastleProvider.PROVIDER_NAME); ka1.init(iPrivKey); //initator Private Key
ka1.doPhase(rPubKey, true); //recipient Public Key
byte[] secret1 = ka1.generateSecret();
... 

byte[] secret2 = ka2.generateSecret(); 
...

byte[] secret3 = ka3.generateSecret(); 

To be exactly precise on what I am looking for how to do SK = KDF(DH1 || DH2 || DH3) having already computed DH1 DH2 and DH3 in bouncy castle? I.E how to combine secret1, secret2 and secret3 as input keying material or seed for HKDFParameters?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

玩套路吗 2025-01-17 16:10:45

正如@Topaco 所提到的,它只是三个共享秘密的简单串联。 Java 代码如下:

     byte[] getAgreementBytes(PrivateKey privKey,PublicKey pubKey) throws NoSuchAlgorithmException, NoSuchProviderException, InvalidKeyException {
        KeyAgreement ka = KeyAgreement.getInstance("X448", BouncyCastleProvider.PROVIDER_NAME);
        ka.init(privKey);
        ka.doPhase(pubKey, true);
        byte[] secret = ka.generateSecret();
        privKey = null;//let gc do it's work
        return secret;
    }
...
...
...

        byte[] secretA = getAgreementBytes(iPrivKeyA,getRPubKeyB());
        byte[] secretB = getAgreementBytes(iPrivKeyB,getRPubKeyC());
        byte[] secretC = getAgreementBytes(iPrivKeyC,getRPubKeyA());

        byte[] secret = new byte[secretA.length + secretB.length + secretC.length];
        System.arraycopy(secretA,0,secret,0,secretA.length);
        System.arraycopy(secretB,0,secret,secretA.length,secretB.length);
        System.arraycopy(secretC,0,secret,secretA.length + secretB.length,secretC.length);

        return secret;

信号文档还提到使用 57 0xFF 字节(对于 X448),但我还没有理解。但是,上面的代码对我有用。

As mentioned by @Topaco it is just plain concatenation of the three shared secrets. Java code follows:

     byte[] getAgreementBytes(PrivateKey privKey,PublicKey pubKey) throws NoSuchAlgorithmException, NoSuchProviderException, InvalidKeyException {
        KeyAgreement ka = KeyAgreement.getInstance("X448", BouncyCastleProvider.PROVIDER_NAME);
        ka.init(privKey);
        ka.doPhase(pubKey, true);
        byte[] secret = ka.generateSecret();
        privKey = null;//let gc do it's work
        return secret;
    }
...
...
...

        byte[] secretA = getAgreementBytes(iPrivKeyA,getRPubKeyB());
        byte[] secretB = getAgreementBytes(iPrivKeyB,getRPubKeyC());
        byte[] secretC = getAgreementBytes(iPrivKeyC,getRPubKeyA());

        byte[] secret = new byte[secretA.length + secretB.length + secretC.length];
        System.arraycopy(secretA,0,secret,0,secretA.length);
        System.arraycopy(secretB,0,secret,secretA.length,secretB.length);
        System.arraycopy(secretC,0,secret,secretA.length + secretB.length,secretC.length);

        return secret;

The signal doc also mentions using 57 0xFF bytes (for X448), which I am yet to make sense of. However, the above code works for me.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文