Pergunta

Eu preciso carregar um PEM codificado X.509 certificado em um contexto Windows API Crypto para usar com C ++. Eles são os únicos que têm -----BEGIN RSA XXX KEY----- e -----END RSA XXX KEY----- . Eu encontrei exemplos para Python e .NET, mas eles usam funções específicas que não podem se relacionar com a planície API do Windows Crypto.

Eu entendo como para criptografar / descriptografar uma vez que eu tenho uma HCRYPTKEY. MAS, eu simplesmente não entendo como importar o blob Base64 no arquivo .PEM (s) e obter um HCRYPTKEY que eu posso usar fora dele.

Eu tenho essa estranha sensação de que há mais do que simplesmente chamando CryptDecodeObject().

Os ponteiros que podem me colocar no caminho certo? Eu já perdi dois dias fazendo "tentativa e erro" de programação e chegando a lugar nenhum.

Foi útil?

Solução

KJKHyperion disse em sua resposta :

Eu descobri a seqüência de "mágica" de chamadas para importar uma chave pública RSA no formato PEM. Aqui vai:

  1. decodificar a chave em um blob binário com CryptStringToBinary ; passar CRYPT_STRING_BASE64HEADER na dwFlags
  2. decodificar o blob de chave binário em um CERT_PUBLIC_KEY_INFO com CryptDecodeObjectEx ; passar X509_ASN_ENCODING em dwCertEncodingType e X509_PUBLIC_KEY_INFO em lpszStructType
  3. decodificar o blob PublicKey do CERT_PUBLIC_KEY_INFO em um blob de chave RSA com CryptDecodeObjectEx ; passar X509_ASN_ENCODING em dwCertEncodingType e RSA_CSP_PUBLICKEYBLOB em lpszStructType
  4. importar o blob de chave RSA com CryptImportKey

Esta seqüência realmente me ajudou a entender o que está acontecendo, mas não funcionou para mim como está. A segunda chamada para CryptDecodeObjectEx deu-me um erro: "ASN.1 mau valor tag conheci". Depois de muitas tentativas de documentação compreensão Microsoft, eu finalmente percebi que a saída do decodificação punho não pode ser decodificado como ASN novamente, e que ele está realmente pronto para importação. Com esse entendimento, eu encontrei a resposta no link a seguir:

http: //www.ms-news .net / f2748 / importadores de problema-chave pública-4052577.html

A seguir é o meu próprio programa que as importações uma chave pública a partir de um arquivo .pem a um contexto 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;
}

Outras dicas

Eu descobri a seqüência de "mágica" de chamadas para importar uma chave pública RSA no formato PEM. Aqui vai:

  1. decodificar a chave em um blob binário com CryptStringToBinary ; passar CRYPT_STRING_BASE64HEADER na dwFlags
  2. decodificar o blob de chave binário em um CERT_PUBLIC_KEY_INFO com CryptDecodeObjectEx ; passar X509_ASN_ENCODING em dwCertEncodingType e X509_PUBLIC_KEY_INFO em lpszStructType
  3. decodificar o blob PublicKey do CERT_PUBLIC_KEY_INFO em um blob de chave RSA com CryptDecodeObjectEx ; passar X509_ASN_ENCODING em dwCertEncodingType e RSA_CSP_PUBLICKEYBLOB em lpszStructType
  4. importar o blob de chave RSA com CryptImportKey

Atualmente estou enfrentando a mesma dificuldade. Eu não terminei de codificação uma solução, mas como eu entendo que é preciso retirar a ----- BEGIN etc ----- e ----- END etc ------ tags e decodificar a Base64 .

Isso deixa você com uma corda DER codificado, o que você precisa analisar para obter o módulo e expoente público. Daqueles que você pode preencher as estruturas PUBLICKEYSTRUC e RSAPUBKEY. Boa sorte; -)

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top