我做了一个手机软件是在windows mobile 5或以上系统上运行的
软件根据手机计算出机器码
然后用户把机器码发给我
然后用我的注册机程序根据这个机器码生成密钥文件,密钥文件中包含了机器码加密后的密文,和公钥数据,可是把这个密钥文件发给用户后,用户在他们的系统上导入公钥后解密后的数据不是原来的机器码,导至无法注册,而我在我手机试验上确注册成功,且试了好多次了,是不是CryptoApi在系统版本不一样的情况下,公钥不能通用了.下面贴出我的代码,
注册机加密机器码的代码和软件里导入公钥解密的代码
1,注册机加密机器码的代码
//导出公钥文件和加密后的密文
void CKeyDlg::OnOutKeyfile()
{
HCRYPTPROV hProv=NULL;
HCRYPTKEY hXchgKey=NULL;
if(!CryptAcquireContext(&hProv,NULL,MS_DEF_PROV,PROV_RSA_FULL,0))
{
if(!CryptAcquireContext(&hProv,NULL, MS_DEF_PROV,PROV_RSA_FULL,CRYPT_NEWKEYSET))
{
OutputDebugString(TEXT("\n创建容器失败\n"));
return ;
}
}
if(!CryptGetUserKey(hProv,AT_KEYEXCHANGE,&hXchgKey))
{
OutputDebugString(TEXT("\n取得密钥句柄失败\n"));
if(GetLastError()==NTE_NO_KEY)
{
OutputDebugString(TEXT("\n没有密钥,正在创建\n"));
if(!CryptGenKey(hProv,AT_KEYEXCHANGE,0,&hXchgKey))
{
OutputDebugString(TEXT("\n创建密钥失败\n"));
return;
}
}
}
PBYTE pbKeyBlob=NULL;
DWORD dwBlobLen;
DWORD dwLen;
char szText[1024];
_tcscpy(szText,"123456789");//被加密的字符串,
dwLen=strlen(szText);
if(!CryptEncrypt(hXchgKey,0,TRUE,0,(BYTE*)szText,&dwLen,200))//加密上面的字符串
{
OutputDebugString(TEXT("\n加密出错\n"));
}
else
{
OutputDebugString(TEXT("\n加密成功\n"));
wsprintf(szTmp,TEXT("\n加密长度:%d\n"),dwLen);
OutputDebugString(szTmp);
}
if(!CryptExportKey(hXchgKey,NULL,PUBLICKEYBLOB,0,NULL,&dwBlobLen))//获取导出公钥的长度
{
OutputDebugString(TEXT("获取长度失败\n"));
return ;
}
if((pbKeyBlob=(PBYTE)malloc(dwBlobLen))==NULL)//分配内存来导出公钥
{
OutputDebugString(TEXT("\n内存不足\n"));
}
if(!CryptExportKey(hXchgKey,NULL,PUBLICKEYBLOB,0,pbKeyBlob,&dwBlobLen))//导出公钥
{
OutputDebugString(TEXT("导出失败\n"));
}
HANDLE hFile=CreateFile(szPath,GENERIC_WRITE,FILE_SHARE_READ,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,0);
CFile file;
if(!file.Open(szPath,CFile::modeCreate|CFile::modeReadWrite,NULL))
{
return ;
}
DWORD dwWrited=0;
file.Write(&dwLen,sizeof(DWORD));//上面密文123456789的长度
file.Write(szText,dwLen);//密文123456789
file.Write(&dwBlobLen,sizeof(DWORD));//公钥长度
file.Write(pbKeyBlob,dwBlobLen);//公钥
file.Close();
CryptDestroyKey(hXchgKey);
CryptReleaseContext(hProv,0);
}
//软件里根据注册文件获取公钥和密文后解密的代码
//解密,相关数据已经从文件中读出,
void DePass()
{
if(!CryptAcquireContext(&hProv,NULL,NULL,PROV_RSA_FULL,0))
{
if(!CryptAcquireContext(&hProv,NULL,0,PROV_RSA_FULL,CRYPT_NEWKEYSET))
{
//OutputDebugString(TEXT("\n创建密钥容器失败\n"));
MessageBox(hWnd,TEXT("创建数据失败"),TEXT("提示"),MB_OK);
return
}
}
//导入密钥
//dwBlobLen为已经获取的公钥长度,从上面的注册文件中读出来的
//pkKeyBlob为根据dwBlobLen分配内荐
//导入公钥
if(!CryptImportKey(hProv,pbKeyBlob,dwBlobLen,0,0,&hXchgKey))
{
return 0;
}
//dwLen为密文的长度
//btPassText,为根据dwLen分配的内存,已经从上面的文件中读取出密文,将用上面导入的公钥解密,主要错误就是错在这里,老提示密钥错误或不正确
if(CryptDecrypt(hXchgKey,0,0,0,(BYTE*)btPassText,&dwLen))
{
OutputDebugString(TEXT("\n解密后数据为:\n"));
OutputDebugString(szOutText);
}
else
{
//老提示失败,用GetLastError提示"获取密钥错误"
}
if(pbKeyBlob)VirtualFreepbKeyBlob,dwBlobLen,MEM_RELEASE);
if(hXchgKey)CryptDestroyKey(hXchgKey);
if(hProv)CryptReleaseContext(hProv,0);
}
各位前辈看看,我这样使用正确吗,为什么在我的手机系统试验使用就没有问题,而我把这个注册文件发给别人,就无法解密.当然是根据用户的机器加的密,是不是Windows的CryptoApi在各个系统版本不一样的情况下不能通用了.请指点下,不胜感激
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)