Проверка подписи RAW RSA с помощью библиотеки crypto ++

Как можно проверить цифровую подпись с помощью библиотеки crypto ++?

Входные данные:

  • public_key Шестнадцатеричная строка в кодировке BASE64.
  • публичный показатель от публичного ключа.
  • подпись в виде шестнадцатеричной строки.

Я не знаю, что такое закрытый ключ. Я написал эту тестовую функцию, но она всегда заканчивается ошибкой «VerifierFilter: цифровая подпись недействительна».

Ключ здесь экспортирован из действующей пары ключей!

void rawRSAVerificationTest()
{

// RSA 2048 digital signature verification
try {

    std::string pupKeyStr ("e0c3851114c758fb943a30ca8f9b4c7f506d52aa101c34ad5134f2cdbdddbef11ee6d1470d54caf3774d4d17d69488abf0b78beaebc046115cb29617610e98be3d5c303e19c14ae57ce0994701e3f24a628abf5c421777fb3c2b9b8b17f2a4cda4b9fd89e3c122085831c3e4502734bc3f3157d3ccd01198a8e3795f03661b55112acb69e8d5782bdf506bf5222777baf382d4d4bc2dd83e53af9236ed6e7a0fb8b5bb543ed4abbf478911bdc517e13e580b138f10f153eb2733ad60f3796e99b7d59f9abbd6666c69ba5ecc17a391424dc8ca3cf24a759c62d490056cda30265e11e316e7695028721c50eaf8e596161f0b59e4f598c85063bb3a847a5acb9d");
    //sha256 hashed data signature
    std::string signatureStr = "d8d1df600d6781a9c030d9c697ec928eac34bf0670cf469f7fffb9c046deaee359b4e1218b419ff2589434510db8470ccf7abd28876a04b8d5a27293723e897f97a9367d2fbb379f8c52ec2a04cb71a06891a3f44d00e8bb9622b2038dbe6f29d0118203c372853ae09fb820702f1c16ee772998bd8a3db9e5127992a18d999fc422822caf0a82d9c12d6231605457ce651b0350b1e98584f9d4e6b973d6668df863d4b73784bbc00d8449918a0f049ddbeffc0d79579ade13a2d9012906b7ded7aae934bc54c5b85c924aee6627d66b7b200a23cd9b6a9c14650f1f9384e9ef9b90ac217ece026a1802bc0623150057ecd2b31f5f758e4ff866bb2e81d28368";

    //Chinese Remainder Theorem (CRT)
    std::string pupExpStr ("0x10001");

    CryptoPP::AutoSeededRandomPool rng;
    CryptoPP::RSA::PublicKey pubKeyRaw;

    CryptoPP::Integer pup_key_cast( static_cast<CryptoPP::Integer> (pupKeyStr.c_str()));
    CryptoPP::Integer pup_exp_cast( static_cast<CryptoPP::Integer> (pupExpStr.c_str()));

    pubKeyRaw.Initialize(pup_key_cast, pup_exp_cast);
    if (!pubKeyRaw.Validate(rng, 3))
    {   
        std::cout << "Error while public key validation" << std::endl;
    }

    CryptoPP::RSASS<CryptoPP::PSS,  CryptoPP::SHA256>::Verifier verifier_sha256(pubKeyRaw);


    CryptoPP::StringSource( signatureStr, true,   
        new CryptoPP::SignatureVerificationFilter(   
        verifier_sha256, NULL,   
        CryptoPP::SignatureVerificationFilter::THROW_EXCEPTION   
        ) // SignatureVerificationFilter   
        ); // StringSource   

}
catch( CryptoPP::Exception& e )
{
    std::cerr << "ERROR: " << e.what() << std::endl;
}
catch( ... )
{
    std::cerr << "ERROR: Unknown verify signature error" << std::endl;
}
}

Что я пропустил?

Буду очень признателен за любую помощь! Заранее спасибо!


person Diethard    schedule 21.06.2012    source источник
comment
Что вы имеете в виду под сырым? Какая схема подписи RSA использовалась для создания подписи? PSS?   -  person Rasmus Faber    schedule 22.06.2012
comment
Для меня это больше похоже на модуль в шестнадцатеричной кодировке. Это ровно 512 символов (что означает 256 байтов или 2048 бит). Что делают операторы приведения?   -  person Maarten Bodewes    schedule 22.06.2012
comment
Я имею в виду RAW RSA: выполнение операций шифрования и дешифрования с использованием Crypto ++ с примитивами RSA.   -  person Diethard    schedule 22.06.2012
comment
Да, это модуль в шестнадцатеричной кодировке. Приведение используется для целочисленного класса crypto ++. Что импортирует строку модуля в этот класс.   -  person Diethard    schedule 22.06.2012
comment
Дополнительная информация заключается в том, что у pupKeyStr нет обычного формата контейнера PKCS # 1, это простой модуль ключа!   -  person Diethard    schedule 22.06.2012
comment
Ваша подписьStr имеет длину 32 байта. Вероятность того, что это на самом деле подпись RSA с 2048-битным ключом RSA, невероятно мала. Скорее всего, это просто хеш SHA-256. Конечно, вам нужен хеш для проверки подписи, но вам также нужна настоящая подпись. Чтобы проверить подпись RSA, вам понадобятся четыре части данных: модуль, публичная экспонента, хэш (или весь знаковый текст, чтобы вы могли вычислить хеш) и подпись.   -  person Rasmus Faber    schedule 22.06.2012
comment
Спасибо! Да, подпись слишком короткая, теперь я пересчитал подпись с добавленным хешем sha256 над данными. Размер подписи RSA теперь равен размеру ключа RSA.   -  person Diethard    schedule 25.06.2012
comment
Итак, размер подписи в вопросе теперь правильный, но помогло ли это решить ваш вопрос?   -  person Maarten Bodewes    schedule 29.06.2012
comment
Нет, к сожалению, это не решает эту проблему! Нужна ли мне кодировка BER / DER для подписи или импортированного дублирующего ключа? Маби, есть ли еще байтовая кодировка, необходимая для решения этой проблемы?   -  person Diethard    schedule 29.06.2012
comment
Также см. Криптография RSA и Raw RSA на вики-странице Crypto ++.   -  person jww    schedule 16.06.2016


Ответы (1)


Как можно проверить цифровую подпись с помощью библиотеки crypto ++?

Что ж, это легко, когда знаешь, где искать. Из вики-страницы Crypto ++ на странице Схемы подписи RSA:

RSA::PrivateKey privateKey = ...;
RSA::PublicKey publicKey = ...; 

////////////////////////////////////////////////
// Setup
string message = "RSA-PSSR Test", signature, recovered;    

////////////////////////////////////////////////
// Sign and Encode
RSASS<PSSR, SHA1>::Signer signer(privateKey);

StringSource ss1(message, true, 
    new SignerFilter(rng, signer,
        new StringSink(signature),
        true // putMessage for recovery
   ) // SignerFilter
); // StringSource

////////////////////////////////////////////////
// Verify and Recover
RSASS<PSSR, SHA1>::Verifier verifier(publicKey);

StringSource ss2(signature, true,
    new SignatureVerificationFilter(
        verifier,
        new StringSink(recovered),
        THROW_EXCEPTION | PUT_MESSAGE
   ) // SignatureVerificationFilter
); // StringSource

cout << "Verified signature on message" << endl;
cout << "Message: " << recovered << endl;

CryptoPP::RSASS<CryptoPP::PSS,  CryptoPP::SHA256>::Verifier verifier_sha256(pubKeyRaw);

Несколько вопросов:

  • Это должно быть PSS (схема подписи с приложением) или PSSR (схема подписи с восстановлением)?
  • Вы уверены, что это, например, не PKCS1v15?
  • Если это схема восстановления, закодирована ли подпись в начале или в конце шестнадцатеричного кода signatureStr?

Эта первоначальная инициализация Integer, вероятно, была неправильной. Crypto ++ попытается проанализировать строку как десятичное целое число, а не шестнадцатеричное целое число, потому что в нем отсутствуют префикс 0x и суффикс h (должен присутствовать тот или иной).

Вы должны добавить префикс, суффикс или использовать конструктор байтового массива. Конструктор байтового массива показан ниже.

std::string pupKeyStr ("e0c3851114c758fb...");

string pupKeyBin;
StringSource ss1(pupKeyStr, true,
    new HexDecoder(
        new StringSink(pupKeyBin)
    )
);

CryptoPP::Integer pup_key_cast( (unsigned char*)pupKeyBin.data(), pupKeyBin.size() );

StringSource( signatureStr, true, ...
...

Наверное, это неправильно. Вероятно, вам понадобится что-то вроде:

string signatureBin;
StringSource ss1(signatureStr, true,
    new HexDecoder(
        new StringSink(signatureBin)
    )
);

StringSource ss2(signatureBin, true,
    new SignatureVerificationFilter(...
    ...

Я пробовал код с двоичной подписью, используя как PSSA, так и PSSR. Ни то, ни другое не сработало. Я также пробовал использовать SIGNATURE_AT_BEGIN и SIGNATURE_AT_END SignatureVerificationFilter. Ни то, ни другое не сработало. И я пробовал комбинации с SHA1 и RSASSA_PKCS1v15_SHA_Verifier. Ничего не получилось.

Можете ли вы точно проверить, что у вас есть?

person jww    schedule 03.10.2013