none
Почему SignerSign не подписывает файлы, если algidHash в SIGNER_SIGNATURE_INFO установить в отличное от CALC_SHA1 значение? RRS feed

  • Общие обсуждения

  • Ну, весь вопрос озвучен в теме. Я никак с этим не разберусь, может значение algidHash зависит как-то от сертификата? Ну у меня есть сертификат в котором алгоритм хеширования SHA256, в качестве параметра в структуре SIGNER_SIGNATURE_INFO я устанавливаю CALG_SHA_256, ну и получаю ошибку: 0x8009000a, вот мой код, для подписания файлов:

    //cтруктуры, необходимые для цифровой подписи файлов
    typedef struct _SIGNER_FILE_INFO {
        DWORD cbSize;
        LPCWSTR pwszFileName;
        HANDLE hFile;
    } SIGNER_FILE_INFO, *PSIGNER_FILE_INFO;
     
    typedef struct _SIGNER_BLOB_INFO {
        DWORD cbSize;
        GUID *pGuidSubject;
        DWORD cbBlob;
        BYTE *pbBlob;
        LPCWSTR pwszDisplayName;
    } SIGNER_BLOB_INFO, *PSIGNER_BLOB_INFO;
     
    typedef struct _SIGNER_SUBJECT_INFO {
        DWORD cbSize;
        DWORD *pdwIndex;
        DWORD dwSubjectChoice;
        union {
            SIGNER_FILE_INFO *pSignerFileInfo;
            SIGNER_BLOB_INFO *pSignerBlobInfo;
        };
    } SIGNER_SUBJECT_INFO, *PSIGNER_SUBJECT_INFO;
     
    typedef struct _SIGNER_CERT_STORE_INFO {
        DWORD cbSize;
        PCCERT_CONTEXT pSigningCert;
        DWORD dwCertPolicy;
        HCERTSTORE hCertStore;
    } SIGNER_CERT_STORE_INFO, *PSIGNER_CERT_STORE_INFO;
     
    typedef struct _SIGNER_SPC_CHAIN_INFO {
        DWORD cbSize;
        LPCWSTR pwszSpcFile;
        DWORD dwCertPolicy;
        HCERTSTORE hCertStore;
    } SIGNER_SPC_CHAIN_INFO, *PSIGNER_SPC_CHAIN_INFO;
     
    typedef struct _SIGNER_CERT {
        DWORD cbSize;
        DWORD dwCertChoice;
        union {
            LPCWSTR pwszSpcFile;
            SIGNER_CERT_STORE_INFO *pCertStoreInfo;
            SIGNER_SPC_CHAIN_INFO *pSpcChainInfo;
        };
        HWND hwnd;
    } SIGNER_CERT, *PSIGNER_CERT;
     
    typedef struct _SIGNER_ATTR_AUTHCODE {
        DWORD cbSize;
        BOOL fCommercial;
        BOOL fIndividual;
        LPCWSTR pwszName;
        LPCWSTR pwszInfo;
    } SIGNER_ATTR_AUTHCODE, *PSIGNER_ATTR_AUTHCODE;
     
    typedef struct _SIGNER_SIGNATURE_INFO {
        DWORD cbSize;
        ALG_ID algidHash;
        DWORD dwAttrChoice;
        union {
            SIGNER_ATTR_AUTHCODE *pAttrAuthcode;
        };
        PCRYPT_ATTRIBUTES psAuthenticated;
        PCRYPT_ATTRIBUTES psUnauthenticated;
    } SIGNER_SIGNATURE_INFO, *PSIGNER_SIGNATURE_INFO;
     
    typedef struct _SIGNER_PROVIDER_INFO {
        DWORD cbSize;
        LPCWSTR pwszProviderName;
        DWORD dwProviderType;
        DWORD dwKeySpec;
        DWORD dwPvkChoice;
        union {
            LPWSTR pwszPvkFileName;
            LPWSTR pwszKeyContainer;
        };
    } SIGNER_PROVIDER_INFO, *PSIGNER_PROVIDER_INFO;
    typedef struct _SIGNER_CONTEXT {
        DWORD cbSize;
        DWORD cbBlob;
        BYTE *pbBlob;
    } SIGNER_CONTEXT, *PSIGNER_CONTEXT;
    //необходимые функции для цифровой подписи файлов
    typedef HRESULT(WINAPI *SignerSignType)(
        _In_     SIGNER_SUBJECT_INFO   *pSubjectInfo,
        _In_     SIGNER_CERT           *pSignerCert,
        _In_     SIGNER_SIGNATURE_INFO *pSignatureInfo,
        _In_opt_ SIGNER_PROVIDER_INFO  *pProviderInfo,
        _In_opt_ LPCWSTR               pwszHttpTimeStamp,
        _In_opt_ PCRYPT_ATTRIBUTES     psRequest,
        _In_opt_ LPVOID                pSipData);
    
    //структуры и типы определённые мною
    typedef std::wstring WSTRING;
    struct WWS_ERROR_REPORT_STRUCTW {
            WSTRING ErrorString;//строка с ошибкой
            WSTRING ErrorCaption;//заголовок ошибки
            DWORD ErrorCode;// код ошибки
    };
    struct SIGN_FILE_RESULT {//данную структуру возвращает функция SignFile
        struct SIGNING_FILE {//данная структура передаётся функции  SignFile в качестве параметра
            PCCERT_CONTEXT SignCertificate = nullptr;
            LPCWSTR SigningFileName = nullptr;//имя подписываемого файла
            ALG_ID HashAlgorithmId = PP.HashAlgorithmId;// алгоритм хеширования для цифровой подписи
            DWORD dwAttrChoice = 0;//требуется ли использовать pAttrAuthcode
            SIGNER_ATTR_AUTHCODE *pAttrAuthcode = nullptr;//дополнительные параметры для подписи
        };
        typedef const SIGNING_FILE *PCSIGNING_FILE;
        bool FileIsSigned = false;//файл был подписан
        bool InitializationFailed = false;//была ли ошибка инициализации функции SignFile
        WWS_ERROR_REPORT_STRUCTW ErrorInfo;//данный член будет заполнен в том случае, если не удастся инициализировать функцию SIGN_FILES_RESULT
    };
    //функция формирует сообщение об ошибке
    WWS_ERROR_REPORT_STRUCTW ErrorString(LPCWSTR ErrorText) {
            WWS_ERROR_REPORT_STRUCTW result;
        result.ErrorCode = GetLastError();
        LPWSTR BufferForFormatMessage = nullptr;
        DWORD FMResult = FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, result.ErrorCode, LANG_USER_DEFAULT, (LPWSTR)&BufferForFormatMessage, NULL, nullptr);
        if (FMResult == 0) {
            result.ErrorString = ErrorText;
            result.ErrorString += (L"\nКод Ошибки: " + std::to_wstring(result.ErrorCode));
            result.ErrorString += L"\nПричина ошибки: Не удалось узнать причину возникновения ошибки!";
        }
        else {
            result.ErrorString = ErrorText;
            result.ErrorString += (L"\nКод Ошибки: " + std::to_wstring(result.ErrorCode));
            result.ErrorString += L"\nПричина ошибки: ";
            result.ErrorString += BufferForFormatMessage;
        }
        if (HeapFree(GetProcessHeap(), NULL, BufferForFormatMessage) == NULL) {
            result.ErrorString += L"Не удалось освободить буфуер при обработке предыдущей ошибки!\n";
            result.ErrorString += (L"Код ошибки: " + std::to_wstring(GetLastError()));
        }
        return result;
    }
    //Вот функция, выполняющая подпись файлов
    SIGN_FILE_RESULT SignFile(SIGN_FILE_RESULT::PCSIGNING_FILE SF, SignerSignType pfSignerSign) {
        SIGN_FILE_RESULT result;
        SIGNER_FILE_INFO signerFileInfo;
        SIGNER_SUBJECT_INFO signerSubjectInfo;
        SIGNER_CERT_STORE_INFO signerCertStoreInfo;
        SIGNER_CERT signerCert;
        SIGNER_SIGNATURE_INFO signerSignatureInfo;
        if (pfSignerSign) {
            DWORD dwIndex = 0;
            signerFileInfo.cbSize = sizeof(SIGNER_FILE_INFO);
            signerFileInfo.pwszFileName = SF->SigningFileName;
            signerFileInfo.hFile = NULL;
            // Prepare SIGNER_SUBJECT_INFO struct
            signerSubjectInfo.cbSize = sizeof(SIGNER_SUBJECT_INFO);
            signerSubjectInfo.pdwIndex = &dwIndex;
            signerSubjectInfo.dwSubjectChoice = 1; // SIGNER_SUBJECT_FILE
            signerSubjectInfo.pSignerFileInfo = &signerFileInfo;
            // Prepare SIGNER_CERT_STORE_INFO struct
            signerCertStoreInfo.cbSize = sizeof(SIGNER_CERT_STORE_INFO);
            signerCertStoreInfo.pSigningCert = SF->SignCertificate;
            signerCertStoreInfo.dwCertPolicy = 2; // SIGNER_CERT_POLICY_CHAIN
            signerCertStoreInfo.hCertStore = NULL;
            // Prepare SIGNER_CERT struct
            signerCert.cbSize = sizeof(SIGNER_CERT);
            signerCert.dwCertChoice = 2; // SIGNER_CERT_STORE
            signerCert.pCertStoreInfo = &signerCertStoreInfo;
            signerCert.hwnd = NULL;
            // Prepare SIGNER_SIGNATURE_INFO struct
            signerSignatureInfo.cbSize = sizeof(SIGNER_SIGNATURE_INFO);
            signerSignatureInfo.algidHash = SF->HashAlgorithmId;//сюда приходит CALG_SHA_245
            signerSignatureInfo.psAuthenticated = NULL;
            signerSignatureInfo.psUnauthenticated = NULL;
            signerSignatureInfo.dwAttrChoice = NULL; // SIGNER_NO_ATTR
            signerSignatureInfo.pAttrAuthcode = NULL;
            HRESULT hSignerSignResult = pfSignerSign(&signerSubjectInfo, &signerCert, &signerSignatureInfo, NULL, NULL, NULL, NULL);
            if (SUCCEEDED(hSignerSignResult)) {
                //SI->pfSignerFreeSignerContext(pSignerContext);
                result.FileIsSigned = true;
            }
            else {
                //в случае если неудалось подписать файл
                WSTRING ErrorText = L"Не удалось подписать файл \"";
                ErrorText += SF->SigningFileName;
                ErrorText += L"\" цифровой подписью!";
                result.ErrorInfo.ErrorString = ErrorString(ErrorText.c_str(), hSignerSignResult);
                result.ErrorInfo.ErrorCaption = L"Ошибка подписи файла";
                result.ErrorInfo.ErrorCode = hSignerSignResult;
            }
        }
        else {
            result.ErrorInfo = ErrorString(L"Неверный адресс функции SignerSignEx, он не может равняться nullptr!");
            result.ErrorInfo.ErrorCaption = L"Неверный адресс функции!";
            result.InitializationFailed = true;
        }
        return result;
    }

    Важное замечание, тут опущен процесс загрузки DLL в которой содержится функция SignerSign и опущен процесс получения адресса этой функции, с этим всё окей, успех или не успех подписи файла зависит только от значения  algidHash в структуре SIGNER_SIGNATURE_INFO, если там стоит CALG_SHA1 то всё окей, если же я ставлю значение в CALG_SHA_256 то подпись файлов завершается неудачно, причём не зависимо от того, используется ли SHA1 в качестве хеша или SHA256 я приложу скриншоты свойств обоих. К сожалению, я не смог приложить скриншоты свойств сертификатов, возможно сделаю это позже...


    28 декабря 2019 г. 7:54