KJKHyperion ha detto nel suo 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
Questa sequenza mi ha aiutato a capire cosa sta succedendo , ma non ha funzionato per me così com'è. La seconda chiamata a CryptDecodeObjectEx
mi ha restituito un errore: "Valore tag non valido ASN.1 soddisfatto". Dopo molti tentativi di comprensione della documentazione Microsoft, ho finalmente realizzato che l'output della decodifica del pugno non può essere decodificato come ASN e che è effettivamente pronto per l'importazione. Con questa comprensione ho trovato la risposta al seguente link:
http://www.ms-news.net/f2748/problem-importing-public-key-4052577.html
seguito è il mio programma che importa una chiave pubblica da un.file PEM ad un contesto 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;
}
potresti fornire la chiave pubblica di LAVORO? Il tuo programma non funziona ancora per me ... ma la mia chiave è davvero valida. – socketpair
Un'altra implementazione: http://idrix.fr/Root/Samples/capi_pem.cpp – socketpair
@socketpair a seconda dell'implementazione, potrebbe essere necessario che la firma digitale sia completamente invertita in byte prima di essere verificata – moala