Подписание кода больше не работает

У нас есть устаревший рабочий процесс Windows, который использует SignerSign для применения цифровой подписи к EXE. Мы отходим от рабочего процесса Windows, поэтому я подготовил инструмент в контексте нашего нового процесса для выполнения той же операции подписи. Я скопировал/вставил код подписи кода из действия рабочего процесса в класс нового проекта, но при попытке запустить его возникает ошибка.

Грубый план того, что делает код:

  • CertOpenStore используется для открытия файла PFX, содержащего закрытый ключ и сертификат.
  • Контекст сертификата получается путем вызова CertEnumCertificatesInStore для результирующего дескриптора хранилища сертификатов.
  • SignerSign вызывается с SIGNER_SUBJECT_INFO, указывающим на целевой EXE-файл, SIGNER_CERT, указывающим на контекст сертификата из предыдущего шага, и SIGNATURE_SIGNER_INFO, указывающим, что следует использовать алгоритм SHA-1. (Я попытался изменить алгоритм на SHA-2 512 без каких-либо изменений в результате.) Параметр pProviderInfo равен NULL.
  • Выполняется отдельный вызов SignerTimeStamp для применения метки времени к подписи. Комментарий в коде указывает, что если используется параметр pwszHttpTimeStamp для SignerSign, он возвращает HRESULT 0x80070020 ("Файл используется"?)

Когда я пытаюсь запустить этот код в 64-разрядной версии Windows 10 из 32-разрядного или 64-разрядного процесса, я получаю сообщение об ошибке HRESULT 0x80092006 «Для хранилища или объекта не указан поставщик». Я попытался предоставить pProviderInfo с именем провайдера, установленным на «Microsoft Strong Cryptographic Provider» (видно в выводе трассировки API Monitor, когда SignTool.exe подписывает исполняемый файл — это работает), но это не повлияло на результат.

Кто-нибудь знает, что именно означает эта ошибка и как ее исправить?


person Jonathan Gilbert    schedule 20.02.2018    source источник


Ответы (1)


Я понятия не имею, почему это сработало, но, массируя мой код, чтобы он делал то же самое, я вижу, что SignTool делает в мониторе API Rohitab, а затем убирает биты до того, что кажется минимальным рабочим набором, теперь это снова подписывает файлы :

  • Вместо CertOpenStore,. PFXImportCertStore используется для открытия файла PFX и создания файла HCERTSTORE. Это требует загрузки PFX в память, чтобы его можно было передать как CRYPT_DATA_BLOB — ничего страшного.
  • Контекст сертификата получается с использованием CertEnumCertificatesInStore, как и раньше.
  • CertGetCertificateChain используется в результирующем контексте сертификата с неограниченным CERT_CHAIN_PARA и флагами CERT_CHAIN_DISABLE_PASS1_QUALITY_FILTERING | CERT_CHAIN_RETURN_LOWER_QUALITY_CONTEXTS | CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT. Дополнительный магазин не указан. Когда я первоначально написал это, основываясь на результатах монитора API, я определил CERT_CHAIN_PARA_HAS_EXTRA_FIELDS и заполнил их так же, как показано в захвате монитора API, но я продолжаю получать S_OK из SignerSign с короткой структурой CERT_CHAIN_PARA.
  • SignerSign вызывается, как и раньше, за исключением того, что фиктивное хранилище типа коллекции передается как hCertStore структуры SIGNER_CERT_STORE_INFO, вложенной в SIGNER_CERT. Это фиктивное хранилище типа коллекции создается путем двойного вызова CertOpenStore, один раз с CERT_STORE_PROV_COLLECTION и флагом CERT_STORE_CREATE_NEW_FLAG и один раз с CERT_STORE_PROV_MEMORY, указывающим кодировку PKCS_7_ASN_ENCODING | X509_ASN_ENCODING, а затем добавлением хранилища памяти в хранилище коллекции с использованием CertAddStoreToCollection.

Если фиктивное хранилище типа коллекции не указано, то SignerSign жалуется, что не может найти путь к доверенному корню. Обратите внимание, что сертификат, который я использую в своем тестировании, является самозаверяющим и поэтому не имеет путь к доверенному корню. Возможно, хранилище фиктивного типа коллекции не было бы необходимо с сертификатом подписи кода, у которого есть путь к доверенному корню, у меня сейчас нет средств для проверки.

В любом случае, я надеюсь, что это поможет решить эту проблему всем, кто мог столкнуться с проблемами с SignerSign. :-)

person Jonathan Gilbert    schedule 20.02.2018