2010-12-21 15 views
9

पर एमएस क्रिप्टो एपीआई व्यवहार मैं समझने की कोशिश कर रहा हूं कि XP, Vista और Windows 7 में पीईएम प्रारूप (नीचे दिए गए कोड में शामिल नमूना) से आयात की गई सार्वजनिक कुंजी कैसे प्राप्त करें। नमूना कोड एक्सपी और विंडोज विस्टा/7 दोनों पर कुंजी आयात करें, लेकिन वही नहीं।विंडोज एक्सपी बनाम विस्टा/7

Windows XP, स्ट्रिंग "(प्रोटोटाइप)" पर क्रिप्टोग्राफिक प्रदाता के नाम में आवश्यक है, और CryptImportPublicKeyInfo करने के लिए कॉल पारित करने के लिए अनुमति देता है।

विंडोज 7 पर, "(प्रोटोटाइप)" प्रदाता स्पष्ट रूप से मौजूद है, लेकिन CryptImportPublicKeyInfo को कॉल का समर्थन नहीं करता है, जो भ्रमित है।

इन ऑपरेटिंग सिस्टम के बीच एक सही कार्यान्वयन कैसा दिख सकता है? क्या XP को पहचानना और "(प्रोटोटाइप)" के साथ नाम का अनुरोध करना आवश्यक है, और इसके बिना अन्य ऑपरेटिंग सिस्टम के लिए? क्या यह संभव है कि यह अभी भी कुछ एक्सपी सिस्टम पर असफल रहेगा?

या, इस भ्रमित व्यवहार का पता लगाने और किसी भी क्रिप्टोग्राफिक प्रदाता को आवश्यक कॉल का समर्थन करने का कोई तरीका है? विंडोज 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. 

सी ++ स्रोत कोड जो पैदा करता है कि उत्पादन: (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; 
} 

उत्तर

10

समस्या है जो आप का वर्णन करने के कारण बहुत आसान है: माइक्रोसॉफ्ट

  • "Microsoft Enhanced RSA and AES Cryptographic Provider" को Windows XP में

    • "Microsoft Enhanced RSA and AES Cryptographic Provider (Prototype)" से एईएस क्रिप्टोग्राफिक प्रदाता नाम बदलकर आपरेशन सिस्टम के बाद के संस्करणों में।

    WinCrypt.h में MS_ENH_RSA_AES_PROV और MS_ENH_RSA_AES_PROV_XP जो आप उपयोग कर सकते हैं के रूप में इसी स्थिरांक परिभाषित कर रहे हैं।

    आप आप सिर्फ NULLpszProvider के रूप में साथ CryptAcquireContext उपयोग कर सकते हैं आपरेशन सिस्टम के संस्करण का परीक्षण (और dwProvType रूप PROV_RSA_AES का उपयोग जारी) करने के लिए नहीं करना चाहते हैं। आपके कोड में आप analyzeCryptographicSupport(NULL); शामिल कर सकते हैं।

    तुम भी डिफ़ॉल्ट PROV_RSA_AES प्रदाता का नाम देखने के लिए रजिस्ट्री कुंजी

    HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography\Defaults\Provider Types\Type 024 
    

    की "नाम" मूल्य की जांच कर सकते हैं।

  • +1

    लगता है कि मेरे मामले के लिए संक्षिप्त उत्तर XP का पता लगाने और उचित प्रदाता स्ट्रिंग का उपयोग करना है ... दुर्भाग्यपूर्ण, लेकिन बहुत बड़ा सौदा नहीं। – g01d

    +0

    @ g01d, यह अच्छी तरह से काम करता है, लेकिन अधिक "सही" तरीका ओएस संस्करण का पता लगाने के लिए नहीं है, लेकिन रजिस्ट्री में क्रिप्टो नाम और वहां से हैंडल करता है। बाल बांटते हुए, मुझे पता है ... –

    +0

    @ प्रो। फाल्कन: कारण में से कोई ओएस का पता लगा सकता है। मैंने लिखा है कि कोई वैकल्पिक रूप से 'pszProvider = NULL' और' dwProvType = PROV_RSA_AES' का उपयोग कर सकता है। मैंने अपने उत्तर में * व्याख्या करने की कोशिश की कि समस्या की वास्तविक उत्पत्ति 'MS_ENH_RSA_AES_PROV' स्थिर है जो रजिस्ट्री से केवल स्ट्रिंग है। मुझे लगता है कि माइक्रोसॉफ्ट ने रजिस्ट्री में अनियंत्रित "(प्रोटोटाइप)" प्रत्यय के साथ गलत पाठ के उपयोग के साथ विंडोज एक्सपी में सिर्फ एक त्रुटि की है। इसलिए 'MS_ENH_RSA_AES_PROV_XP' की शुरूआत में त्रुटि "त्रुटि" है। यदि कोई समस्या को समझता है ** समस्या का कारण ** सबसे अच्छा समाधान चुन सकता है। – Oleg

    0

    मुझे लगता है कि मैं रिम एम्बर कहीं कहीं पढ़ रहा है कि माइक्रोसॉफ्ट ने नाम पर गुमराह किया है और इसके लिए एक्सपी पर मौजूद होने के लिए "(प्रोटोटाइप)" और Vista और उससे ऊपर अनुपस्थित होना आवश्यक है। मुझे लगता है कि आपको रनटाइम पर मंच का पता लगाना होगा और उपयुक्त स्ट्रिंग का उपयोग करना होगा।

    संबंधित मुद्दे