Дело о таинственных сбоях при подписывании кода

Во время подготовки исполняемых файлов Sysinternals для публикации на веб-узле я регулярно подписываю код. Когда файл снабжается цифровой подписью, его хэш-код зашифровывается закрытым ключом из пары открытого/закрытого ключей. Чтобы проверить подпись, стороннее лицо может расшифровать хэш-код с применением открытого ключа и сравнить результат с хэш-кодом файла, вычисленным самостоятельно. Процесс подписывания предельно упрощается благодаря Signtool.exe - служебной программе, входящей в состав пакета Platform SDK и платформы .NET Framework. На входе ей нужно передать в качестве аргументов командной строки сертификат подписи, файл с закрытым ключом и конечный файл, а все остальное она делает автоматически, под конец присоединяя к файлу подписанный хэш-код.

На днях, пытаясь подписать обновленную версию одной из программ Sysinternals, я столкнулся с сообщением об ошибке следующего содержания:

signtool1

 

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

В первую очередь, я выполнил поиск библиотеки capicom.dll с помощью встроенной служебной программы Where. Она ищет указанный файл во всех каталогах, перечисленных в переменной среды PATH. Эта переменная предназначена именно для поиска библиотек DLL, и посредством этого действия я рассчитывал убедиться в отсутствии файла Capicom.dll.

signtool2

Выходные данные программы, казалось бы, подтвердили мое предположение, но тут я понял, что работаю с 64-разрядной версией ОС, а Signtool - 32-разрядный исполняемый файл. Следовательно, программа Where.exe не проводит поиск в каталоге %SystemRoot%\Syswow64, где и должны храниться 32-разрядные библиотеки DLL. Заглянув в этот каталог самостоятельно, я с удивлением обнаружил копию Capicom.dll:

signtool3

Таким образом, очевидно, программа Signtool не ищет библиотеку Capicom.dll в каталогах, перечисленных в переменной среды PATH. Возник закономерный вопрос: а где же она ищет? Идеальный способ ответить на такой вопрос - запустить программу Process Monitor, что я и сделал. Настроив фильтр включения на все пути, которые оканчиваются строкой “capicom.dll”, я вновь выполнил команду Nmake, которая ранее спровоцировала ошибку.

signtool4

Судя по трассировке, программа Signtool почему-то ищет библиотеку Capicom.dll лишь в двух каталогах:  Microsoft Shared (это подкаталог системного каталога Common Files) и \Bin (именно в нем находится моя копия программы Signtool).

Для решения проблемы достаточно было скопировать файл Capicom.dll из каталога \Windows\Syswow64 в каталог \Bin. Я выполнил команду еще раз, и, как и ожидалось, проблема исчезла. Process Monitor вам в помощь!