KJKHyperion a dit dans son answer:
I discovered the "magic" sequence of calls to import a RSA public key in PEM format. Here you go:
- decode the key into a binary blob with CryptStringToBinary; pass CRYPT_STRING_BASE64HEADER in dwFlags
- decode the binary key blob into a CERT_PUBLIC_KEY_INFO with CryptDecodeObjectEx; pass X509_ASN_ENCODING in dwCertEncodingType and X509_PUBLIC_KEY_INFO in lpszStructType
- decode the PublicKey blob from the CERT_PUBLIC_KEY_INFO into a RSA key blob with CryptDecodeObjectEx; pass X509_ASN_ENCODING in dwCertEncodingType and RSA_CSP_PUBLICKEYBLOB in lpszStructType
- import the RSA key blob with CryptImportKey
Cette séquence m'a vraiment aidé à comprendre ce qui se passe , mais ça n'a pas marché pour moi tel quel. Le deuxième appel à CryptDecodeObjectEx
m'a donné une erreur: "ASN.1 bad tag value met". Après de nombreuses tentatives de compréhension de la documentation de Microsoft, j'ai finalement réalisé que la sortie du premier décodage ne peut plus être décodée en ASN et qu'elle est 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/problem-importing-public-key-4052577.html
Ce qui suit est mon propre programme qui importe une clé publique d'un.fichier pem dans un contexte de 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;
}
pourriez-vous fournir la clé publique WORKING? Votre programme ne fonctionne toujours pas pour moi .. mais ma clé est vraiment valide. – socketpair
Autre implémentation: http://idrix.fr/Root/Samples/capi_pem.cpp – socketpair
@socketpair en fonction de l'implémentation, la signature numérique devra peut-être être complètement inversée par octet avant d'être vérifiée – moala