Как сделать тройное соглашение о ключах Диффи-Хеллмана (3 - DH) в Java с использованием надувного замка?

Существует множество примеров того, как выполнить соглашение о ключах Диффи-Хеллмана для вычисления общего секрета. Однако я не смог найти ни одного примера того, как сделать 3DH в java с помощью надувного замка (или, если честно, какой-либо безопасности). Все, что я нахожу, читая, является абстрактной теорией, а не реальной реальной реализацией/примером.

В частности, как можно объединить три индивидуально рассчитанных соглашения о ЦТ? Хорошим источником для справки может быть протокол соглашения 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(); 

Чтобы быть точным в том, что я ищу, как это сделать SK = KDF(DH1 || DH2 || DH3)уже вычислив DH1 DH2 и DH3 в надувном замке? IE, как объединить secret1, secret2 и secret3 в качестве входного ключевого материала или начального числа для HKDFParameters?

1 ответ

Как уже упоминал @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), что мне еще предстоит понять. Тем не менее, приведенный выше код работает для меня.

Другие вопросы по тегам