проверить цифровую подпись с помощью открытого ключа в openssl

Я подписал данные в Windows, используя wincrypt cryptoapi (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING), а в Linux у меня есть сертификат x509 и подписанное сообщение, которое я должен проверить.

Code in windows to sign :
hStoreHandle = CertOpenStore(
    CERT_STORE_PROV_SYSTEM,
    0,
    NULL,
    CERT_SYSTEM_STORE_CURRENT_USER,
    CERT_PERSONAL_STORE_NAME
);
CheckError((BOOL)hStoreHandle, L"CertOpenStore....................... ");

// Get signer's certificate with access to private key.
do {
    // Get a certificate that matches the search criteria
    pSignerCert = CertFindCertificateInStore(
        hStoreHandle,
        MY_TYPE,
        0,
        CERT_FIND_SUBJECT_STR,
        SignerName,
        pSignerCert
    );
    CheckError((BOOL)pSignerCert, L"CertFindCertificateInStore.......... ");

    // Get the CSP, and check if we can sign with the private key           
    bResult = CryptAcquireCertificatePrivateKey(
        pSignerCert,
        0,
        NULL,
        &hCryptProv,
        &dwKeySpec,
        NULL
    );
    CheckError(bResult, L"CryptAcquireCertificatePrivateKey... ");

} while ((dwKeySpec & AT_SIGNATURE) != AT_SIGNATURE);

// Create the hash object.
bResult = CryptCreateHash(
    hCryptProv, 
    CALG_MD5, 
    0, 
    0, 
    &hHash
);
CheckError(bResult, L"CryptCreateHash..................... ");

// Open the file with the content to be signed 
hDataFile = CreateFileW(DataFileName,
    GENERIC_READ,
    FILE_SHARE_READ,
    NULL,
    OPEN_EXISTING,
    FILE_FLAG_SEQUENTIAL_SCAN,
    NULL
);
CheckError((hDataFile != INVALID_HANDLE_VALUE), L"CreateFile.......................... ");

// Compute the cryptographic hash of the data.
while (bResult = ReadFile(hDataFile, rgbFile, BUFSIZE, &cbRead, NULL))
{
    if (cbRead == 0)
    {
        break;
    }
    CheckError(bResult, L"ReadFile............................ ");

    bResult = CryptHashData(
        hHash, 
        rgbFile, 
        cbRead, 
        0
    );
    CheckError(bResult, L"CryptHashData....................... ");

}
CheckError(bResult, L"ReadFile............................ ");

// Sign the hash object
dwSigLen = 0;
bResult = CryptSignHash(
    hHash, 
    AT_SIGNATURE, 
    NULL, 
    0, 
    NULL, 
    &dwSigLen
);
CheckError(bResult, L"CryptSignHash....................... ");

pbSignature = (BYTE *)malloc(dwSigLen);
CheckError((BOOL)pbSignature, L"malloc.............................. ");

bResult = CryptSignHash(
    hHash, 
    AT_SIGNATURE, 
    NULL, 
    0, 
    pbSignature, 
    &dwSigLen
);
CheckError(bResult, L"CryptSignHash....................... ");

// Create a file to save the signature
hSignatureFile = CreateFileW(
    SignatureFileName,
    GENERIC_WRITE,
    0,
    NULL,
    CREATE_ALWAYS,
    FILE_ATTRIBUTE_NORMAL,
    NULL
);
CheckError((hSignatureFile != INVALID_HANDLE_VALUE), L"CreateFile.......................... ");

// Write the signature to the file
bResult = WriteFile(
    hSignatureFile, 
    (LPCVOID)pbSignature, 
    dwSigLen, 
    &lpNumberOfBytesWritten, 
    NULL
);
CheckError(bResult, L"WriteFile........................... ");



In openssl i tried:

 openssl rsautl -verify -inkey pubkey.pem -keyform PEM -pubin -in signedmessage   

it is throwing error::   
RSA operation error  
4296:error:0406706C:rsa routines:RSA_EAY_PUBLIC_DECRYPT:data greater than modlen:fips_rsa_eay.c:709:  
and this error if the signedmessage is hashed
RSA operation error
4432:error:0407006A:rsa routines:RSA_padding_check_PKCS1_type_1:block type is not     01:rsa_pk1.c:100:
4432:error:04067072:rsa routines:RSA_EAY_PUBLIC_DECRYPT:padding check     failed:fips_rsa_eay.c:748:


i also tried :  
   openssl dgst -verify pubkey.pem -signature signedmessage
but program goes into infinite loop

I also find one command:
 int PKCS7_verify(PKCS7 *p7, STACK_OF(X509) *certs, X509_STORE *store, BIO *indata, BIO *out, int flags);
     but it require too many argument of which i am not aware of.e.g there is no x509_store, crlfile used in this  

. кто-нибудь может сказать мне, как проверить подписанное сообщение

Я получаю сертификат x509 pem и подписанное сообщение в качестве входных данных в Linux, которые я должен проверить


person ashmish2    schedule 20.04.2011    source источник
comment
Возможно, это несоответствие формата. Каков результат вашей функции Windows и ключ, который вы используете для проверки? Может быть, включить ссылки, шестнадцатеричные дампы или что-то в этом роде?   -  person Henno Brandsma    schedule 20.04.2011
comment
я приложил код, используемый для подписи   -  person ashmish2    schedule 20.04.2011
comment
Что является примером подписанных данных и открытого ключа pem?   -  person Henno Brandsma    schedule 20.04.2011
comment
Большие целые числа (такие как n и d), вероятно, имеют формат с прямым порядком байтов. Я считаю, что e - это DWORD, и это нормально. Я также считаю, что WinCrypt также использует прямой порядок байтов для подписи из-за CryptDecodeObjectEx и CRYPT_DECODE_NO_SIGNATURE_BYTE_REVERSAL_FLAG. Вы должны изменить порядок байтов на обратный, чтобы OpenSSL мог их использовать.   -  person jww    schedule 18.09.2019


Ответы (1)


После какого-то примера по почте мы добрались до следующего рецепта

настройка: у нас есть сертификат x509 cert.p7b для начала, файл message.txt, подписанный Windows, созданный Windows, и использование sha1 для определенности.

openssl pkcs7 -inform DER -outform PEM -in cert.p7b -out cert.pem -print_certs

openssl x509 -in cert.pem -noout -pubkey > pubkey.pem

(это нужно сделать только один раз для сертификата, чтобы получить открытый ключ в формате PEM), затем поменять местами signed.dat побайтно на signed.dat.rev (используя простую программу на C или выводить байты по-другому в Windows, в альтернативной форме) и, наконец,

openssl dgst -sha1 -verify pubkey.pem -signature signed.dat.rev message.txt

Основная проблема заключалась в обратном порядке байтов в Windows (что я видел раньше)

person Henno Brandsma    schedule 20.04.2011
comment
Я пробовал: openssl rsautl -verify -in signed_HashSign -pubin -inkey pub.pem -pkcs -asn1parse -hexdump и это дает:: ошибка операции RSA 4676: ошибка: 0407006A: подпрограммы rsa: RSA_padding_check_PKCS1_type_1: тип блока не 01: rsa_pk1 .c:100: 4676:ошибка:04067072:подпрограммы rsa:RSA_EAY_PUBLIC_DECRYPT:ошибка проверки заполнения:fips_rsa_eay.c:748: - person ashmish2; 20.04.2011
comment
добавление -rev также может помочь, так как CryptoAPI в некоторых случаях меняет порядок буферов. - person Henno Brandsma; 20.04.2011
comment
openssl pkeyutl -in file -verify -sigfile signed_hash -pubin -inkey key.pem -keyform PEM -rsa_padding_mode:pkcs1 может работать, возможно, с добавлением -rev. Трудно попробовать это без конкретных данных примера! - person Henno Brandsma; 20.04.2011
comment
@henno мой openssl - это OpenSSL 0.9.8e-fips-rhel5 01 июля 2008 г., и нет опций -pkeyutl и -rev :( - person ashmish2; 20.04.2011
comment
У меня 1.0.0, так что это объясняет... Каковы ваши примеры? - person Henno Brandsma; 20.04.2011
comment
Примеры? вы имели в виду вариант, предоставляемый openssl - person ashmish2; 20.04.2011
comment
попробую на 1.0.0. затем сообщит вам, если возникнут какие-либо проблемы .. спасибо - person ashmish2; 20.04.2011
comment
нет примеров вашего файла открытого ключа pem и файла и его подписи. - person Henno Brandsma; 20.04.2011
comment
openssl pkeyutl -verify -in file_to_sign -sigfile sig -pubin -inkey mypubkey.pem -pkeyopt rsa_padding_mode:pkcs1 действительно дает Подпись успешно проверена. Подпись делается с помощью openssl pkeyutl -in file_to_sign -out sig -sign -inkey mykey.pem -rsa_padding_mode:pkcs1, где mypubkey.pem — открытый ключ, а mykey.pem — закрытый ключ. openssl rsautl -sign -in file_to_sign -out sig2 -inkey mykey.pem -pkcs имеет тот же результат (sig2 = sig). - person Henno Brandsma; 20.04.2011
comment
-pkeyutl - это не опция, а команда (например, enc), поэтому, как я набрал openssl pkeyutl, а затем следуют опции. Просто замечание. - person Henno Brandsma; 20.04.2011
comment
@Henno, спасибо за эту информацию .. проблема в том, что я подписал сообщение в Windows, используя cryptoapi (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING), упомянутое выше, и проверяя его в Linux с помощью команды ur, это дает ошибку проверки .. Я думаю, что есть проблема с заполнением sm в win crypto api и linux openssl.. - person ashmish2; 20.04.2011
comment
Да, как я и предлагал в первом ответе. Кроме того, -verify проверяет содержимое файла напрямую, поэтому нам нужно сначала поместить дайджест в файл, а затем проверить его. Но опять же, включите пример! Таким образом, мы можем видеть форматы и т.д. - person Henno Brandsma; 20.04.2011
comment
какой пример? я не могу получить это .. вы хотите подписанное сообщение? шестнадцатеричный дамп? - person ashmish2; 20.04.2011
comment
подписанное сообщение (в шестнадцатеричном формате) и pubkey.pem, а также файл, который вы подписываете. Затем я могу попытаться проверить это, используя материалы openssl. - person Henno Brandsma; 20.04.2011
comment
хорошо, но как это загрузить? Вы можете сказать мне, что ваш адрес электронной почты? Спасибо - person ashmish2; 20.04.2011
comment
Папка дропбокса? или попробуйте мое имя, фамилию (все одно слово, в нижнем регистре) на gmail и т. д. - person Henno Brandsma; 20.04.2011
comment
Проблема может быть в ASN1, это не совсем PEM. Но подожду примера. - person Henno Brandsma; 20.04.2011