2017-06-01 178 views
1

我要加密使用C++和WinCrypt(RSA算法)库和解密使用C#加密与C++和WinCrypt(RSA算法)库和解密使用C#

我做加密和解密使用C++成功,但是当我想要解密,使用C#异常抛出加密文本:“解码OAEP填充时发生错误。”

以下为C++代码:

void main() 
{ 
Acqired(); 
Generate2048BitKeys(); 
ExportPrivateKey(L"privateKey.txt"); 
ExportPublicKey(L"publicKey.txt"); 

// Encrypt 
ImportKey(L"publicKey.txt"); 
EncryptDataWriteToFile(L"New Text For Encryption...", L"encryptedData.txt"); 
DestroyKeys(); 

// Decrypt 
Acqired(); 
ImportKey(L"privateKey.txt"); 
LPBYTE lpDecryptedData = NULL; 
DWORD dwDataLen = 0; 
DecryptDataFromFile(&lpDecryptedData, L"encryptedData.txt", &dwDataLen); 
WriteBytesFile(L"decryptedData.txt", lpDecryptedData, dwDataLen); 
} 
void DestroyKeys() 
{ 
if (hKey != NULL) 
{ 
    CryptDestroyKey(hKey); 
    hKey = NULL; 
} 

if (hProvider != NULL) 
{ 
    CryptReleaseContext(hProvider, 0); 
    hProvider = NULL; 
    } 
} 
void Acqired() 
{ 
    BOOL res = CryptAcquireContext(&hProvider, NULL, MS_ENHANCED_PROV, 
    PROV_RSA_FULL, CRYPT_VERIFYCONTEXT); 
if (!res) 
{ 
    std::printf("Error Acquiring Key Context\n"); 
    return; 
} 
std::printf("Key Context Acquired\n"); 
} 
void Generate2048BitKeys() 
{ 
const DWORD RSA2048BIT_KEY = 0x8000000; 
DWORD dwParams; 
dwParams = RSA2048BIT_KEY | CRYPT_EXPORTABLE | CRYPT_NO_SALT; //set the 
key length to 2048 bits, allow the keys to be exported, no salt 
bool res = CryptGenKey(hProvider, AT_KEYEXCHANGE, dwParams, &hKey); 
if (!res) 
{ 
    printf("SERVER: Unable to generate exchange keys\n"); 
    return; 
} 
printf("SERVER: Exchange keys generated\n"); 
} 
void ExportPrivateKey(LPTSTR lpFileName) 
{ 
if (hKey == NULL) 
{ 
    printf("Error in function 'ExportPrivateKey', hKey is NULL\n"); 
    return; 
} 

DWORD dwDataLen = 0; 
bool exportResult = CryptExportKey(hKey, NULL, PRIVATEKEYBLOB, 0, NULL, &dwDataLen); 
LPBYTE lpKeyBlob = (LPBYTE)malloc(dwDataLen); 
exportResult = CryptExportKey(hKey, NULL, PRIVATEKEYBLOB, 0, lpKeyBlob, &dwDataLen); 
WriteBytesFile(lpFileName, lpKeyBlob, dwDataLen); 
free(lpKeyBlob); 
} 
void ExportPublicKey(LPTSTR lpFileName) 
{ 
if (hKey == NULL) 
{ 
    printf("Error in function 'ExportPublicKey', hKey is NULL\n"); 
    return; 
} 

DWORD dwDataLen = 0; 
bool exportResult = CryptExportKey(hKey, NULL, PUBLICKEYBLOB, 0, NULL, &dwDataLen); 
LPBYTE lpKeyBlob = (LPBYTE)malloc(dwDataLen); 
exportResult = CryptExportKey(hKey, NULL, PUBLICKEYBLOB, 0, lpKeyBlob, &dwDataLen); 
WriteBytesFile(lpFileName, lpKeyBlob, dwDataLen); 
free(lpKeyBlob); 
} 
void ImportKey(LPTSTR lpFileName) 
{ 
if (hProvider == NULL) 
{ 
    printf("Error in function ImportKey, hProvider is NULL\n"); 
    return; 
} 

if (hKey != NULL) 
    CryptDestroyKey(hKey); 

LPBYTE lpKeyContent = NULL; 
DWORD dwDataLen = 0; 
ReadBytesFile(lpFileName, &lpKeyContent, &dwDataLen); 
bool importResult = CryptImportKey(hProvider, lpKeyContent, dwDataLen, 0, CRYPT_OAEP, &hKey); 
if (!importResult) 
{ 
    printf("Error in function ImportKey, CryptImportKey is failed\n"); 
    return; 
} 

delete[] lpKeyContent; 
} 
void EncryptDataWriteToFile(LPTSTR lpSimpleDataToEncrypt, LPTSTR lpFileName) 
{ 
DWORD SimpleDataToEncryptLength = _tcslen(lpSimpleDataToEncrypt) * sizeof(TCHAR); 
DWORD BufferLength = SimpleDataToEncryptLength * 10; 
BYTE *EncryptedBuffer = new BYTE[BufferLength]; 

SecureZeroMemory(EncryptedBuffer, BufferLength); 
CopyMemory(EncryptedBuffer, lpSimpleDataToEncrypt, 
SimpleDataToEncryptLength); 

bool cryptResult = CryptEncrypt(hKey, NULL, TRUE, CRYPT_OAEP, EncryptedBuffer, &SimpleDataToEncryptLength, BufferLength); 
if (!cryptResult) 
{ 
    printf("Error in function EncryptDataWriteToFile, CryptEncrypt is failed\n"); 
    return; 
} 

WriteBytesFile(lpFileName, EncryptedBuffer, SimpleDataToEncryptLength); 
delete[] EncryptedBuffer; 

printf("Encrypt Data Successfully\n"); 
} 
void DecryptDataFromFile(LPBYTE *lpDecryptedData, LPTSTR lpFileName, DWORD *dwDecryptedLen) 
{ 
if (hKey == NULL) 
{ 
    printf("Error in function 'DecryptDataFromFile', hKey is NULL.\n"); 
    return; 
} 

LPBYTE lpEncryptedData = NULL; 
DWORD dwDataLen = 0; 
ReadBytesFile(lpFileName, &lpEncryptedData, &dwDataLen); 

bool decryptResult = CryptDecrypt(hKey, NULL, TRUE, CRYPT_OAEP, lpEncryptedData, &dwDataLen); 
if (!decryptResult) 
{ 
    printf("Error in function 'DecryptDataFromFile', CryptDecrypt cann't be decrypted data.\n"); 
    return; 
} 
printf("decrypted Successfully ... \n"); 
*dwDecryptedLen = dwDataLen; 
*lpDecryptedData = new BYTE[dwDataLen + 1]; 
SecureZeroMemory(*lpDecryptedData, dwDataLen + 1); 
CopyMemory(*lpDecryptedData, lpEncryptedData, dwDataLen); 

delete[]lpEncryptedData; 
} 
void WriteBytesFile(LPTSTR lpFileName, BYTE* content, DWORD dwDataLen) 
{ 
HANDLE hFile = CreateFile(lpFileName, GENERIC_READ | GENERIC_WRITE, 0x7, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); 
DWORD dwBytesWritten = 0; 
bool result = WriteFile(hFile, content, dwDataLen, &dwBytesWritten, NULL); 
CloseHandle(hFile); 
} 
void ReadBytesFile(LPTSTR lpFileName, BYTE **content, DWORD *dwDataLen) 
{ 
HANDLE hFile = CreateFile(lpFileName, GENERIC_READ, 0x7, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); 
DWORD dwFileLength = 0; 
DWORD dwBytesToRead = GetFileSize(hFile, NULL); 
DWORD dwBytesRead = 0; 

*content = new BYTE[dwBytesToRead + 1]; 
SecureZeroMemory(*content, dwBytesToRead + 1); 

ReadFile(hFile, *content, dwBytesToRead, &dwBytesRead, NULL); 

*dwDataLen = dwBytesRead; 

CloseHandle(hFile); 
} 

和C#代码:

const int PROVIDER_RSA_FULL = 1; 
    const string SERVICE_PROVIDER = "Microsoft Enhanced Cryptographic Provider v1.0"; //128 bit encryption 
    static void Main(string[] args) 
    { 
     //var publicKey = File.ReadAllBytes("D:\\RSA\\pubkey.afp"); 
     var privateKey = File.ReadAllBytes("D:\\RSA\\privateKey.txt"); 
     var Data = File.ReadAllBytes("D:\\RSA\\encryptedData.txt"); 



     RSACryptoServiceProvider rsa; 


     CspParameters cspParams; 
     cspParams = new CspParameters(PROVIDER_RSA_FULL); 

     cspParams.Flags = CspProviderFlags.UseExistingKey | CspProviderFlags.UseMachineKeyStore; 
     cspParams.ProviderName = SERVICE_PROVIDER; 

     using (rsa = new RSACryptoServiceProvider(2048,cspParams)) 
     { 
     rsa.ImportCspBlob(privateKey); 
     // ---------------------------------------------------------------------- 
     byte[] result = rsa.Decrypt(Data, true); 
     Console.WriteLine(Convert.ToString(result)); 
     } 
    } 

谁能帮我?

回答

1
这个问题

最好的方式使用托管C++

创建LIB C++,用lib在托管C++,然后你可以使用C#中的管理文件