2011-02-17 116 views

回答

4

沒有CryptoAPI的豐富知識,這應該是困難得多。

的主要障礙是:

  • 解碼使用CryptStringToBinaryA和CryptDecodeObjectEx
  • 轉換DSA簽名格式的X509 DSA公鑰
    • OpenSSL的DSA_sign在ASN.1 DER產生DSA簽名格式
    • CryptoAPI的CryptVerifySignature預計在P1363格式的DSA簽名

這裏有一個如何我終於解決了這個問題一個粗略的樣本:

const char* pubKey = "MIIBtjCCASsGByqGSM44BAEwggEeAoGBANW/k8nYREKtRMvIShnJTSAwxF33haU4" 
         ..... 
         "/FEGAibbOp31rjq9UfaJ2t06eN0t0B+DP1hjz/MfpGtPOxHqF3dQnDRa3ot1FSTP"; 

bool verify(const unsigned char* msgData, unsigned int msgLength, const unsigned char* signature, unsigned int signatureLength) 
{ 
    HCRYPTPROV hCryptProv; 
    if (!CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_DSS, CRYPT_VERIFYCONTEXT)) 
    { 
     return false; 
    } 

    bool result = false; 

    unsigned char derPubKey[2048]; 
    DWORD derPubKeyLen = 2048; 
    CERT_PUBLIC_KEY_INFO *publicKeyInfo = NULL; 
    DWORD publicKeyInfoLen = 0; 

    if (CryptStringToBinaryA(pubKey, strlen(pubKey), CRYPT_STRING_BASE64, derPubKey, &derPubKeyLen, NULL, NULL) && 
     CryptDecodeObjectEx(X509_ASN_ENCODING, X509_PUBLIC_KEY_INFO, derPubKey, derPubKeyLen, 
           CRYPT_ENCODE_ALLOC_FLAG, NULL, &publicKeyInfo, &publicKeyInfoLen)) 
    { 
     HCRYPTKEY hPubKey; 
     if (CryptImportPublicKeyInfo(hCryptProv, X509_ASN_ENCODING, publicKeyInfo, &hPubKey)) 
     { 
      HCRYPTHASH hHash; 
      if (CryptCreateHash(hCryptProv, CALG_SHA1, 0, 0, &hHash)) 
      { 
       CryptHashData(hHash, msgData, msgLength, 0); 

       BYTE* dsaSignature = NULL; 
       DWORD dsaSignatureLen = 0; 
       if (CryptDecodeObjectEx(X509_ASN_ENCODING, X509_DSS_SIGNATURE, signature, signatureLength, 
             CRYPT_ENCODE_ALLOC_FLAG, NULL, &dsaSignature, &dsaSignatureLen)) 
       { 
        if (CryptVerifySignature(hHash, dsaSignature, dsaSignatureLen, hPubKey, NULL, 0)) 
        { 
         result = true; 
        } 
        LocalFree(dsaSignature); 
       } 

       CryptDestroyHash(hHash); 
      } 
      CryptDestroyKey(hPubKey); 
     } 
     LocalFree(publicKeyInfo); 
    } 
    CryptReleaseContext(hCryptProv, 0); 
    return result; 
} 
1

剛一說明,微軟的加密API不支持DSA密鑰長度大於1024 CryptImportPublicKeyInfo,可以()將失敗,並NTE_BAD_DATA 。

+0

謝謝! BTW:當使用大於1024(Win10)的DSA密鑰時,我在賭E_INVALIDARG(0x80070057)。 – Youw 2018-01-08 19:00:51