2017-04-21 14 views
3

C#에서 RijndaelManaged를 사용하여 데이터를 암호화하고 C++ 코드에서 해독해야합니다.Windows AES 암호화 공급자를 사용하여 C++에서 C# 암호화 된 데이터를 암호 해독

C# 암호화 코드 :

static string Encrypt(string plainText) 
{ 
    byte[] plainTextBytes = Encoding.UTF8.GetBytes(plainText); 

    var keyBytes = new byte[] { /* ... 32 bytes of a key */}; 
    byte[] iv = new byte[] { /* ... 16 bytes of IV */ }; 


    var symmetricKey = new RijndaelManaged() 
    { 
     Mode = CipherMode.CBC, 
     Padding = PaddingMode.Zeros, 
     BlockSize = 128, // Must be 128 to be compatible with AES 
     KeySize = 256 
    }; 

    var encryptor = symmetricKey.CreateEncryptor(keyBytes, iv); 

    byte[] cipherTextBytes; 
    using(var memoryStream = new MemoryStream()) 
    { 
     using(var cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write)) 
     { 
      cryptoStream.Write(plainTextBytes, 0, plainTextBytes.Length); 
      cryptoStream.FlushFinalBlock(); 
      cipherTextBytes = memoryStream.ToArray(); 
      cryptoStream.Close(); 
     } 
     memoryStream.Close(); 
    } 
    return Convert.ToBase64String(cipherTextBytes); 
} 

그러나 C++ 코드를 암호 해독 할 때 나는 항상를 CryptDecrypt에서 응답 NTE_BAD_DATA 얻을.

__declspec(dllexport) DWORD Decrypt(char* stringBuffer) 
{ 
string encryptedString(stringBuffer); 

// Decode base64 string to byte array. Works ok, the binary array is the same as the one in C# code. 
vector<BYTE> encryptionBuffer = Base64::decode(encryptedString); 
DWORD bufferSize = encryptionBuffer.size(); 

struct CryptoBlob { 
    BLOBHEADER header; 
    DWORD cbKeySize; 
    BYTE rgbKeyData[32]; 
} keyBlob; 

keyBlob.header.bType = PLAINTEXTKEYBLOB; 
keyBlob.header.bVersion = CUR_BLOB_VERSION; 
keyBlob.header.reserved = 0; 
keyBlob.header.aiKeyAlg = CALG_AES_256; 
keyBlob.cbKeySize = 32; 

BYTE keyData[32] = { /* 32 bytes of a key the same as in C# code */ }; 
BYTE ivData[16] = { /* 16 bytes of IV the same as in C# code */ }; 

memcpy(keyBlob.rgbKeyData, keyData, 32); 

HCRYPTKEY hPubKey; 
HCRYPTPROV hProv; 

CryptAcquireContext(
    &hProv, 
    NULL, 
    NULL, 
    PROV_RSA_AES, 
    CRYPT_VERIFYCONTEXT); 

CryptImportKey(hProv, (const LPBYTE)&keyBlob, sizeof(keyBlob), 0, 0, &hPubKey); 
CryptSetKeyParam(hPubKey, KP_IV, ivData, 0); 

// Here the error happens, the value returned is 0x80090005 (NTE_BAD_DATA) 
DWORD err = CryptDecrypt(hPubKey, 0, TRUE, 0, encryptionBuffer.data(), &bufferSize); 

// overwrite the input buffer with decrypted data 
memset(stringBuffer, 0, encryptedString.length()); 
memcpy(stringBuffer, encryptionBuffer.data(), bufferSize); 

return 0; 
} 

어떤 생각이 잘못 될 수 있는지 : 여기에 (모든 검사가 명확성을 위해 제거) C++ 코드는? 감사합니다.

+1

필자는 * 패딩 *과 관련된 동일한 문제에 대한 여러 참조를 조사한 바 있습니다. 여기를 확인하십시오 : [CryptoAPI CryptDecrypt 함수 NT_BAD_DATA 오류] (https://social.msdn.microsoft.com/Forums/windowsdesktop/en-US/e2735c15-afe8-4f86-abb8-14e987fb0ccd/cryptoapi-cryptdecrypt-function-ntbaddata-error ? forum = vcgeneral) 여기에 : [CryptDecrypt function] (https://msdn.microsoft.com/ko-kr/library/windows/desktop/aa379913(v=vs.85)asp) (NTE_BAD_DATA 오류 코드). –

답변

4

TRUE을 세 번째 매개 변수로 CryptDecrypt으로 전달하면 PKCS # 7 패딩을 취소하려고 시도합니다. 해당 패딩을 실행 취소 할 수 없으면 NTE_BAD_DATA를 내 보냅니다.

암호화의 패딩 모드를 Pkcs7 이외의 값으로 변경 했으므로 FALSE을 전달하고 수동 depadding을 수행해야합니다.

PaddingMode.Zeros는 본질적으로 실행 취소 할 수 없으므로 수행 할 수있는 장애물이 없습니다.

+0

그것은 작동합니다! 고마워요! – ElDog

0

위의 대답이 아니라면, 나는 C++과 C# 둘 다 key/iv를보고 바이트 배열이 정확히 똑같은지 확인하는 것이 좋습니다.

마지막에 여분의 문자가 있으면 문제가 발생할 수 있습니다.

일치하지 않는 경우 프로그래밍 언어와 구현에 따라 반환되는 출력 유형 (예 : 서명/서명되지 않은 문자/바이트 배열)에 차이가있을 수 있으며 문제가 발생할 수 있다는 점에 유의하십시오.

+0

예, 몹시 불투명했습니다. 귀하의 의견에 감사드립니다. – didiz