Windows XP対VistaのMS Crypto API動作/7
-
12-10-2019 - |
質問
XP、Vista、Windows 7にわたって、PEM形式(以下のコードに含まれるサンプル)からインポートされた公開キーを取得する方法を理解しようとしています。サンプルコードはXPとWindows Vista/7の両方にキーをインポートしますが、同じ方法。
Windows XPで、文字列 "(プロトタイプ)" 暗号化プロバイダーの名前で必要であり、cryptimportpublickeyinfoへの呼び出しがパスできるようにします。
Windows 7では "(プロトタイプ)" プロバイダーは明らかに存在していますが、Cryptimportpublickeyinfoへの呼び出しをサポートしていません。
これらのオペレーティングシステム間で正しい実装はどのように見えますか? XPを検出して名前をリクエストする必要がありますか "(プロトタイプ)", 、そして他のオペレーティングシステムのためにそれがありませんか?一部のXPシステムでまだ失敗する可能性はありますか?
または、この混乱を招く動作を検出し、必要な呼び出しをサポートする暗号化プロバイダーを選択する方法はありますか?
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****.
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 ++ソースコード:( 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;
}
解決
あなたが説明する問題の理由は非常に簡単です: MicrosoftはAES暗号プロバイダーに改名しました から
"Microsoft Enhanced RSA and AES Cryptographic Provider (Prototype)"
Windows XPに"Microsoft Enhanced RSA and AES Cryptographic Provider"
操作システムの後のバージョン。
の WinCrypt.h
対応する定数として定義されます MS_ENH_RSA_AES_PROV
と MS_ENH_RSA_AES_PROV_XP
使用できるもの。
操作システムのバージョンをテストしたくない場合は、使用できます Cryptacirecontext と NULL
なので pszProvider
(そして引き続き使用します PROV_RSA_AES
として dwProvType
)。コードに含めることができます analyzeCryptographicSupport(NULL);
.
レジストリキーの「名前」値を調べることもできます
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography\Defaults\Provider Types\Type 024
デフォルトの名前を表示します PROV_RSA_AES
プロバイダー。
他のヒント
Microsoftが名前でGoofを上げた場所を読んだことを覚えていると思います。それは「(プロトタイプ)」がXPに存在し、Vista以上に存在しないことを必要とします。実行時にプラットフォームを検出し、適切な文字列を使用する必要があると思います。