OpenSSL иногда генерирует неверную подпись - PullRequest
0 голосов
/ 16 октября 2018

У меня есть программа на C ++, пара ключей ECDSA и строка для подписи.Программа генерирует подпись и сохраняет ее в файл (signature.bin).Затем я проверяю действительность подписи с помощью следующей команды:

openssl dgst -verify ec_public.pem -signature signature.bin ToSign.txt

проблема в том, что программа иногда генерирует неправильную подпись .16 раз из 21 вышеприведенных командных выходных данных:

Error Verifying Data

, в то время как в оставшихся 5 случаях она выдает:

Verified OK

Как это возможно?

Здесьтакое программа:

SSL_library_init();
OPENSSL_config(nullptr);
SSL_load_error_strings();
OpenSSL_add_all_algorithms();
ERR_load_BIO_strings();
CRYPTO_set_id_callback(ThreadIdFunction);
CRYPTO_set_locking_callback(LockingFunction);

const TString pk = "-----BEGIN EC PRIVATE KEY-----\n"
                       "MHcCAQEEIG90zmo1o3NWNFa8wp2z4rdQXGSN8xAP/OATLpwlgi+1oAoGCCqGSM49\n"
                       "AwEHoUQDQgAE5TwpzBhjUWZoOf629GfwGG5WlRJD7TSuz+ZTHUaiK5mj2qgxBOPk\n"
                       "eqOrTYXsiPwnaWe23zHjIM8NOhAm1BiGgA==\n"
                       "-----END EC PRIVATE KEY-----\n";

const TString ToSign = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJhc2RmIn0";

EVP_MD_CTX *Ctx    = EVP_MD_CTX_create();
BIO *       Bio    = BIO_new_mem_buf(pk.data(), pk.size());
EVP_PKEY *  EVPKey = PEM_read_bio_PrivateKey(Bio, nullptr, nullptr, nullptr);

EVP_DigestSignInit(Ctx, nullptr, EVP_sha256(), nullptr, EVPKey);
EVP_DigestSignUpdate(Ctx, ToSign.data(), ToSign.size());
size_t SignatureLength;
EVP_DigestSignFinal(Ctx, nullptr, &SignatureLength);

TString Result;
Result.resize(SignatureLength);
EVP_DigestSignFinal(Ctx, reinterpret_cast<unsigned char *>(const_cast<char *>(Result.data())), &SignatureLength);

// Saving to file...

1 Ответ

0 голосов
/ 17 октября 2018

Вы вызываете правильные методы OpenSSL.Однако вы не объяснили подробно, как вы сохраняете Result в файл.Исходя из его имени, TString, вероятно, ведет себя как строка с нулем в конце.Если это так, то подпись не будет правильно записана в файл, но урезана слишком рано, если она содержит 0-байт.Обратите внимание, что шаги подписи ECDSA включают случайный компонент, поэтому сигнатура меняется каждый раз, когда вы запускаете свой код.

Следующие рассуждения подтверждают это предположение и приблизительно объясняют, почему ваш код дает сбой и выполняется так же часто, как и он.Если вы прочитаете это объяснение о формате подписи ECDSA , вы увидите, что 0-байт очень часто встречается в таких сигнатурах.Вероятность составляет примерно 3/4 для первых байтов компонентов r и s вместе взятых.Тогда есть дополнительная вероятность 1- (255/256) ^ 64, около 1/4, что оставшиеся 64 байта будут содержать 0. Таким образом, вероятность сбоя составляет примерно 3/4 + 1/4 * 1/4., около 80%.

Ваше пространство выборки невелико, но с учетом этой строковой ошибки 5 успехов из 21 попытки является вероятным результатом.

...