Frage

Ich versuche zu verstehen, wie einen öffentlichen Schlüssel von PEM-Format (Probe im Code enthielt unten) eingeführt bekommen über XP, Vista und Windows 7. Der Beispielcode wird den Schlüssel sowohl auf XP und Windows Vista importieren / 7 , aber nicht die gleiche Art und Weise.

Unter Windows XP die Zeichenfolge "(Prototyp)" ist in den Verschlüsselungs-Provider Namen erforderlich ist, und ermöglicht es der Aufruf CryptImportPublicKeyInfo zu passieren.

Unter Windows 7 wird die "(Prototyp)" Provider ist offenbar vorhanden, aber nicht unterstützt, den Anruf zu CryptImportPublicKeyInfo, die verwirrend ist.

Wie könnte eine korrekte Umsetzung aussehen wie zwischen diesen Betriebssystemen? Ist es notwendig, XP zu erkennen und den Namen mit anfordern „(Prototyp)“ , und ohne sie für andere Betriebssysteme? Ist es möglich, dass das immer noch auf einigen XP-Systeme scheitern?

Oder gibt es eine Möglichkeit, dieses verwirrende Verhalten zu erkennen und wählen Sie je nachdem, welche Verschlüsselungs-Provider den notwendigen Aufruf unterstützen?

Ausgabe auf Windows 7:

ANALYZING CRYPTOGRAPHIC SUPPORT FOR:
     "Microsoft Enhanced RSA and AES Cryptographic Provider"
     CryptAcquireContext success.
     CryptAcquireContext.1 success.
     CryptStringToBinary.2 success.
     CryptDecodeObjectEx success.
     CryptImportPublicKeyInfo success.
     SUCCESS.
ANALYZING CRYPTOGRAPHIC SUPPORT FOR:
     "Microsoft Enhanced RSA and AES Cryptographic Provider (Prototype)"
     CryptAcquireContext success.
     CryptAcquireContext.1 success.
     CryptStringToBinary.2 success.
     CryptDecodeObjectEx success.
     CryptImportPublicKeyInfo FAILED****.

Ausgabe unter Windows XP:

ANALYZING CRYPTOGRAPHIC SUPPORT FOR:
     "Microsoft Enhanced RSA and AES Cryptographic Provider"
     CryptAcquireContext success.
     CryptAcquireContext.1 success.
     CryptStringToBinary.2 success.
     CryptDecodeObjectEx success.
     CryptImportPublicKeyInfo FAILED****.
ANALYZING CRYPTOGRAPHIC SUPPORT FOR:
     "Microsoft Enhanced RSA and AES Cryptographic Provider (Prototype)"
     CryptAcquireContext success.
     CryptAcquireContext.1 success.
     CryptStringToBinary.2 success.
     CryptDecodeObjectEx success.
     CryptImportPublicKeyInfo success.
     SUCCESS.

C ++ Quellcode, dass die Ausgabe erzeugt: (erfordert crypt32.lib)

#include <stdio.h>
#include <tchar.h>
#include <windows.h>
#include <wincrypt.h>

bool windowsAcquireProviderContext(HCRYPTPROV *pHandleProv, LPCTSTR pProviderName);
bool analyzeCryptographicSupport(LPCTSTR pProviderName);

int _tmain(int argc, _TCHAR* argv[])
{
    analyzeCryptographicSupport(MS_ENH_RSA_AES_PROV);
    analyzeCryptographicSupport(L"Microsoft Enhanced RSA and AES Cryptographic Provider (Prototype)");
    return 0;
}

bool windowsAcquireProviderContext(HCRYPTPROV *pHandleProv, LPCTSTR pProviderName) {
    WCHAR *pContainerName = L"blah blah blah";
    if(!CryptAcquireContext(pHandleProv, pContainerName, pProviderName, PROV_RSA_AES, CRYPT_SILENT)) {
        if(GetLastError() == NTE_BAD_KEYSET) {
            if(CryptAcquireContext(pHandleProv, pContainerName, pProviderName, PROV_RSA_AES, CRYPT_NEWKEYSET|CRYPT_SILENT)) {
                return true;
            }
        } 
    }
    return true;
}

LPCWSTR pwszPemPublicKey = 
    L"-----BEGIN PUBLIC KEY-----\r\n"
    L"MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC6GUVcbn92bahlwOskKi8XkG9q\r\n"
    L"Vq863+C4cOWC6HzJojc011pJFFIBu8/pG1EI8FZJdBmTrFaJTriYw1/SpbOH0QqE\r\n"
    L"eHanT8qWn+S5m9xgDJoWTBJKcnu3OHOvJJU3c8jOHQQnRWLfghJH4vnwStdiwUUY\r\n"
    L"SMWpwuHObsNelGBgEQIDAQAB\r\n"
    L"-----END PUBLIC KEY-----\r\n";
int pemPublicKeySize = wcslen(pwszPemPublicKey);

bool analyzeCryptographicSupport(LPCTSTR pProviderName) {

    printf("ANALYZING CRYPTOGRAPHIC SUPPORT FOR:\r\n");
    wprintf(L"\t \"%s\"\r\n", pProviderName);

    HCRYPTPROV hProv;
    if(!windowsAcquireProviderContext(&hProv, pProviderName)) {
        wprintf(L"\t CryptAcquireContext FAILED.\r\n");
        return false;
    }
    wprintf(L"\t CryptAcquireContext success.\r\n");

    DWORD blobSize;

    if(!CryptStringToBinary(pwszPemPublicKey, pemPublicKeySize, CRYPT_STRING_BASE64_ANY,  NULL, &blobSize, NULL, NULL)) {
        CryptReleaseContext(hProv, 0);
        wprintf(L"\t CryptStringToBinary.1 FAILED****.\r\n");
        return false;
    }
    wprintf(L"\t CryptAcquireContext.1 success.\r\n");

    BYTE *pBlob = (BYTE *)malloc(blobSize);

    if(!CryptStringToBinary(pwszPemPublicKey, pemPublicKeySize, CRYPT_STRING_BASE64_ANY,  pBlob, &blobSize, NULL, NULL)) {
        free(pBlob);
        CryptReleaseContext(hProv, 0);
        wprintf(L"\t CryptStringToBinary.2 FAILED****.\r\n");
        return false;
    }
    wprintf(L"\t CryptStringToBinary.2 success.\r\n");

    CERT_PUBLIC_KEY_INFO *publicKeyInfo;
    DWORD publicKeyInfoLen;
    HCRYPTKEY hPublicKey;

    if(!CryptDecodeObjectEx(X509_ASN_ENCODING|PKCS_7_ASN_ENCODING, X509_PUBLIC_KEY_INFO, pBlob, blobSize, CRYPT_DECODE_ALLOC_FLAG, NULL, &publicKeyInfo, &publicKeyInfoLen)) {
        free(pBlob);
        CryptReleaseContext(hProv, 0);
        wprintf(L"\t CryptDecodeObjectEx FAILED****.\r\n");
        return false;
    }
    wprintf(L"\t CryptDecodeObjectEx success.\r\n");

    if(!CryptImportPublicKeyInfo(hProv, X509_ASN_ENCODING|PKCS_7_ASN_ENCODING, publicKeyInfo, &hPublicKey)) {
        LocalFree(publicKeyInfo);
        free(pBlob);
        CryptReleaseContext(hProv, 0);
        wprintf(L"\t CryptImportPublicKeyInfo FAILED****.\r\n");
        return false;
    }
    wprintf(L"\t CryptImportPublicKeyInfo success.\r\n");

    CryptDestroyKey(hPublicKey);
    LocalFree(publicKeyInfo);
    free(pBlob);
    CryptReleaseContext(hProv, 0);

    wprintf(L"\t SUCCESS.\r\n");
    return true;
}
War es hilfreich?

Lösung

Der Grund des Problems, das Sie beschreibt, ist sehr einfach: Microsoft umbenannt AES Cryptographic Provider von

  • "Microsoft Enhanced RSA and AES Cryptographic Provider (Prototype)" in Windows XP
  • "Microsoft Enhanced RSA and AES Cryptographic Provider" in den späteren Versionen der Betriebssysteme.

In WinCrypt.h sind die entsprechenden Konstanten wie MS_ENH_RSA_AES_PROV und MS_ENH_RSA_AES_PROV_XP definiert, die Sie verwenden können.

Wenn Sie nicht möchten, dass die Version des Betriebssystems testen, können Sie nur ein href verwenden <= "http://msdn.microsoft.com/en-us/library/aa379886%28VS.85%29. aspx "> CryptAcquireContext mit NULL als pszProvider (und Nutzung PROV_RSA_AES als dwProvType fortgesetzt). In Ihrem Code können Sie analyzeCryptographicSupport(NULL); umfassen.

Sie können auch den „Name“ Wert des Registrierungsschlüssels

prüfen
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography\Defaults\Provider Types\Type 024

den Namen der Standard PROV_RSA_AES Anbieter zu sehen.

Andere Tipps

Ich glaube, ich erinnere mich, irgendwo, dass Microsoft auf dem Namen gepatzt und es erfordert „(Prototyp)“, die auf XP und abwesend auf Vista und höher zu sein. Ich glaube, Sie müssen die Plattform zur Laufzeit erkennen und die entsprechende Zeichenfolge verwenden.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top