Как сделать тройное соглашение о ключах Диффи-Хеллмана (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), что мне еще предстоит понять. Тем не менее, приведенный выше код работает для меня.