使用cryptapi加密数据,为何在64位下很慢?

LinuxCard 2015-02-12 10:06:00
网上找了一个例子,用的是cryptapi里面的加密算法,用的des加密,10M的数据加密解密,循环10次
在32位机器上测试结果是3秒多
在64位的机器上测试结果是15秒多

64位的是很新的服务器,不是硬件问题导致的

请问,为什么会出现这个问题呀?

下面是源代码:
功能是先用 dh算法来交换密钥,密钥交换成功后,用des来加密,上面测得得时间是从加密开始算起


#//pragma comment(lib,"Crypt32.lib")
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>

#include <Wincrypt.h>


#define DHKEYSIZE 512


void HandleError(char *s);

static const BYTE g_rgbPrime[] =
{
0x91, 0x02, 0xc8, 0x31, 0xee, 0x36, 0x07, 0xec,
0xc2, 0x24, 0x37, 0xf8, 0xfb, 0x3d, 0x69, 0x49,
0xac, 0x7a, 0xab, 0x32, 0xac, 0xad, 0xe9, 0xc2,
0xaf, 0x0e, 0x21, 0xb7, 0xc5, 0x2f, 0x76, 0xd0,
0xe5, 0x82, 0x78, 0x0d, 0x4f, 0x32, 0xb8, 0xcb,
0xf7, 0x0c, 0x8d, 0xfb, 0x3a, 0xd8, 0xc0, 0xea,
0xcb, 0x69, 0x68, 0xb0, 0x9b, 0x75, 0x25, 0x3d,
0xaa, 0x76, 0x22, 0x49, 0x94, 0xa4, 0xf2, 0x8d
};

// Generator in little-endian format.
static BYTE g_rgbGenerator[] =
{
0x02, 0x88, 0xd7, 0xe6, 0x53, 0xaf, 0x72, 0xc5,
0x8c, 0x08, 0x4b, 0x46, 0x6f, 0x9f, 0x2e, 0xc4,
0x9c, 0x5c, 0x92, 0x21, 0x95, 0xb7, 0xe5, 0x58,
0xbf, 0xba, 0x24, 0xfa, 0xe5, 0x9d, 0xcb, 0x71,
0x2e, 0x2c, 0xce, 0x99, 0xf3, 0x10, 0xff, 0x3b,
0xcb, 0xef, 0x6c, 0x95, 0x22, 0x55, 0x9d, 0x29,
0x00, 0xb5, 0x4c, 0x5b, 0xa5, 0x63, 0x31, 0x41,
0x13, 0x0a, 0xea, 0x39, 0x78, 0x02, 0x6d, 0x62
};



//基于DH密钥交换协议的例子
void DH()
{
// PCHAR szSource;
// PCHAR szDestination;
// PCHAR szPassword;
// char response;
BYTE *bufa;
BYTE *bufb;
int buflen;
buflen = 1024 * 1024 * 10; // 10M的数据
bufa = new BYTE[buflen];
bufb = new BYTE[buflen];
memcpy(bufb, bufa, buflen);

BOOL fReturn;
HCRYPTPROV hCryptProv1 ; //密钥1的CSP
HCRYPTPROV hCryptProv2 ; //密钥2的CSP
HCRYPTKEY hPrivateKey1 = NULL;
HCRYPTKEY hPrivateKey2 = NULL;
HCRYPTKEY hSessionKey1 = NULL;
HCRYPTKEY hSessionKey2 = NULL;
DWORD dwDataLen1;
DWORD dwDataLen2;
DATA_BLOB P;
DATA_BLOB G;
PBYTE pbKeyBlob1 = NULL;
PBYTE pbKeyBlob2 = NULL;
ALG_ID Algid = CALG_DES;
BYTE *pbData;
int i = 0;

P.cbData = DHKEYSIZE/8;
P.pbData = (BYTE*)(g_rgbPrime);

G.cbData = DHKEYSIZE/8;
G.pbData = (BYTE*)(g_rgbGenerator);




printf("连接CSP1(DH)...\n");

if(CryptAcquireContext(
&hCryptProv1,
NULL,
MS_ENH_DSS_DH_PROV,//MS_ENHANCED_PROV
PROV_DSS_DH, //PROV_RSA_FULL
CRYPT_VERIFYCONTEXT)) //0
{
printf("打开CSP1成功 \n");
}
else
{
HandleError("调用 CryptAcquireContext 出错!");
}


printf("生成密钥对1...\n");

if(CryptGenKey(
hCryptProv1,
CALG_DH_EPHEM,
DHKEYSIZE << 16 | CRYPT_EXPORTABLE | CRYPT_PREGEN,
&hPrivateKey1))
{
printf("创建会话密钥1成功. \n");
}
else
{
HandleError("调用 CryptGenKey 出错!");
}

// Set the prime for party 1's private key.
fReturn = CryptSetKeyParam(
hPrivateKey1,
KP_P,
(PBYTE)&P,
0);
if(!fReturn)
{
goto ErrorExit;
}

// Set the generator for party 1's private key.
fReturn = CryptSetKeyParam(
hPrivateKey1,
KP_G,
(PBYTE)&G,
0);
if(!fReturn)
{
goto ErrorExit;
}

// Generate the secret values for party 1's private key.
fReturn = CryptSetKeyParam(
hPrivateKey1,
KP_X,
NULL,
0);
if(!fReturn)
{
goto ErrorExit;
}

printf("连接CSP2(DH)...\n");
if(CryptAcquireContext(
&hCryptProv2,
NULL,
MS_ENH_DSS_DH_PROV,//MS_ENHANCED_PROV
PROV_DSS_DH, //PROV_RSA_FULL
CRYPT_VERIFYCONTEXT)) //0
{
printf("打开CSP2成功 \n");
}
else
{
HandleError("调用 CryptAcquireContext 出错!");
}


printf("生成密钥对2...\n");

if(CryptGenKey(
hCryptProv2,
CALG_DH_EPHEM,
DHKEYSIZE << 16 | CRYPT_EXPORTABLE | CRYPT_PREGEN,
&hPrivateKey2))
{
printf("创建会话密钥2成功. \n");
}
else
{
HandleError("调用 CryptGenKey 出错!");
}

fReturn = CryptSetKeyParam(
hPrivateKey2,
KP_P,
(PBYTE)&P,
0);
if(!fReturn)
{
goto ErrorExit;
}

// Set the generator for party 2's private key.
fReturn = CryptSetKeyParam(
hPrivateKey2,
KP_G,
(PBYTE)&G,
0);
if(!fReturn)
{
goto ErrorExit;
}

// Generate the secret values for party 2's private key.
fReturn = CryptSetKeyParam(
hPrivateKey2,
KP_X,
NULL,
0);
if(!fReturn)
{
goto ErrorExit;
}



printf("\n开始导出pubkey1...\n");


//导出1的公钥
if(!CryptExportKey(hPrivateKey1,NULL,PUBLICKEYBLOB,0,NULL,&dwDataLen1))
{
goto ErrorExit;
}
if(!(pbKeyBlob1 = (PBYTE)malloc(dwDataLen1)))
{
goto ErrorExit;
}

if(!CryptExportKey(hPrivateKey1,0,PUBLICKEYBLOB,0,pbKeyBlob1,&dwDataLen1))
{
goto ErrorExit;
}
printf("成功导出pubkey1...\n");
// for(;i < dwDataLen1 ; i++)
// printf("%d ",pbKeyBlob1);


printf("\n开始导出pubkey2...\n");
//导出2的公钥
if(!CryptExportKey(hPrivateKey2,NULL,PUBLICKEYBLOB,0,NULL,&dwDataLen2))
{
goto ErrorExit;
}
if(!(pbKeyBlob2 = (PBYTE)malloc(dwDataLen2)))
{
goto ErrorExit;
}

if(!CryptExportKey(hPrivateKey2,0,PUBLICKEYBLOB,0,pbKeyBlob2,&dwDataLen2))
{
goto ErrorExit;
}

printf("成功导出pubkey2...\n");
// for(i=0;i < dwDataLen2 ; i++)
// printf("%d ",pbKeyBlob2);
printf("\n");


//party 2 导入1的公钥得到 会话密钥1
if(!CryptImportKey(
hCryptProv2,
pbKeyBlob1,
dwDataLen1,
hPrivateKey2,
0,
&hSessionKey1))
{
HandleError("调用 CryptAcquireContext 出错!");
//goto ErrorExit;
}
printf("成功得到会话密钥1...\n");

//将会话密钥1转化为对称密钥
if(!CryptSetKeyParam(hSessionKey1,KP_ALGID,(PBYTE)&Algid,0))
{
goto ErrorExit;
}
printf("成功得到对称会话密钥1...\n");

//party 1 导入2的公钥得到 会话密钥2
if(!CryptImportKey(
hCryptProv1,
pbKeyBlob2,
dwDataLen2,
hPrivateKey1,
0,
&hSessionKey2))
{
HandleError("调用 CryptAcquireContext 出错!");
goto ErrorExit;
}
printf("成功得到会话密钥2...\n");



//将会话密钥2转化为对称密钥
if(!CryptSetKeyParam(hSessionKey2,KP_ALGID,(PBYTE)&Algid,0))
{
goto ErrorExit;
}

//用会话密钥1加密一些数据
DWORD t=GetTickCount();
for(int i=0;i<10;i++)
{
DWORD dwLength=buflen-1024;

fReturn = CryptEncrypt(
hSessionKey1,
0,
TRUE,
0,
bufa,
&dwLength,
buflen);
if(!fReturn)
{
HandleError("CryptEncrypt!");
goto ErrorExit;
}
//printf("加密后:%s\n",pbData);
fReturn = fReturn = CryptDecrypt(
hSessionKey2,
0,
TRUE,
0,
bufa,
&dwLength);
if(!fReturn)
{
HandleError("CryptEncrypt!");
goto ErrorExit;
}
int datalen=buflen-1024;
if (memcmp(bufa, bufb, datalen) != 0)
HandleError("memcmp error");
//printf("使用会话密钥2解密...\n解密后:%s\n",pbData);
//用会话密钥2解密一些数据
}
printf("time: %d",GetTickCount()-t);
getchar();

ErrorExit:

if(hPrivateKey1)
{
CryptDestroyKey(hPrivateKey1);
hPrivateKey2 = NULL;
}
if(hPrivateKey2)
{
CryptDestroyKey(hPrivateKey2);
hPrivateKey2 = NULL;
}
if(hCryptProv1)
{
CryptReleaseContext(hCryptProv1, 0);
hCryptProv1 = NULL;
}

if(hCryptProv2)
{
CryptReleaseContext(hCryptProv2, 0);
hCryptProv2 = NULL;
}

}



//************************************************************************/

//出错处理函数
void HandleError(char *s)
{
printf("本程序在运行时有错误发生.\n");
printf("%s\n",s);
printf("错误码: %x\n.",GetLastError());
printf("程序退出.\n");
exit(1);

}
int main(int argc, char* argv[])
{
DH();
return 0;
}

...全文
244 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
用户 昵称 2015-02-13
  • 打赏
  • 举报
回复
引用 5 楼 LinuxCard 的回复:
[quote=引用 4 楼 jennyvenus 的回复:] 函数没为64位优化,比如你本来可以一次操作8字节,原来的算法一次最多操作4字节,势必不合适。 算法本身跟硬件无关,但是实现跟硬件非常相关,合适的算法比不合适的快几百倍的事情也发生过。
那就只有忍了?cryptoapi没听说有64位版本的呀[/quote] des代码那么多,几乎是拿过来就能用的,换一个嘛,非得用cryptoapi中的des?其他的你不变,就这个换一下应该没问题吧。
LinuxCard 2015-02-13
  • 打赏
  • 举报
回复
引用 4 楼 jennyvenus 的回复:
函数没为64位优化,比如你本来可以一次操作8字节,原来的算法一次最多操作4字节,势必不合适。 算法本身跟硬件无关,但是实现跟硬件非常相关,合适的算法比不合适的快几百倍的事情也发生过。
那就只有忍了?cryptoapi没听说有64位版本的呀
用户 昵称 2015-02-13
  • 打赏
  • 举报
回复
函数没为64位优化,比如你本来可以一次操作8字节,原来的算法一次最多操作4字节,势必不合适。 算法本身跟硬件无关,但是实现跟硬件非常相关,合适的算法比不合适的快几百倍的事情也发生过。
LinuxCard 2015-02-12
  • 打赏
  • 举报
回复
引用 1 楼 oyljerry 的回复:
加点log等,然后看时间花在什么地方
调试过了,就是花在加密解密函数的调用上,其他都挺快的
oyljerry 2015-02-12
  • 打赏
  • 举报
回复
加点log等,然后看时间花在什么地方
liuxychad 2015-02-12
  • 打赏
  • 举报
回复
mark,学习一下

16,471

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • Web++
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

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