0

私はMicrosoftCryptoAPIを使用するためのコードを書こうとしています。目標は非常に単純です。文字列を暗号化してから復号化します。ほぼ機能しているようですが、CryptDecryptMessageの最後の呼び出しが失敗します。

したがって、文字列を正常に暗号化することができます。次に、暗号化されたバイナリ文字列を取得して復号化しようとすると、CryptDecryptMessageへの最後の呼び出しを除いてすべてが機能します。私が使用している復号化コードは以下のとおりです。

コードが立っているとき、出力バッファーの必要なサイズを取得するためのCryptDecryptMessageの最初の呼び出しは成功しますが、常にクリアテキスト文字列サイズに6を加えたものに等しいサイズを返します。次に出力バッファーのサイズを大きくし、次の呼び出しto CryptDecryptMessageは失敗します(戻り値はゼロで、ゼロdwSizeRequiredに設定され、出力バッファーには何も入れられず、GetLastErrorNTE_BAD_KEYを返します)。

一方、コメントを外す#define TESTING_INCORRECTと、動作が少し異なります。CryptDecryptMessageへの最初の呼び出しは成功します。その戻り値はゼロですが、期待どおりのをGetLastError返します。最も重要なのは、エンコードされた元のクリアテキスト文字列のサイズで設定されることです。次に、CryptDecryptMessageを2回割り当てて呼び出しますが、上記のように再び失敗します。ERROR_MORE_DATAdwSizeRequired

最後に、キーストアに秘密証明書キーがあります。

ここで何が悪いのか誰かが知っていますか????? ありがとう。

void decrypt(std::string& sClearTextString , const std::vector<T_Byte>& sEncryptedBinaryString, const std::string& sKey)
{
    BOOL bResult;

    HCRYPTPROV hProv;
    bResult = CryptAcquireContext( &hProv, NULL, MS_DEF_PROV, PROV_RSA_FULL, 0); 
    CHECK_CRYPT_ERR( !bResult , "Unable to find crypto context");

    HCERTSTORE hStore(NULL);
    const char* const pcKey = sKey.empty()? "MY" : sKey.c_str();
    hStore = CertOpenSystemStore( 0, pcKey);
    CHECK_CRYPT_ERR( hStore==NULL, "unable to open certificate store.");

    HCERTSTORE CertStoreArray[] = {hStore};

    CRYPT_DECRYPT_MESSAGE_PARA  DecryptParams;
    DWORD  DecryptParamsSize = sizeof(DecryptParams);
    memset(&DecryptParams, 0, DecryptParamsSize);
    DecryptParams.cbSize = DecryptParamsSize;
    DecryptParams.dwMsgAndCertEncodingType = (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING);
    DecryptParams.cCertStore = sizeof(CertStoreArray)/sizeof(HCERTSTORE);
    DecryptParams.rghCertStore = CertStoreArray;

    const BYTE* const pbContent = &sEncryptedBinaryString[0];
    DWORD dwSize = STATICCAST<DWORD>(sEncryptedBinaryString.size());
    DWORD dwSizeRequired = 0;

    BYTE* pbOutBuffer = NULL;
//#define TESTING_INCORRECT
#ifdef TESTING_INCORRECT
    std::string sDummyBuffer(2,'\0');
    pbOutBuffer = (BYTE*)(&sDummyBuffer[0]);
#endif

    // Get required buffer size.
    bResult = CryptDecryptMessage( &DecryptParams, pbContent, dwSize, pbOutBuffer, &dwSizeRequired, NULL);
    CHECK_CRYPT_ERR( !bResult && ERROR_MORE_DATA != GetLastError() , "Unable to get buffer length");

    //Allocate buffer
    sClearTextString.clear();
    sClearTextString.resize(dwSizeRequired+1,0);
    pbOutBuffer = (BYTE*)(&sClearTextString[0]);

    //Now actually decryt
    bResult = CryptDecryptMessage( &DecryptParams, pbContent, dwSize, pbOutBuffer, &dwSizeRequired, NULL);
    CHECK_CRYPT_ERR( !bResult , "Unable to decrypt");

    CertCloseStore(hStore, CERT_CLOSE_STORE_CHECK_FLAG);
    CryptReleaseContext(hProv, 0);
}
4

1 に答える 1

2

使用されているキーを調査します。2148073475の戻りコードは、実際には0x80090003に変換されます。これはNTE_BAD_KEYです。234のGetLastErrorはERR_MORE_DATAであり、これはバッファのサイズが小さすぎることを示します。

問題は、CryptDecryptMessageへの最初の呼び出しがサイジング呼び出しのためにpbDecryptedへのポインターとしてNULLを受け取るという期待にあると思いますが、コメントが削除されたnullではないため、何かを復号化しようとしていると考えて234の結果が得られますそれはすでにサイズ設定されています。

サイジング(最初の)呼び出しの受信バッファーがnullであるという推定が正しい場合、NTE_BAD_KEYエラーコードに従って、キーが何らかの形で疑わしい可能性があることを示唆します。

それがあなたのためにいくつかの有益な考えをかき立てることを願っています。

于 2013-02-28T18:22:36.280 に答える