微软倒是有提供Crypto API并支持DES。
问题出在大部分网上的C++例子都是利用CryptHashData和CryptDeriveKey来用MD5作密码,基本没有看到直接用密码并加IV扰动的,这跟C#的DESCryptoServiceProvider处理方式很不一样。
不过C++中可以利用CryptImportKey来导入一个密码,并用CryptSetKeyParam来设置IV。
下面例子C++的结果可以用C#的方式解密:
{
byte[] bytes = { 0xf1, 0x9e, 0xfc, 0x8f, 0x6a, 0x59, 0x2d, 0xcb };
string password = "nihaoma?";
string s = DecryptDES(Convert.ToBase64String(bytes), password); //s="hello"
}
#include "stdafx.h"
#include <windows.h>
#include <atlstr.h>
#include <wincrypt.h>
const BYTE IV[] = {0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF };
DWORD DesEncrypt(CString data, CString password, BYTE* buffer, DWORD bufferLength)
{
CT2CA passwd(password, CP_UTF8);
CT2CA secret(data, CP_UTF8);
DWORD dataLength = strlen(secret);
if(buffer == NULL || bufferLength < dataLength + 8 - (dataLength % 8) || password.GetLength() < 8) return 0;
memcpy(buffer, secret, dataLength);
HCRYPTPROV hProv = NULL;
HCRYPTKEY hSessionKey = NULL;
BOOL bResult = TRUE;
typedef struct
{
BLOBHEADER header;
DWORD cbKeySize;
BYTE rgbKeyData[8];
}KeyBlob;
KeyBlob blob;
blob.header.bType = PLAINTEXTKEYBLOB;
blob.header.bVersion = CUR_BLOB_VERSION;
blob.header.reserved = 0;
blob.header.aiKeyAlg = CALG_DES;
blob.cbKeySize = 8;
memcpy(blob.rgbKeyData, passwd, 8);
bResult &= CryptAcquireContext(&hProv,NULL, MS_DEF_PROV, PROV_RSA_FULL,0);
bResult &= CryptImportKey(hProv, (BYTE*)&blob, sizeof(blob), 0, 0, &hSessionKey);
bResult &= CryptSetKeyParam(hSessionKey, KP_IV, (BYTE*)IV, 0);
bResult &= CryptEncrypt(hSessionKey, NULL, TRUE, 0, (BYTE*)buffer, &dataLength, bufferLength);
bResult &= CryptDestroyKey(hSessionKey);
bResult &= CryptReleaseContext(hProv, 0);
return bResult ? dataLength : 0;
}
void _tmain(int argc, _TCHAR* argv[])
{
BYTE buffer[8];
int dataLength = DesEncrypt("hello", "nihaoma?", buffer, sizeof(buffer));
// dataLength = 8;
// buffer = { 0xf1, 0x9e, 0xfc, 0x8f, 0x6a, 0x59, 0x2d, 0xcb };
}
注:该C++例子中没有把二进制内容转换为Base64,C++ Base64编码网上很多。