Понять, почему блок pkcs7 не прошел во время проверки с использованием openssl - PullRequest
0 голосов
/ 11 ноября 2018

У меня есть файл в формате PKCS # 7 Der с именем p7 и файл сертификата x509 с именем mroot.der.cer, который соответствует корневому сертификату цепочки p7.

Я бы хотел проверить цепочку сертификатов p7, используя openssl, используя следующие команды:

First - convert my mroot trusted cert file to pem format. 
openssl x509 -in mroot.der.cer -inform der -outform PEM -out mroot.pem.cer

Second - verify the root chain using mroot.pem.cer
openssl  smime -verify -CAfile mroot.pem.cer -in p7 -inform DER -out blabla

Однако я получил следующую ошибку:

Ошибка проверки 140735569544136: ошибка: 21075075: процедуры PKCS7: PKCS7_verify: ошибка проверки сертификата: /BuildRoot/Library/Caches/com.apple.xbs/Sources/libressl/libressl-22.50.2/libressl/crypto/pkcs7/pk7_sm.me: Ошибка проверки: невозможно получить сертификат локального эмитента

Я также пытался добавить последнюю команду, флаг -noverify, но получил другую ошибку.

Ошибка проверки 140735569544136: ошибка: 21071065: подпрограммы PKCS7: PKCS7_signatureVerify: сбой дайджеста: /BuildRoot/Library/Caches/com.apple.xbs/Sources/libressl/libressl-22.50.2/libressl/crypto/pkcs7/pc7: 140735569544136: ошибка: 21075069: подпрограммы PKCS7: PKCS7_verify: сбой подписи: /BuildRoot/Library/Caches/com.apple.xbs/Sources/libressl/libressl-22.50.2/libressl/crypto/pkcs7/pk7_smimec: 1018 *

Структура pkcs7 должна быть в порядке, поскольку я извлек ее из PE-файла iexlorer.exe и из его цепочки извлек корневой сертификат и назвал его доверенным.

Что я здесь не так делаю?

P.s. Чтобы наблюдать те же ошибки, что и я, я загрузил файлы по следующим ссылкам:

https://ufile.io/vrqpt

https://ufile.io/ajgex

1 Ответ

0 голосов
/ 11 ноября 2018

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

Во-первых, срок действия сертификата подписавшего в файле p7 истек Apr 24 22:33:39 2014 GMT. Вам нужно будет отключить проверку срока годности, если вы хотите проверить цепочку. Это программно выполняется с помощью флага проверки X509_V_FLAG_NO_CHECK_TIME или параметра -no_check_time для инструмента OpenSSL smime -verify.

Тогда ваш "корень доверия", найденный в файле mroot.pem.cer, не тот. Вы извлекли сертификат Microsoft Time-Stamp PCA, тогда как лицо, подписавшее файл p7, цепочки до сертификата Microsoft Code Signing PCA.

Допустим, вы извлекаете этот правильный сертификат в файл с именем trust.pem.cer. Этот сертификат не является самоподписанным: его эмитент - Microsoft Root Certificate Authority. Вам нужно будет указать, что вы используете так называемую частичную цепочку, если вы хотите, чтобы такой сертификат находился в конце цепочки. Это программно выполняется с помощью флага проверки X509_V_FLAG_PARTIAL_CHAIN или опции -partial_chain для инструмента OpenSSL smime -verify.

Кроме того, похоже, что реализация OpenSSL проверки PKCS7 требует, чтобы ваш сертификат включал расширенное использование ключа подписи S ​​/ MIME, которое ваш сертификат не включает. Похоже, что это можно обойти, установив цель подписи кода для OpenSSL X509_STORE. Средство OpenSSL smime -verify не предоставляет такой настройки, поэтому вам придется сделать это программно, установив цель XKU_CODE_SIGN. XKU расшифровывается как eXtended Key Usage и, как предостережение, документация OpenSSL, которая практически отсутствует. Вы должны тщательно проверить это, если решите использовать его.

Часть кода ниже (проверка кода возврата опущена) успешно проверяет цепочку сертификатов в файле p7, но не подпись:

BIO *bio_p7 = BIO_new_file("p7", "r");
PKCS7 *p7 = d2i_PKCS7_bio(bio_p7, NULL);
X509_STORE *store = X509_STORE_new();
X509_LOOKUP *lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file());
X509_LOOKUP_load_file(lookup, "trust.pem.cer", X509_FILETYPE_PEM);
X509_STORE_set_purpose(store, XKU_CODE_SIGN); /* see caveat above */
X509_VERIFY_PARAM_set_flags(
    X509_STORE_get0_param(store),
    X509_V_FLAG_NO_CHECK_TIME | X509_V_FLAG_PARTIAL_CHAIN);
int retcode = PKCS7_verify(p7, NULL, store, NULL, NULL, PKCS7_NOSIGS);

Для проверки самой подписи: функция verify_pe_pkcs7 () в osslsigncode.c дает пример кода для этого. Его вызов PKCS7_verify() не проверяет цепочку сертификатов, но проверяет подпись. Это требует извлечения хэша, который хранится в специфическом для Microsoft элементе в p7 типа с именем SpcIndirectDataContent, как указано в @ dave_thompson_085 ниже. Можно проверить подпись, которая была взята за этот хэш. Для полной проверки вам также необходимо пересчитать хеш-код самого файла PE и сравнить его со значением хеш-функции, найденным в p7.

Этот ответ основан на OpenSSL 1.1.1. Только сейчас я понимаю, что вы используете libressl, который основан на (намного) более старой версии OpenSSL. Это может не сработать в вашем случае. Например, для моей версии libressl инструмент smime -verify не поддерживает параметры partial_chain и no_time_check, поскольку они были введены в ветке OpenSSL 1.1.0.

...