首页
社区
课程
招聘
[求助]各位前辈看看我这们用CryptoApi加密注册码正确吗,为什么在另一台计算机上结果不一样了
发表于: 2009-12-14 18:52 6615

[求助]各位前辈看看我这们用CryptoApi加密注册码正确吗,为什么在另一台计算机上结果不一样了

2009-12-14 18:52
6615
我做了一个手机软件是在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在各个系统版本不一样的情况下不能通用了.请指点下,不胜感激

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费 0
支持
分享
最新回复 (5)
雪    币: 205
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
没人知道吗,自己顶一下
2009-12-18 07:15
0
雪    币: 1022
活跃值: (31)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
3
调试下CryptDecrypt函数,看下它解密时到底用的是哪个密钥,难道容器初始化有问题?
会不会是用CryptDecrypt函数解密像RSA类的非对称算法,调用时有什么注意事项?
PS:没用过Crypt API,希望不会误导你~~~
2009-12-18 11:37
0
雪    币: 208
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
没在手机上玩过程序,但在PC上碰到过LZ的问题

原因是编译器设置不同,造成变量长度不同,如int是2字节还是4字节等。加密程序大量使用移位等计算,变量长度不对就不能保证结果正确
2009-12-19 06:58
0
雪    币: 205
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
谢谢楼上的两位,我已经从网上找了些大数运算的算法,正在自己实现大数运算类.本论坛上也有相关的运算类,我也参考了.我不需要很多功能,只要能私钥加密,公钥解密就行了,
2009-12-21 19:27
0
雪    币: 295
活跃值: (461)
能力值: ( LV9,RANK:210 )
在线值:
发帖
回帖
粉丝
6
解密不正确很可能就是你加密使用的N、E和交给客户的不一样,猜想应该是系统平台的字节存储顺序造成的。
你可以把你的N顺序按照字节倒序,可能在对方的手机中就正确运行了
2009-12-26 12:21
0
游客
登录 | 注册 方可回帖
返回
//