Загрузите сертификат X.509 в кодировке PEM в Windows CryptoAPI

StackOverflow https://stackoverflow.com/questions/1231178

Вопрос

Мне нужно загрузить сертификат X.509 в кодировке PEM в контекст Windows Crypto API для использования с C ++. Это те, которые имеют ----- ключ BEGIN RSA XXX ----- и ----- ключ END RSA XXX ----- . Я нашел примеры для Python и .NET, но они используют специальные функции, которые я не могу отнести к простому Windows Crypto API.

Я понимаю, как зашифровать / расшифровать, когда у меня есть HCRYPTKEY. НО, я просто не понимаю, как импортировать BLOB-объект Base64 в файл (ы) .PEM и получить HCRYPTKEY , который я могу использовать из него.

У меня такое странное ощущение, что это нечто большее, чем просто вызов CryptDecodeObject () .

Какие-нибудь указатели, которые могут поставить меня на путь? Я уже потерял два дня на "пробную версию" Ошибка & Quot; программирование и получение в никуда.

Это было полезно?

Решение

KJKHyperion сказал в своем ответ :

  

Я обнаружил "магию" последовательность вызовов для импорта открытого ключа RSA в формате PEM. Вот, пожалуйста:

     <Ол>   
  • декодировать ключ в двоичный двоичный объект с помощью CryptStringToBinary ; передать CRYPT_STRING_BASE64HEADER в dwFlags
  •   
  • декодировать двоичный двоичный ключ в CERT_PUBLIC_KEY_INFO с помощью CryptDecodeObjectEx ; передать X509_ASN_ENCODING в dwCertEncodingType и X509_PUBLIC_KEY_INFO в lpszStructType
  •   
  • декодировать BLOB-объект PublicKey из CERT_PUBLIC_KEY_INFO в ключевой BLOB-объект RSA с помощью CryptDecodeObjectEx ; передайте X509_ASN_ENCODING в dwCertEncodingType и RSA_CSP_PUBLICKEYBLOB в lpszStructType
  •   
  • импортируйте бланк ключа RSA с помощью CryptImportKey
  •   

    Эта последовательность действительно помогла мне понять, что происходит, но у меня не получилось как есть. Второй вызов CryptDecodeObjectEx дал мне ошибку: " встреченное значение неверного тега ASN.1 " ;. После многих попыток понять документацию Microsoft я наконец понял, что вывод первого декодера не может быть снова декодирован как ASN, и что он фактически готов к импорту. С этим пониманием я нашел ответ по следующей ссылке:

    http: //www.ms-news .net / f2748 / проблема импортирующих-открытого ключа-4052577.html

    Ниже приведена моя собственная программа, которая импортирует открытый ключ из файла .pem в контекст CryptApi:

    int main()
    {
        char           pemPubKey[2048];
        int            readLen;
        char           derPubKey[2048];
        size_t         derPubKeyLen = 2048;
        CERT_PUBLIC_KEY_INFO *publicKeyInfo;
        int            publicKeyInfoLen;
        HANDLE         hFile;
        HCRYPTPROV     hProv = 0;
        HCRYPTKEY      hKey = 0;
    
        /*
         * Read the public key cert from the file
         */
        hFile = CreateFileA( "c:\\pub.pem", GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
        if ( hFile == INVALID_HANDLE_VALUE )
        {
            fprintf( stderr, "Failed to open file. error: %d\n", GetLastError() );
        }
    
        if ( !ReadFile( hFile, pemPubKey, 2048, &readLen, NULL ) )
        {
            fprintf( stderr, "Failed to read file. error: %d\n", GetLastError() );
        }
    
        /*
         * Convert from PEM format to DER format - removes header and footer and decodes from base64
         */
        if ( !CryptStringToBinaryA( pemPubKey, 0, CRYPT_STRING_BASE64HEADER, derPubKey, &derPubKeyLen, NULL, NULL ) )
        {
            fprintf( stderr, "CryptStringToBinary failed. Err: %d\n", GetLastError() );
        }
    
        /*
         * Decode from DER format to CERT_PUBLIC_KEY_INFO
         */
        if ( !CryptDecodeObjectEx( X509_ASN_ENCODING, X509_PUBLIC_KEY_INFO, derPubKey, derPubKeyLen, 
                                   CRYPT_ENCODE_ALLOC_FLAG, NULL, &publicKeyInfo, &publicKeyInfoLen ) )
        {
            fprintf( stderr, "CryptDecodeObjectEx 1 failed. Err: %p\n", GetLastError() );
            return -1;
        }
    
        /*
         * Acquire context 
         */
        if( !CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT) )
        {
            {
                printf( "CryptAcquireContext failed - err=0x%x.\n", GetLastError() );
                return -1;
            }
        }
    
        /*
         * Import the public key using the context
         */
        if ( !CryptImportPublicKeyInfo( hProv, X509_ASN_ENCODING, publicKeyInfo, &hKey ) )
        {
            fprintf( stderr, "CryptImportPublicKeyInfo failed. error: %d\n", GetLastError() );
            return -1;
        }
        LocalFree( publicKeyInfo );
    
        /*
         * Now use hKey to encrypt whatever you need.
         */
    
        return 0;
    }
    

    Другие советы

    Я обнаружил "магию" последовательность вызовов для импорта открытого ключа RSA в формате PEM. Вот, пожалуйста:

    <Ол>
  • декодировать ключ в двоичный двоичный объект с помощью CryptStringToBinary ; передать CRYPT_STRING_BASE64HEADER в dwFlags
  • декодировать двоичный двоичный ключ в CERT_PUBLIC_KEY_INFO с помощью CryptDecodeObjectEx ; передать X509_ASN_ENCODING в dwCertEncodingType и X509_PUBLIC_KEY_INFO в lpszStructType
  • декодировать BLOB-объект PublicKey из CERT_PUBLIC_KEY_INFO в ключевой BLOB-объект RSA с помощью CryptDecodeObjectEx ; передайте X509_ASN_ENCODING в dwCertEncodingType и RSA_CSP_PUBLICKEYBLOB в lpszStructType
  • импортируйте бланк ключа RSA с помощью CryptImportKey
  • В настоящее время я сталкиваюсь с той же трудностью. Я еще не закончил кодировать решение, но, насколько я понимаю, вам нужно удалить теги ----- BEGIN и т. Д. ----- и ----- END и т. Д. ------ и декодировать Base64 .

    Это оставляет вам строку в кодировке DER, которую нужно проанализировать, чтобы получить модуль и открытый показатель. Из них вы можете заполнить структуры PUBLICKEYSTRUC и RSAPUBKEY. Удачи; -)

    Лицензировано под: CC-BY-SA с атрибуция
    Не связан с StackOverflow
    scroll top