Ключевое слово в защите информации
КЛЮЧЕВОЕ СЛОВО
в защите информации
Наши способы организации безопасного удалённого доступа к рабочим местам и корпоративным ресурсам
Добро пожаловать, Гость! Чтобы использовать все возможности Вход или Регистрация.

Уведомление

Icon
Error

Опции
К последнему сообщению К первому непрочитанному
Offline lex_shadow  
#1 Оставлено : 23 октября 2020 г. 15:43:29(UTC)
lex_shadow

Статус: Новичок

Группы: Участники
Зарегистрирован: 23.10.2020(UTC)
Сообщений: 1
Российская Федерация
Откуда: Ессентуки

Добрый день. Подскажите как с помощью CryptoAPI получить подпись эквивалентную:
csptest -sfsign -sign -in файл –out подпись -my сертификат -detached –add

При использовании CryptSignMessage на выходе получаю файл одинакового размера с вышеприведенной командой, но с совершенно иным содержимым
Offline Андрей Русев  
#2 Оставлено : 27 октября 2020 г. 17:13:51(UTC)
Андрей Русев

Статус: Сотрудник

Группы: Администраторы, Участники
Зарегистрирован: 16.04.2008(UTC)
Сообщений: 687

Сказал(а) «Спасибо»: 1 раз
Поблагодарили: 152 раз в 120 постах
День добрый.
Это её реализация. Половины функций не хватает, но должно быть понятно.
Код:
static int do_sign(TCHAR *infile, TCHAR *certfile, TCHAR *outfile, int detached,
                   LPCSTR hash_oid, int include, int req_compliant, BOOL base64, 
                   int Cert_LM, DWORD dwCadesFlags, BOOL bAddSigTime, PCSTR szPIN, DWORD dwFlags)
{
    PCCERT_CONTEXT	pUserCert = NULL;
    PCCERT_CONTEXT	pMemoryCert = NULL;
    int			ret = ERROR_INTERNAL_ERROR;
    BOOL		bResult;
    DWORD		dwErrFn;
    BYTE		*mem_tbs = NULL;
    DWORD		mem_len = 0;

    CRYPT_SIGN_MESSAGE_PARA param;
    DWORD		MessageSizeArray[1];
    const BYTE		*MessageArray[1];
    DWORD		signed_len = 0;
    BYTE		*signed_mem = NULL;
    char		errtxt[100];
    HCRYPTPROV		hCryptProv = 0;
    DWORD		keytype = 0;
    BOOL		should_release_ctx = FALSE;

    CRYPT_ATTR_BLOB	cablob[1];
    CRYPT_ATTRIBUTE	ca[1];
    LPBYTE		pbAuth = NULL;
    DWORD		cbAuth = 0;
    FILETIME		fileTime;
    SYSTEMTIME		systemTime;

    if (!certfile) {
        DebugErrorFL("No user certificate specified.");
        goto err;
    }
    if (!infile) {
        DebugErrorFL("No input file was specified.");
        goto err;
    }
    pUserCert = read_cert_from_my(certfile, Cert_LM);
    if (!pUserCert) {
        sprintf(errtxt, "Cannot find User certificate: " _T2A, certfile);
        DebugErrorFL(errtxt);
        goto err;
    }

    if (req_compliant) {
        if (verify_certificate_chain(pUserCert)) {
            DebugErrorFL("Certificate chain verify failed.");
            goto err;
        }
        else {
            _tprintf(_TEXT("Certificate chain validation succeed.\n\n"));
        }
    }

    dwErrFn = SetCertPin(pUserCert, szPIN, &pMemoryCert);
    if (dwErrFn) {
        ret = dwErrFn;
        goto err;
    }

    if (pUserCert) {
        CertFreeCertificateContext(pUserCert);
    }
    pUserCert = pMemoryCert;

    dwFlags |= CRYPT_ACQUIRE_COMPARE_KEY_FLAG;
    bResult = CryptAcquireCertificatePrivateKey(
                  pUserCert,
                  dwFlags,
                  NULL,
                  &hCryptProv,
                  &keytype,
                  &should_release_ctx);

    if (!bResult) {
        ret = DebugErrorFL("Cryptographic context could not be acquired.");
        goto err;
    }

    if (!get_file_data_pointer(infile, &mem_len, &mem_tbs)) {
        DebugErrorFL("Cannot open input file.");
        goto err;
    }

    if (!hash_oid)
        hash_oid = GetDefaultHashOID(pUserCert->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId);

    // Обязательно нужно обнулить все поля структуры,
    // иначе это может привести к access violation в функциях CryptoAPI.
    // В примере из MSDN это отсутствует.
    ZeroMemory(&param, sizeof(CRYPT_SIGN_MESSAGE_PARA));
    param.cbSize = sizeof(CRYPT_SIGN_MESSAGE_PARA);
    param.dwMsgEncodingType = TYPE_DER;
    param.pSigningCert = pUserCert;

    param.HashAlgorithm.pszObjId = (LPSTR)hash_oid;
    param.HashAlgorithm.Parameters.cbData = 0;
    param.HashAlgorithm.Parameters.pbData = NULL;
    param.pvHashAuxInfo = NULL;
    param.cMsgCert = include;		/* включаем сертификат отправителя если попросили*/
    param.rgpMsgCert = &pUserCert;
    param.cAuthAttr = 0;
    param.dwInnerContentType = 0;
    param.cMsgCrl = 0;
    param.cUnauthAttr = 0;

    GetSystemTime(&systemTime);
    SystemTimeToFileTime(&systemTime, &fileTime);

    bResult = CryptEncodeObject(TYPE_DER,
                                szOID_RSA_signingTime,
                                (LPVOID)&fileTime,
                                NULL,
                                &cbAuth);
    if (!bResult) {
        ret = DebugErrorFL("Cannot encode object");
        goto err;
    }

    pbAuth = (BYTE*)malloc(cbAuth);
    if (!pbAuth) {
        ret = DebugCodeFL(ERROR_NOT_ENOUGH_MEMORY, "Out of memory");
        goto err;
    }

    bResult = CryptEncodeObject(TYPE_DER,
                                szOID_RSA_signingTime,
                                (LPVOID)&fileTime,
                                pbAuth,
                                &cbAuth);
    if (!bResult) {
        ret = DebugErrorFL("Cannot encode object");
        goto err;
    }

    cablob[0].cbData = cbAuth;
    cablob[0].pbData = pbAuth;

    ca[0].pszObjId = szOID_RSA_signingTime;
    ca[0].cValue = 1;
    ca[0].rgValue = cablob;

    if (bAddSigTime) {
        param.cAuthAttr = 1;
        param.rgAuthAttr = ca;
    }

    param.dwFlags = dwCadesFlags;

    MessageArray[0] = mem_tbs;
    MessageSizeArray[0] = mem_len;

    printf ("Source message length: %lu\n", (unsigned long)mem_len);

    bResult = CryptSignMessage(
                  &param,
                  detached,
                  1,
                  MessageArray,
                  MessageSizeArray,
                  NULL,
                  &signed_len);

    if (bResult) {
        printf("Calculated signature (or signed message) length: %lu\n", (unsigned long)signed_len);
        signed_mem = (BYTE*) malloc(signed_len);
        if (!signed_mem) {
            ret = DebugCodeFL(ERROR_NOT_ENOUGH_MEMORY, "Out of memory");
            goto err;
        }
    }
    else {
        ret = DebugErrorFL("Signature creation error");
        goto err;
    }
    bResult = CryptSignMessage(
                  &param,
                  detached,
                  1,
                  MessageArray,
                  MessageSizeArray,
                  signed_mem,
                  &signed_len);
    if (bResult) {
        printf("Signature was done. Signature (or signed message) length: %lu\n", (unsigned long)signed_len);
    }
    else {
        ret = DebugErrorFL("Signature creation error");
        goto err;
    }

    if (outfile) {
        ret = write_binary_file(outfile, signed_len, signed_mem, base64);
        goto err;
    }

    if (req_compliant) {
        _tprintf(_TEXT("\nSignature of file (%s) was created using key tied with certificate:\n\n"), infile);
        PrintCertInfo(pUserCert);
        if (outfile) {
            _tprintf(_TEXT("\nSignature was saved in file (%s).\n\n"), outfile ? outfile : _TEXT("NULL"));
        }
    }

    ret = ERROR_SUCCESS;
err:
    if (pUserCert) {
        CertFreeCertificateContext(pUserCert);
    }
    if (should_release_ctx)
        CryptReleaseContext(hCryptProv, 0);
    free(signed_mem);
    free(pbAuth);
    release_file_data_pointer(mem_tbs);
    return ret;
}
Официальная техподдержка. Официальная база знаний.
thanks 1 пользователь поблагодарил Андрей Русев за этот пост.
two_oceans оставлено 28.10.2020(UTC)
RSS Лента  Atom Лента
Пользователи, просматривающие эту тему
Быстрый переход  
Вы не можете создавать новые темы в этом форуме.
Вы не можете отвечать в этом форуме.
Вы не можете удалять Ваши сообщения в этом форуме.
Вы не можете редактировать Ваши сообщения в этом форуме.
Вы не можете создавать опросы в этом форуме.
Вы не можете голосовать в этом форуме.