Не удается проверить подпись с помощью вызовов функций в стиле C

Следующие распечатки FAIL, и я не могу понять, почему:

#include <cryptopp/eccrypto.h>
#include <cryptopp/oids.h>
#include <cryptopp/osrng.h>
#include <iostream>
using namespace std;
using namespace CryptoPP;
int main() {
AutoSeededRandomPool prng;
ECDSA<ECP, SHA256>::PrivateKey private_key;
ECDSA<ECP, SHA256>::PublicKey public_key;
private_key.Initialize( prng, ASN1::secp160r1() );
private_key.MakePublicKey(public_key);
ECDSA<ECP, SHA256>::Signer signer(private_key);
ECDSA<ECP, SHA256>::Verifier verifier(public_key);
signer.AccessKey().Initialize(prng, ASN1::secp160r1());
string signature(signer.MaxSignatureLength(), 0);
string message = "asdf";
auto signature_length = signer.SignMessage(
prng, (const byte*)message.data(),
message.size(), (byte*)signature.data());
signature.resize(signature_length);
bool verified = verifier.VerifyMessage(
(const byte*)message.data(), message.size(),
(const byte*)signature.data(), signature.size());
if (verified)
cout << "PASS" << endl;
else
cout << "FAIL" << endl;
}

Это следует инструкциям в crypto ++ wiki: https://www.cryptopp.com/wiki/ECDSA#Message_Signing и проверяет с помощью открытого ключа, полученного из частного, используемого для подписания того же сообщения. Должен ли я перейти на фильтры?

-1

Решение

Следующие распечатки FAIL, и я не могу понять, почему:

Вы близки. Глядя на вики-страницу, есть несколько проблем. Во-первых, это неопределенное поведение (это было исправлено в вики):

auto signature_length = signer.SignMessage(
prng, (const byte*)message.data(),
message.size(), (byte*)signature.data());

Чтобы получить неконстантный указатель, вам нужно это (но это не является причиной вашей проблемы):

auto signature_length = signer.SignMessage(
prng, (const byte*)&message[0],
message.size(), (byte*)&signature[0]);

Во-вторых, когда вы звоните Initialize дважды ты ударишь старую конфигурацию. «Whack» означает, что вы генерируете новые параметры. Фактически вы перезаписали другой закрытый ключ:

private_key.Initialize( prng, ASN1::secp160r1() );
...
signer.AccessKey().Initialize(prng, ASN1::secp160r1());

Это не очевидно, но Initialize это занимает prng генерирует новый ключ. Вы хотите Initialize тот не взять prng:

private_key.Initialize( prng, ASN1::secp160r1() );
...
signer.AccessKey().Initialize(private_key);

В-третьих, на странице непонятно, как перемещаться между Signers / Verifiers и PublicKey / PrivateKey. Вот несколько других способов сделать это для наглядности:

cryptopp $ cat test.cxx
#include "eccrypto.h"#include "oids.h"#include "osrng.h"#include <string>
#include <iostream>

int main()
{
using namespace CryptoPP;
AutoSeededRandomPool prng;

ECDSA<ECP, SHA256>::Signer signer;
ECDSA<ECP, SHA256>::Verifier verifier;

signer.AccessKey().Initialize(prng, ASN1::secp160r1());
signer.AccessKey().MakePublicKey(verifier.AccessKey());

std::string signature(signer.MaxSignatureLength(), 0);
std::string message = "asdf";

auto signature_length = signer.SignMessage(
prng, (const byte*)&message[0],
message.size(), (byte*)&signature[0]);
signature.resize(signature_length);

bool verified = verifier.VerifyMessage(
(const byte*)&message[0], message.size(),
(const byte*)&signature[0], signature.size());

if (verified)
std::cout << "PASS" << std::endl;
else
std::cout << "FAIL" << std::endl;

return 0;
}

Я работаю из каталога Crypto ++, так что include и командная строка немного отличаются:

cryptopp$ g++ -I . test.cxx ./libcryptopp.a -o test.exe
cryptopp$ ./test.exe
PASS

Если вы хотите использовать как Signers / Verifiers, так и PublicKey / PrivateKey, попробуйте что-то вроде:

cryptopp$ cat test.cxx
#include "eccrypto.h"#include "oids.h"#include "osrng.h"#include <string>
#include <iostream>

int main()
{
using namespace CryptoPP;
AutoSeededRandomPool prng;

ECDSA<ECP, SHA256>::Signer signer;
ECDSA<ECP, SHA256>::Verifier verifier;

ECDSA<ECP, SHA256>::PrivateKey& sKey = signer.AccessKey();
sKey.Initialize(prng, ASN1::secp160r1());
ECDSA<ECP, SHA256>::PublicKey& pKey = verifier.AccessKey();
sKey.MakePublicKey(pKey);

std::string signature(signer.MaxSignatureLength(), 0);
std::string message = "asdf";

auto signature_length = signer.SignMessage(
prng, (const byte*)&message[0],
message.size(), (byte*)&signature[0]);
signature.resize(signature_length);

bool verified = verifier.VerifyMessage(
(const byte*)&message[0], message.size(),
(const byte*)&signature[0], signature.size());

if (verified)
std::cout << "PASS" << std::endl;
else
std::cout << "FAIL" << std::endl;

return 0;
}

Это выглядит немного необычно:

ECDSA<ECP, SHA256>::Signer signer;
...
signer.AccessKey().Initialize(prng, ASN1::secp160r1());

Обычно вы используете {secp160r1, SHA1} или же {secp256k1, SHA256}, Это поддерживает Уровни безопасности системы в целом. Когда вы используете {secp160r1, SHA256} вы снижаете уровень безопасности примерно до 80 бит из-за secp160r1,

0

Другие решения

Других решений пока нет …

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector