Question

Je dois charger un certificat X.509 codé PEM dans un contexte API Windows Crypto à utiliser avec C ++. Ce sont ceux qui ont ----- BEGIN RSA XXX KEY ----- et ----- END RSA XXX KEY ----- . J'ai trouvé des exemples pour Python et .NET, mais ils utilisent des fonctions spécifiques que je ne peux pas relier à l'API Windows Crypto.

Je comprends comment chiffrer / déchiffrer une fois que j'ai un HCRYPTKEY. MAIS, je ne comprends pas comment importer le blob Base64 dans le (s) fichier (s) .PEM et obtenir un HCRYPTKEY que je peux utiliser.

J'ai ce sentiment étrange qu'il ne s'agit pas simplement d'appeler CryptDecodeObject () .

Des indicateurs qui peuvent me mettre sur la bonne voie? J'ai déjà perdu deux jours à "essayer". erreur " programmation et obtenir nulle part.

Était-ce utile?

La solution

KJKHyperion a déclaré dans son répondre :

  

J'ai découvert le "magique". séquence d'appels pour importer une clé publique RSA au format PEM. Ici vous allez:

     
      
  1. décodez la clé en un objet blob binaire avec CryptStringToBinary ; transmettez CRYPT_STRING_BASE64HEADER dans dwFlags
  2.   
  3. décodez le blob de clé binaire en un CERT_PUBLIC_KEY_INFO avec CryptDecodeObjectEx ; transmettez X509_ASN_ENCODING à dwCertEncodingType et X509_PUBLIC_KEY_INFO à lpszStructType
  4.   
  5. décodez le blob PublicKey du CERT_PUBLIC_KEY_INFO en un blob de clé RSA avec CryptDecodeObjectEx ; transmettez X509_ASN_ENCODING dans dwCertEncodingType et RSA_CSP_PUBLICKEYBLOB dans lpszStructType
  6.   
  7. importer le blob de clé RSA avec CryptImportKey
  8.   

Cette séquence m'a vraiment aidé à comprendre ce qui se passe, mais cela n'a pas fonctionné pour moi tel quel. Le deuxième appel à CryptDecodeObjectEx m'a donné une erreur: "Valeur de balise ASN.1 incorrecte atteinte". Après de nombreuses tentatives pour comprendre la documentation Microsoft, j'ai finalement compris que la sortie du premier décodage ne pouvait plus être décodée en tant qu'ASN et qu'elle était prête à être importée. Avec cette compréhension, j'ai trouvé la réponse dans le lien suivant:

http: //www.ms-news .net / f2748 / problème-importation-clé-publique-4052577.html

Voici mon propre programme qui importe une clé publique d'un fichier .pem vers un contexte 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;
}

Autres conseils

J'ai découvert le "magique". séquence d'appels pour importer une clé publique RSA au format PEM. Ici vous allez:

  1. décodez la clé en un objet blob binaire avec CryptStringToBinary ; transmettez CRYPT_STRING_BASE64HEADER dans dwFlags
  2. décodez le blob de clé binaire en un CERT_PUBLIC_KEY_INFO avec CryptDecodeObjectEx ; transmettez X509_ASN_ENCODING à dwCertEncodingType et X509_PUBLIC_KEY_INFO à lpszStructType
  3. décodez le blob PublicKey du CERT_PUBLIC_KEY_INFO en un blob de clé RSA avec CryptDecodeObjectEx ; transmettez X509_ASN_ENCODING dans dwCertEncodingType et RSA_CSP_PUBLICKEYBLOB dans lpszStructType
  4. importer le blob de clé RSA avec CryptImportKey

Je suis actuellement confronté à la même difficulté. Je n'ai pas fini de coder une solution, mais si j'ai bien compris, vous devez retirer les balises ----- COMMENCER etc. ----- et ----- END etc. ------ et décoder la Base64. .

Cela vous laisse avec une chaîne codée DER, que vous devez analyser pour obtenir le module et l’exposant public. À partir de celles-ci, vous pouvez renseigner les structures PUBLICKEYSTRUC et RSAPUBKEY. Bonne chance ;-)

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top