Проблема в том, что Curve25519 не генерирует одинаковые общие ключи ...
curve25519 описывает базовое поле.x25519 - ключевое соглашение по области.Каждый запуск протокола создает новый общий секрет.Это происходит потому, что каждый раз, когда запускается протокол, используется новый набор случайных параметров.
Вот как вы выполняете согласование ключей с x25519 .x25519 - это схема согласования ключей Бернштейна с использованием кривой25519.Пример кода ниже был взят из Crypto ++ wiki .
Сначала создайте несколько эфемерных ключей:
AutoSeededRandomPool rndA, rndB;
x25519 ecdhA(rndA), ecdhB(rndB);
SecByteBlock privA(ecdhA.PrivateKeyLength());
SecByteBlock pubA(ecdhA.PublicKeyLength());
ecdhA.GenerateKeyPair(rndA, privA, pubA);
SecByteBlock privB(ecdhB.PrivateKeyLength());
SecByteBlock pubB(ecdhB.PublicKeyLength());
ecdhB.GenerateKeyPair(rndB, privB, pubB);
Во-вторых, настройте общий секретный буфер:
SecByteBlock sharedA(ecdhA.AgreedValueLength());
SecByteBlock sharedB(ecdhB.AgreedValueLength());
В-третьих, выполните протокол соглашения:
if(!ecdhA.Agree(sharedA, privA, pubB))
throw std::runtime_error("Failed to reach shared secret (1)");
if(!ecdhB.Agree(sharedB, privB, pubA))
throw std::runtime_error("Failed to reach shared secret (2)");
Наконец, вы можете проверить ключи:
HexEncoder encoder(new FileSink(std::cout));
std::cout << "Shared secret (A): ";
StringSource(sharedA, sharedA.size(), true, new Redirector(encoder));
std::cout << std::endl;
std::cout << "Shared secret (B): ";
StringSource(sharedB, sharedB.size(), true, new Redirector(encoder));
std::cout << std::endl;
Пример вывода похож на следующий.
$ ./test.exe
Shared secret (A): B5C105BC3B685869AFBDFE64F15D27D6D0EAAA1A22F03B45B86E09FC76522450
Shared secret (B): B5C105BC3B685869AFBDFE64F15D27D6D0EAAA1A22F03B45B86E09FC76522450
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * имеет много ручных отказов.Вам все еще нужно отправить открытую часть эфемерного ключа другой стороне.И эфемерный открытый ключ, отправленный другой стороне, должен быть подписан, чтобы другая сторона знала, что он является подлинным.
... для подписи и проверки ...
Вот как вы подписываетесь с помощью ed25519 схемы подписи.ed25519 - это схема подписи Бернштейна с использованием кривой25519.Приведенный ниже пример кода был взят из Crypto ++ wiki .
. Сначала создайте ключ подписи:
ed25519::Signer signer;
signer.AccessPrivateKey().GenerateRandom(prng);
Во-вторых, сохраните ключ подписи:
FileSink fs("private.key.bin");
signer.GetPrivateKey().Save(fs);
В-третьих, подпишите сообщение с помощью закрытого ключа:
AutoSeededRandomPool prng;
HexEncoder encoder(new FileSink(std::cout));
std::string message = "Yoda said, Do or do not. There is no try.";
std::string signature;
// Determine maximum signature size
size_t siglen = signer.MaxSignatureLength();
signature.resize(siglen);
// Sign, and trim signature to actual size
siglen = signer.SignMessage(prng, (const byte*)&message[0], message.size(), (byte*)&signature[0]);
signature.resize(siglen);
// Print signature to stdout
std::cout << "Signature: ";
StringSource(signature, true, new Redirector(encoder));
std::cout << "\n" << std::endl;
Пример вывода выглядит следующим образом.
$ ./test.exe
Signature: B8EABDAA754BBCDC0B11ADE1FBA52CE39CD52FF42DE95E44CA6103652171468B63446
81DFB09F0D556EBF01BE43064D90C76711D9E1FF0FD3C41AF843DF17909
Вы можете сохранить свой открытый ключсо следующим кодом.Затем передайте ваш открытый ключ другим людям.
ed25519::Signer signer;
...
ed25519::Verifier verifier(signer);
FileSink fs("public.key.bin");
verifier.GetPublicKey().Save(fs);
... Я думал, что смогу совместить это с HMAC, CMAC или другим алгоритмом [для подписи] ...
Я не уверен, что делать с схемой, которую вы предлагаете, или с использованием HMAC и CMAC.Как отмечает @Maarten в комментариях, вы не описываете, что вы пытаетесь сделать, и не излагаете алгоритм.Я собираюсь оставить это в покое.
Обычно в вашем случае использования вы получаете общий секрет, используя Диффи-Хеллмана.Затем вы получаете пару ключей для блочного шифра или потокового шифра и MAC.Вы обычно делаете это с чем-то вроде HDKF
.Наконец, вы вводите шифр и макинтош, а затем выполняете массовое шифрование.
Я рискну предположить, что, как только вы получите общий секрет с ecdhA.Agree(sharedA, privA, pubB)
и / или ecdhB.Agree(sharedB, privB, pubA)
, получите ключ с помощьюHKDF
, а затем используйте полученный ключ для ключа ChaCha20Poly1305
или XChaCha20Poly1305
(или другого шифрования с проверкой подлинности * шифра режима 1081 *)
При использовании ChaCha20Poly1305
или XChaCha20Poly1305
каждое сообщение должно (обязательно!) Получать уникальный одноразовый номер.Просто запустите счетчик и увеличивайте его после каждого сообщения.