Ваши загруженные файлы примеров имеют несколько свойств, которые не позволяют его проверить.
Во-первых, срок действия сертификата подписавшего в файле 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.