用CryptoAPI实现DES加密的问题

StarsunYzL 2009-02-06 12:17:50
如题,用Windows的CryptoAPI计算MD5我会,但是怎样用CryptoAPI实现DES加密?
自己搞了半天,程序编译没问题,加密得的结果虽然是8字节,但是不对。
对照了MSDN也没看出哪不对,百度、谷歌更是搜不到,有搞过的人能不能指点一下,谢谢!

#include <iostream>
#include <Windows.h>
#include <tchar.h>

#pragma comment(lib, "Crypt32.lib")

int _tmain(int argc, _TCHAR* argv[])
{
BYTE pKey[] = "123";
//BYTE pIV[] = {0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF};
BYTE pData[256] = "abc";
DWORD dwDataLen = 3;

HCRYPTPROV hProv;
if (CryptAcquireContext(&hProv, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL, 0))
{
HCRYPTHASH hHash;
if (CryptCreateHash(hProv, CALG_MD5, 0, 0, &hHash))
{
CryptHashData(hHash, pKey, sizeof(pKey), 0);
HCRYPTKEY hKey;
if (CryptDeriveKey(hProv, CALG_DES, hHash, 0x00380000, &hKey))
{
//CryptSetKeyParam(hKey, KP_IV, pIV, 0);
CryptEncrypt(hKey, 0, TRUE, 0, pData, &dwDataLen, _countof(pData));
TCHAR szBase64[256];
DWORD dwBase64Len = sizeof(szBase64) / sizeof(szBase64[0]);
CryptBinaryToString(pData, dwDataLen, CRYPT_STRING_BASE64, szBase64, &dwBase64Len);
_tprintf(szBase64);
CryptDestroyKey(hKey);
}
CryptDestroyHash(hHash);
}
CryptReleaseContext(hProv, 0);
}
return 0;
}
...全文
1186 15 打赏 收藏 转发到动态 举报
写回复
用AI写文章
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
xiebopublic 2009-05-04
  • 打赏
  • 举报
回复
楼主,请把完美结果后的C++代码贴出来? :-)
StarsunYzL 2009-02-10
  • 打赏
  • 举报
回复
意思是我想用密钥"11111111"来加密数据"1"(这里的1都是字符串,也就是0x31),我用其它两个工具算得出的正确结果是cf 60 cf ac ab 67 bb a8,
但是我4楼帖的程序运行输出的结果却是5c a2 98 19 f0 28 89 40,当然我也试过用密钥11111111来加密数据1(这里的1都直接是数字,也就是0x01,和前面举例的字符串不一样),结果一样不正确。
我的代码哪里有问题?或者能否帖个完整的用CryptoAPI实现DES加密的代码。谢谢了!
StarsunYzL 2009-02-10
  • 打赏
  • 举报
回复
OK,问题完美解决,再次感谢cofanz!
StarsunYzL 2009-02-10
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 cofanz 的回复:]
其它两个工具是什么,有可能是KP_IV不一样引起的吧。
[/Quote]

一个是PYG密码学综合工具,另一个是Win-Tool之编码转换工具
这两个工具都只用填写密钥和要加密的数据,并不用填写IV向量,但加密出来的结果却是一样的,难道这两个工具里IV是一样的?
是不是标准的DES规定有一个固定的IV值?但是我查了些DES的算法描述,并没有看到有关IV的说明
dlschan 2009-02-10
  • 打赏
  • 举报
回复
不懂,帮顶
cofanz 2009-02-10
  • 打赏
  • 举报
回复
cbc模式最后一个字节是padding的长度,如果数据刚好是完整的分组,则需要一个额外的分组来表示padding。
cofanz 2009-02-10
  • 打赏
  • 举报
回复
其它两个工具是什么,有可能是KP_IV不一样引起的吧。
StarsunYzL 2009-02-10
  • 打赏
  • 举报
回复
[Quote=引用 11 楼 cofanz 的回复:]
这两个工具应该是对数据按8字节补齐了,而且结果只是8字节长的话,说明不是cbc模式
[/Quote]

原来是这样,我以为CryptoAPI会自动补齐后再计算。我对算法不甚了解,感谢你的帮助,差不多可以结贴了,还有最后一个问题,
就是你说的加密结果的长度问题,用密钥“11111111”加密数据“11111111”,上面两个程序得到的结果是8字节的65 5e a6 28 cf 62 58 5f,
但是CryptoAPI得到的却是16字节的65 5e a6 28 cf 62 58 5f 04 5b e2 ac fe 00 f0 c1,前8字节是一样的,但是多出了8字节,尝试了所有加密模式,都是16字节,
这是为何呢?那我该怎么确定最终的加密结果是多少字节?


int _tmain(int argc, _TCHAR* argv[])
{
struct
{
BLOBHEADER hdr;
DWORD cbKeySize;
BYTE rgbKeyData[8];
} keyBlob;

keyBlob.hdr.bType = PLAINTEXTKEYBLOB;
keyBlob.hdr.bVersion = CUR_BLOB_VERSION;
keyBlob.hdr.reserved = 0;
keyBlob.hdr.aiKeyAlg = CALG_DES;
keyBlob.cbKeySize = 8;
BYTE Key[8] = {0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31};
CopyMemory(keyBlob.rgbKeyData, Key, keyBlob.cbKeySize);

BYTE pData[256] = {0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31};
DWORD dwDataLen = 8;

HCRYPTPROV hProv;
if (CryptAcquireContext(&hProv, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL, 0))
{
HCRYPTKEY hKey;
if (CryptImportKey(hProv, (BYTE*)(&keyBlob), sizeof(keyBlob), 0, 0, &hKey))
{
DWORD dwMode = CRYPT_MODE_CBC;
CryptSetKeyParam(hKey, KP_MODE, (BYTE*)(&dwMode), 0);
CryptEncrypt(hKey, 0, TRUE, 0, pData, &dwDataLen, _countof(pData));
for (int i = 0; i != dwDataLen; ++i)
_tprintf(_T("%02x "), pData[i]);
_tprintf(_T("\r\n"));
CryptDestroyKey(hKey);
}
CryptReleaseContext(hProv, 0);
}
return 0;
}
cofanz 2009-02-10
  • 打赏
  • 举报
回复
这两个工具应该是对数据按8字节补齐了,而且结果只是8字节长的话,说明不是cbc模式
cofanz 2009-02-09
  • 打赏
  • 举报
回复
得不到正确结果是什么意思
StarsunYzL 2009-02-08
  • 打赏
  • 举报
回复
先谢谢提示,原来plain text key用的是CryptImportKey
但是我的代码好像还是得不到正确的结果,能否麻烦帮忙调试一下是哪的问题,再次谢谢


#include <iostream>
#include <Windows.h>
#include <tchar.h>

#pragma comment(lib, "Crypt32.lib")

int _tmain(int argc, _TCHAR* argv[])
{
struct keyBlob
{
BLOBHEADER hdr;
DWORD cbKeySize;
BYTE rgbKeyData[8];
} keyBlob;

keyBlob.hdr.bType = PLAINTEXTKEYBLOB;
keyBlob.hdr.bVersion = CUR_BLOB_VERSION;
keyBlob.hdr.reserved = 0;
keyBlob.hdr.aiKeyAlg = CALG_DES;
keyBlob.cbKeySize = 8;
BYTE Key[8] = {0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31};
CopyMemory(keyBlob.rgbKeyData, Key, keyBlob.cbKeySize);

//BYTE pIV[8] = {0x0d, 0x3a, 0x62, 0xdd, 0xfe, 0xcb, 0x2b, 0xba};

BYTE pData[256] = {0x31};
DWORD dwDataLen = 1;

HCRYPTPROV hProv;
if (CryptAcquireContext(&hProv, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL, 0))
{
HCRYPTKEY hKey;
if (CryptImportKey(hProv, (BYTE*)(&keyBlob), sizeof(keyBlob), 0, CRYPT_EXPORTABLE, &hKey))
{
//CryptSetKeyParam(hKey, KP_IV, pIV, 0);
CryptEncrypt(hKey, 0, TRUE, 0, pData, &dwDataLen, _countof(pData));
for (int i = 0; i != dwDataLen; ++i)
_tprintf(_T("%02x "), pData[i]);
_tprintf(_T("\r\n"));
CryptDestroyKey(hKey);
}
CryptReleaseContext(hProv, 0);
}
return 0;
}
cofanz 2009-02-06
  • 打赏
  • 举报
回复

GBool KeyEncryptionAlgorithm::decrypt( Guchar *pdata, Gulong *dataLen, Guchar* key, Gulong keyLen)
{
GBool ok = gFalse;
#ifdef _WIN32
HCRYPTPROV hCryptProv = NULL;
HCRYPTKEY hKey = NULL;

Gulong errcode;

struct {
BLOBHEADER hdr;
Gulong len;
BYTE key[32];
} key_blob;

if(!CryptAcquireContext(&hCryptProv, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL, 0))
{
return gFalse;
}

key_blob.hdr.bType = PLAINTEXTKEYBLOB;
key_blob.hdr.bVersion = CUR_BLOB_VERSION;
key_blob.hdr.aiKeyAlg = Algid;
key_blob.hdr.reserved = 0;
key_blob.len = keyLen;
memcpy(key_blob.key, key, keyLen);
if (!CryptImportKey(hCryptProv, (BYTE*)&key_blob, sizeof(key_blob), NULL, 0, &hKey))
{
errcode = GetLastError();
goto err;
}

if (Params)
{
if (Algid == CALG_3DES)
{
if (!CryptSetKeyParam(hKey, KP_IV, Params, 0))
{
errcode = GetLastError();
}
}
}
// Decrypt data.
if(!CryptDecrypt(hKey, NULL, gTrue, 0, pdata, dataLen))
{
errcode = GetLastError();
goto err;
}
ok = gTrue;
err:
if(hKey)
CryptDestroyKey(hKey);
if(hCryptProv)
CryptReleaseContext(hCryptProv, 0);

#else

#endif
return ok;
}
cofanz 2009-02-06
  • 打赏
  • 举报
回复
其中,Params可以是个固定值"\x0d\x3a\x62\xdd\xfe\xcb\x2b\xba"
cofanz 2009-02-06
  • 打赏
  • 举报
回复

GBool KeyEncryptionAlgorithm::encrypt( Guchar *pdata, Gulong *dataLen, Gulong bufLen, Guchar* key, Gulong keyLen )
{
#ifdef _WIN32
HCRYPTPROV hCryptProv = NULL;
HCRYPTKEY hKey = NULL;
GBool ok = gFalse;
Gulong errcode;

if(!CryptAcquireContext(&hCryptProv, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL, 0))
{
return gFalse;
}
if (Algid == CALG_RSA_KEYX)
{
struct {
PUBLICKEYSTRUC hdr;
RSAPUBKEY rsapubkey;
Guchar modulus[130];
} key_blob;

key_blob.hdr.bType = PUBLICKEYBLOB;
key_blob.hdr.bVersion = CUR_BLOB_VERSION;
key_blob.hdr.aiKeyAlg = Algid;
key_blob.hdr.reserved = 0;
key_blob.rsapubkey.bitlen = 1024;
key_blob.rsapubkey.magic = 0x31415352;
Guchar *pubkey = key;
if (!IsSequence(*pubkey++))
goto err;
Gulong len1;
pubkey = getLength(pubkey, &len1);
pubkey = getLittleEndianOctetInteger(pubkey, key_blob.modulus, &len1);
getInteger(pubkey, &key_blob.rsapubkey.pubexp);

if (!CryptImportKey(hCryptProv, (Guchar*)&key_blob, sizeof(key_blob), NULL, 0, &hKey))
{
errcode = GetLastError();
goto err;
}
}
else
{
struct {
BLOBHEADER hdr;
Gulong len;
BYTE key[32];
} key_blob;

key_blob.hdr.bType = PLAINTEXTKEYBLOB;
key_blob.hdr.bVersion = CUR_BLOB_VERSION;
key_blob.hdr.aiKeyAlg = Algid;
key_blob.hdr.reserved = 0;
key_blob.len = keyLen;
memcpy(key_blob.key, key, keyLen);

if (!CryptImportKey(hCryptProv, (BYTE*)&key_blob, sizeof(key_blob), NULL, 0, &hKey))
{
errcode = GetLastError();
goto err;
}
}

if (Params)
{
if (Algid == CALG_3DES)
{
if (!CryptSetKeyParam(hKey, KP_IV, Params, 0))
{
errcode = GetLastError();
}
}
}
if(!CryptEncrypt(hKey, NULL, gTrue, 0, pdata, dataLen, bufLen))
{
errcode = GetLastError();
goto err;
}
ok = gTrue;
err:
if(hKey)
CryptDestroyKey(hKey);
if(hCryptProv)
CryptReleaseContext(hCryptProv, 0);
return ok;
#else
return gFalse;
#endif
}

2,640

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 硬件/系统
社区管理员
  • 硬件/系统社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧