关于微软CryptoAPI用PKI加解密的问题 (200分)

  • 主题发起人 主题发起人 devil-li
  • 开始时间 开始时间
D

devil-li

Unregistered / Unconfirmed
GUEST, unregistred user!
我用微软CryptoAPI用PKI加解密,产生两个问题:<br>1。用公钥加密的数据,公钥也可以解密。<br>2。只能够加密大约53个字符的数据,超过长度CryptEncrypt会出错。CryptEncrypt到底能不能实现PKI加密呀?<br>请教大家是什么原因。下面是我的源代码:<br><br>procedure TForm1.Button1Click(Sender: TObject);<br>begin<br>&nbsp; Str1 := Memo1.Text;<br>&nbsp; Str2 := PvtSignature.Encrypt(Str1, LoadPublicKey);//加密<br>&nbsp; Memo2.Text := Str2;<br>end;<br><br>procedure TForm1.Button2Click(Sender: TObject);<br>begin<br>&nbsp; Str1 := PvtSignature.Decrypt(Str2, LoadPrivateKey);//解密<br>&nbsp; Memo1.Text := Str1; &nbsp; <br>end;<br><br>procedure TForm1.Button3Click(Sender: TObject);<br>var<br>&nbsp; KeyPair: TKeyPair;<br>begin<br>&nbsp; KeyPair := PvtSignature.GetGenKey(PVT_KEYEXCHANGE);//产生随机密钥对<br>&nbsp; SavePrivateKey(KeyPair.PrivateKey);<br>&nbsp; SavePublicKey(KeyPair.PublicKey);<br>end;<br><br>function TPvtSignature.Decrypt(Data, Key: string): string;<br>var<br>&nbsp; hProv: HCRYPTPROV;<br>&nbsp; hKey: HCRYPTKEY;<br>&nbsp; Buffer, temp: string;<br>&nbsp; Index: Integer;<br>&nbsp; dwCount: DWORD;<br>&nbsp; Endof: Boolean;<br>&nbsp; BufferLen: DWORD;<br><br>&nbsp; procedure Init;<br>&nbsp; begin<br>&nbsp; &nbsp; hProv := 0;<br>&nbsp; &nbsp; hKey := 0;<br>&nbsp; end;<br>&nbsp; procedure Clear;<br>&nbsp; begin<br>&nbsp; &nbsp; if Boolean(hKey) then<br>&nbsp; &nbsp; &nbsp; CryptDestroyKey(hKey);<br>&nbsp; &nbsp; if Boolean(hProv) then<br>&nbsp; &nbsp; &nbsp; CryptReleaseContext(hProv, 0);<br>&nbsp; end;<br>begin<br>&nbsp; Init;<br>&nbsp; if not CryptAcquireContext(@hProv, nil, nil, PROV_RSA_FULL, 0) then<br>&nbsp; begin<br>&nbsp; &nbsp; Clear;<br>&nbsp; &nbsp; raise Exception.Create('Error during CryptAcquireContext');<br>&nbsp; end;<br><br>&nbsp; if not CryptImportKey(hProv, PByte(PChar(Key)), Length(Key), 0, 0, @hKey) then<br>&nbsp; begin<br>&nbsp; &nbsp; Clear;<br>&nbsp; &nbsp; raise Exception.Create('Error during CryptImportKey');<br>&nbsp; end;<br><br>&nbsp; Index := 1;<br>&nbsp; Result := '';<br>&nbsp; BufferLen := BlockLen + 8;<br>&nbsp; repeat<br>&nbsp; &nbsp; Buffer := Copy(Data, Index, BlockLen);<br>&nbsp; &nbsp; dwCount := Length(Buffer);<br>&nbsp; &nbsp; Inc(Index, dwCount);<br>&nbsp; &nbsp; Endof := Index &gt; Length(Data);<br>&nbsp; &nbsp; SetLength(Buffer, BufferLen);<br>&nbsp; &nbsp; if not CryptDecrypt(hKey, 0, Endof, 0, PByte(PChar(Buffer)), @dwCount) then<br>&nbsp; &nbsp; begin<br>&nbsp; &nbsp; &nbsp; Clear;<br>&nbsp; &nbsp; &nbsp; raise Exception.Create('Error during CryptDecrypt');<br>&nbsp; &nbsp; end;<br>&nbsp; &nbsp; SetLength(temp, dwCount);<br>&nbsp; &nbsp; Move(PChar(Buffer)^, Pointer(temp)^, dwCount);<br>&nbsp; &nbsp; Result := Result + temp;<br>&nbsp; until Endof;<br>&nbsp; Clear;<br>end;<br><br><br>function TPvtSignature.Encrypt(Data, Key: string): string;<br>var<br>&nbsp; hProv: HCRYPTPROV;<br>&nbsp; hKey: HCRYPTKEY;<br>&nbsp; Buffer, temp: string;<br>&nbsp; Index: Integer;<br>&nbsp; dwCount: DWORD;<br>&nbsp; Endof: Boolean;<br>&nbsp; BufferLen: DWORD;<br><br>&nbsp; procedure Init;<br>&nbsp; begin<br>&nbsp; &nbsp; hProv := 0;<br>&nbsp; &nbsp; hKey := 0;<br>&nbsp; &nbsp; Endof := False;<br>&nbsp; end;<br>&nbsp; procedure Clear;<br>&nbsp; begin<br>&nbsp; &nbsp; if Boolean(hKey) then<br>&nbsp; &nbsp; &nbsp; CryptDestroyKey(hKey);<br>&nbsp; &nbsp; if Boolean(hProv) then<br>&nbsp; &nbsp; &nbsp; CryptReleaseContext(hProv, 0);<br>&nbsp; end;<br>begin<br>&nbsp; Init;<br>&nbsp; if not CryptAcquireContext(@hProv, nil, nil, PROV_RSA_FULL, 0) then<br>&nbsp; begin<br>&nbsp; &nbsp; Clear;<br>&nbsp; &nbsp; raise Exception.Create('Error during CryptAcquireContext');<br>&nbsp; end;<br><br>&nbsp; if not CryptImportKey(hProv, PByte(PChar(Key)), Length(Key), 0, 0, @hKey) then<br>&nbsp; begin<br>&nbsp; &nbsp; Clear;<br>&nbsp; &nbsp; raise Exception.Create('Error during CryptImportKey');<br>&nbsp; end;<br><br>&nbsp; Index := 1;<br>&nbsp; Result := '';<br>&nbsp; BufferLen := BlockLen + 8;<br>&nbsp; repeat<br>&nbsp; &nbsp; Buffer := Copy(Data, Index, BlockLen);<br>&nbsp; &nbsp; dwCount := Length(Buffer);<br>&nbsp; &nbsp; Inc(Index, dwCount);<br>&nbsp; &nbsp; Endof := Index &gt; Length(Data);<br>&nbsp; &nbsp; SetLength(Buffer, BufferLen);<br>&nbsp; &nbsp; if not CryptEncrypt(hKey, 0, Endof, 0, PByte(PChar(Buffer)), @dwCount, BufferLen) then<br>&nbsp; &nbsp; begin<br>&nbsp; &nbsp; &nbsp; Clear;<br>&nbsp; &nbsp; &nbsp; raise Exception.Create('Error during CryptEncrypt');<br>&nbsp; &nbsp; end;<br>&nbsp; &nbsp; SetLength(temp, dwCount);<br>&nbsp; &nbsp; Move(PChar(Buffer)^, Pointer(temp)^, dwCount);<br>&nbsp; &nbsp; Result := Result + temp;<br>&nbsp; until Endof;<br>&nbsp; Clear;<br>end;<br><br>function TPvtSignature.GetGenKey(KeyType: TKeyPairType): TKeyPair;<br>var<br>&nbsp; hProv: HCRYPTPROV;<br>&nbsp; hKey: HCRYPTKEY;<br>&nbsp; pbPublicKeyBlob: PByte;<br>&nbsp; pbPrivateKeyBlob: PByte;<br>&nbsp; dwPublicBlobLen: DWORD;<br>&nbsp; dwPrivateBlobLen: DWORD;<br>&nbsp; VKeyType: Cardinal;<br><br>&nbsp; procedure Init;<br>&nbsp; begin<br>&nbsp; &nbsp; hProv := 0;<br>&nbsp; &nbsp; hKey := 0;<br>&nbsp; &nbsp; pbPublicKeyBlob := nil;<br>&nbsp; &nbsp; pbPrivateKeyBlob := nil;<br>&nbsp; &nbsp; dwPublicBlobLen := 0;<br>&nbsp; &nbsp; dwPrivateBlobLen := 0;<br>&nbsp; end;<br><br>&nbsp; procedure Clear;<br>&nbsp; begin<br>&nbsp; &nbsp; if dwPrivateBlobLen &lt;&gt; 0 then<br>&nbsp; &nbsp; begin<br>&nbsp; &nbsp; &nbsp; FillChar(pbPrivateKeyBlob^, dwPrivateBlobLen, 0);<br>&nbsp; &nbsp; &nbsp; FreeMem(pbPrivateKeyBlob);<br>&nbsp; &nbsp; &nbsp; FillChar(dwPrivateBlobLen, Sizeof(dwPrivateBlobLen), 0);<br>&nbsp; &nbsp; end;<br>&nbsp; &nbsp; if dwPublicBlobLen &lt;&gt; 0 then<br>&nbsp; &nbsp; begin<br>&nbsp; &nbsp; &nbsp; FillChar(pbPublicKeyBlob^, dwPublicBlobLen, 0);<br>&nbsp; &nbsp; &nbsp; FreeMem(pbPublicKeyBlob);<br>&nbsp; &nbsp; &nbsp; FillChar(dwPublicBlobLen, Sizeof(dwPublicBlobLen), 0);<br>&nbsp; &nbsp; end;<br>&nbsp; &nbsp; if Boolean(hKey) then<br>&nbsp; &nbsp; &nbsp; CryptDestroyKey(hKey);<br>&nbsp; &nbsp; if Boolean(hProv) then<br>&nbsp; &nbsp; &nbsp; CryptReleaseContext(hProv, 0);<br>&nbsp; end;<br>begin<br>&nbsp; Init;<br>&nbsp; if not CryptAcquireContext(@hProv, nil, nil, PROV_RSA_FULL, 0) then //取得CSP<br>&nbsp; begin<br>&nbsp; &nbsp; Clear;<br>&nbsp; &nbsp; raise Exception.Create('CryptAcquireContext Failed!');<br>&nbsp; end;<br><br>&nbsp; if KeyType = PVT_SIGNATURE then<br>&nbsp; &nbsp; VKeyType := AT_SIGNATURE<br>&nbsp; else<br>&nbsp; &nbsp; VKeyType := AT_KEYEXCHANGE;<br><br>&nbsp; if not CryptGenKey(hProv, VKeyType, CRYPT_EXPORTABLE, @hKey) then<br>&nbsp; begin<br>&nbsp; &nbsp; Clear;<br>&nbsp; &nbsp; raise Exception.Create('CryptGenKey Failed!');<br>&nbsp; end;<br><br>//===============================================================================<br>&nbsp; if not CryptExportKey(hKey, 0, PUBLICKEYBLOB, 0, nil,<br>&nbsp; &nbsp; @dwPublicBlobLen) then //得到从密钥盒中导出公共密钥所需空间大小<br>&nbsp; begin<br>&nbsp; &nbsp; Clear;<br>&nbsp; &nbsp; raise Exception.Create('CryptExportKey Failed!');<br>&nbsp; end;<br>&nbsp; try<br>&nbsp; &nbsp; GetMem(pbPublicKeyBlob, dwPublicBlobLen);<br>&nbsp; except<br>&nbsp; &nbsp; on EOutOfMemory do<br>&nbsp; &nbsp; begin<br>&nbsp; &nbsp; &nbsp; Clear;<br>&nbsp; &nbsp; &nbsp; raise Exception.Create('OutOfMemory!');<br>&nbsp; &nbsp; end;<br>&nbsp; end;<br>&nbsp; if not CryptExportKey(hKey, 0, PUBLICKEYBLOB, 0, pbPublicKeyBlob,<br>&nbsp; &nbsp; @dwPublicBlobLen) then //从密钥盒中导出公共密钥<br>&nbsp; begin<br>&nbsp; &nbsp; Clear;<br>&nbsp; &nbsp; raise Exception.Create('CryptExportKey Failed!');<br>&nbsp; end;<br>//===============================================================================<br>&nbsp; if not CryptExportKey(hKey, 0, PRIVATEKEYBLOB, 0, nil,<br>&nbsp; &nbsp; @dwPrivateBlobLen) then //得到从密钥盒中导出私有密钥所需空间大小<br>&nbsp; begin<br>&nbsp; &nbsp; Clear;<br>&nbsp; &nbsp; raise Exception.Create('CryptExportKey Failed!');<br>&nbsp; end;<br>&nbsp; try<br>&nbsp; &nbsp; GetMem(pbPrivateKeyBlob, dwPrivateBlobLen);<br>&nbsp; except<br>&nbsp; &nbsp; on EOutOfMemory do<br>&nbsp; &nbsp; begin<br>&nbsp; &nbsp; &nbsp; Clear;<br>&nbsp; &nbsp; &nbsp; raise Exception.Create('OutOfMemory!');<br>&nbsp; &nbsp; end;<br>&nbsp; end;<br>&nbsp; if not CryptExportKey(hKey, 0, PRIVATEKEYBLOB, 0, pbPrivateKeyBlob,<br>&nbsp; &nbsp; @dwPrivateBlobLen) then //从密钥盒中导出私有密钥<br>&nbsp; begin<br>&nbsp; &nbsp; Clear;<br>&nbsp; &nbsp; raise Exception.Create('CryptExportKey Failed!');<br>&nbsp; end;<br>//===============================================================================<br><br>&nbsp; SetLength(Result.PublicKey, dwPublicBlobLen);<br>&nbsp; SetLength(Result.PrivateKey, dwPrivateBlobLen);<br>&nbsp; Move(pbPublicKeyBlob^, Pointer(Result.PublicKey)^, dwPublicBlobLen);<br>&nbsp; Move(pbPrivateKeyBlob^, Pointer(Result.PrivateKey)^, dwPrivateBlobLen);<br>&nbsp; Clear;<br>end;<br><br>
 
以下是我找的一组C语言的代码,自己看看,<br>---- 下面以两个文件加密与解密的C程序片断为例,演示一下CryptoAPI的强大功能。这两个程序均为Win32控制台应用,程序省略了出错处理,实际运行时请加入。 <br><br>---- ①文件加密 <br><br>#include &lt; windows.h &gt;<br>#include &lt; stdio.h &gt;<br>#include &lt; stdlib.h &gt;<br>#include &lt; wincrypt.h &gt;<br><br>//确定使用RC2块编码或是RC4流式编码<br>#ifdef USE_BLOCK_CIPHER<br>#define ENCRYPT_ALGORITHMCALG_RC2<br>#define ENCRYPT_BLOCK_SIZE8<br>#else<br>&nbsp; &nbsp;#define ENCRYPT_ALGORITHMCALG_RC4<br>&nbsp; &nbsp;#define ENCRYPT_BLOCK_SIZE1<br>#endif<br><br>void CAPIDecryptFile(PCHAR szSource, <br>PCHAR szDestination, PCHAR szPassword);<br><br>void _cdecl main(int argc, char *argv[])<br>{<br>PCHAR szSource= NULL;<br>PCHAR szDestination = NULL;<br>PCHAR szPassword= NULL;<br><br>// 验证参数个数<br>if(argc != 3 &amp;&amp; argc != 4) {<br>printf("USAGE: decrypt &lt; source file &gt;<br>&nbsp;&lt; dest file &gt; [ &lt; password &gt; ]/n");<br>exit(1);<br>}<br><br>//读取参数.<br>szSource &nbsp; = argv[1];<br>szDestination &nbsp;= argv[2];<br>if(argc == 4) {<br>szPassword = argv[3];<br>}<br>CAPIDecryptFile(szSource, szDestination, szPassword);<br>}<br><br>/*szSource为要加密的文件名称,szDestination<br>为加密过的文件名称,szPassword为加密口令*/<br>void CAPIEncryptFile(PCHAR szSource, PCHAR <br>szDestination, PCHAR szPassword)<br>{<br>FILE *hSource &nbsp;= NULL;<br>FILE *hDestination = NULL;<br>INT eof = 0;<br>HCRYPTPROV hProv &nbsp; = 0;<br>HCRYPTKEY hKey = 0;<br>HCRYPTKEY hXchgKey = 0;<br>HCRYPTHASH hHash &nbsp; = 0;<br>PBYTE pbKeyBlob = NULL;<br>DWORD dwKeyBlobLen;<br>PBYTE pbBuffer = NULL;<br>DWORD dwBlockLen;<br>DWORD dwBufferLen;<br>DWORD dwCount;<br><br>hSource = fopen(szSource,"rb"));// 打开源文件.<br>hDestination = fopen(szDestination,"wb") ;<br>//.打开目标文件<br>&nbsp; &nbsp;// 连接缺省的CSP<br>CryptAcquireContext(&amp;hProv, NULL, NULL, <br>PROV_RSA_FULL, 0));<br>if(szPassword == NULL) {<br>//口令为空,使用随机产生的会话密钥加密<br>// 产生随机会话密钥.<br>CryptGenKey(hProv, ENCRYPT_ALGORITHM, <br>CRYPT_EXPORTABLE, &amp;hKey)<br>// 取得密钥交换对的公共密钥<br>CryptGetUserKey(hProv, AT_KEYEXCHANGE, &amp;hXchgKey);<br>// 计算隐码长度并分配缓冲区<br>CryptExportKey(hKey, hXchgKey, SIMPLEBLOB, 0, <br>NULL, &amp;dwKeyBlobLen);<br>pbKeyBlob = malloc(dwKeyBlobLen)) == NULL) ;<br>// 将会话密钥输出至隐码<br>CryptExportKey(hKey, hXchgKey, SIMPLEBLOB, <br>0, pbKeyBlob, &amp;dwKeyBlobLen));<br>// 释放密钥交换对的句柄<br>CryptDestroyKey(hXchgKey);<br>hXchgKey = 0;<br>// 将隐码长度写入目标文件<br>fwrite(&amp;dwKeyBlobLen, sizeof(DWORD), 1, hDestination);<br>//将隐码长度写入目标文件<br>fwrite(pbKeyBlob, 1, dwKeyBlobLen, hDestination);<br>} else {<br>//口令不为空, 使用从口令派生出的密钥加密文件<br>CryptCreateHash(hProv, CALG_MD5, 0, 0, &amp;hHash);<br>// 建立散列表<br>CryptHashData(hHash, szPassword, strlen(szPassword), 0);<br>&nbsp;//散列口令<br>// 从散列表中派生密钥<br>CryptDeriveKey(hProv, ENCRYPT_ALGORITHM, hHash, 0, &amp;hKey);<br>// 删除散列表<br>CryptDestroyHash(hHash);<br>hHash = 0;<br>&nbsp;}<br><br>&nbsp;//计算一次加密的数据字节数,必须为ENCRYPT_BLOCK_SIZE的整数倍<br>dwBlockLen = 1000 - 1000 % ENCRYPT_BLOCK_SIZE;<br>//如果使用块编码,则需要额外空间<br>if(ENCRYPT_BLOCK_SIZE &nbsp;&gt; 1) {<br>dwBufferLen = dwBlockLen + ENCRYPT_BLOCK_SIZE;<br>} else {<br>dwBufferLen = dwBlockLen;<br>}<br>//分配缓冲区<br>pbBuffer = malloc(dwBufferLen);<br>//加密源文件并写入目标文件<br>do {<br>// 从源文件中读出dwBlockLen个字节<br>dwCount = fread(pbBuffer, 1, dwBlockLen, hSource);<br>eof = feof(hSource);<br>//加密数据<br>CryptEncrypt(hKey, 0, eof, 0, pbBuffer, <br>&amp;dwCount, dwBufferLen);<br>// 将加密过的数据写入目标文件<br>fwrite(pbBuffer, 1, dwCount, hDestination);<br>} while(!feof(hSource));<br>printf("OK/n");<br>……//关闭文件、释放内存<br>&nbsp; &nbsp;}<br><br>②文件解密<br><br>void CAPIDecryptFile(PCHAR szSource, PCHAR <br>szDestination, PCHAR szPassword)<br>{<br>……//变量声明、文件操作同文件加密程序<br><br>CryptAcquireContext(&amp;hProv, NULL, NULL, PROV_RSA_FULL, 0);<br>&nbsp; if(szPassword == NULL) {<br>// 口令为空,使用存储在加密文件中的会话密钥解密<br>// 读隐码的长度并分配内存<br>fread(&amp;dwKeyBlobLen, sizeof(DWORD), 1, hSource);<br>pbKeyBlob = malloc(dwKeyBlobLen)) == NULL);<br>// 从源文件中读隐码.<br>fread(pbKeyBlob, 1, dwKeyBlobLen, hSource);<br>// 将隐码输入CSP<br>CryptImportKey(hProv, pbKeyBlob, <br>dwKeyBlobLen, 0, 0, &amp;hKey);<br>} else {<br>// 口令不为空, 使用从口令派生出的密钥解密文件<br>CryptCreateHash(hProv, CALG_MD5, 0, 0, &amp;hHash);<br>CryptHashData(hHash, szPassword, strlen(szPassword), 0);<br>CryptDeriveKey(hProv, ENCRYPT_ALGORITHM, <br>hHash, 0, &amp;hKey);<br>CryptDestroyHash(hHash);<br>hHash = 0;<br>}<br><br>dwBlockLen = 1000 - 1000 % ENCRYPT_BLOCK_SIZE;<br>if(ENCRYPT_BLOCK_SIZE &nbsp;&gt; 1) {<br>dwBufferLen = dwBlockLen + ENCRYPT_BLOCK_SIZE;<br>} else {<br>dwBufferLen = dwBlockLen;<br>}<br>pbBuffer = malloc(dwBufferLen);<br><br>//解密源文件并写入目标文件<br>do {<br>dwCount = fread(pbBuffer, 1, dwBlockLen, hSource);<br>eof = feof(hSource);<br>// 解密数据<br>CryptDecrypt(hKey, 0, eof, 0, pbBuffer, &amp;dwCount);<br>// 将解密过的数据写入目标文件<br>fwrite(pbBuffer, 1, dwCount, hDestination);<br>} while(!feof(hSource));<br>printf("OK/n");<br>……//关闭文件、释放内存<br>}<br><br>---- 以上代码在Windows NT4.0、Visual C++6.0环境中编译通过。
 
你的这段代码采用的对称密钥加密。MSDN上都有这段代码。<br>但是我要采用的是公开密钥加密(用公钥加密,私钥解密)。<br>请问如何实现。
 
我的算法是:<br>调用CryptGenKey产生随机公/私密钥对;(对应Button3Click)<br>调用Encrypt对数据用公钥加密。(对应Button1Click)<br>调用Decrypt对数据用私钥解密。(对应Button2Click)
 
我自己搞定了。<br>1。<br>CryptoAPI对公开密钥加密算法的支持需要Windows 2000 或以上版本。<br>Provider 需要MS_ENHANCED_PROV。<br>调用CryptAcquireContext(@hProv, nil, MS_ENHANCED_PROV, PROV_RSA_FULL, 0)<br>就支持公开密钥加密算法了。<br>2。好像是有这样的限制,只好用循环搞定了。<br><br>能不能收回积分呀?
 
to devil-li:<br><br>我正在研究 PKI的算法,我要实现 3DES对称加密和RSA非对称加密<br><br>能不能把你修改过可用的代码发一份给我,flanker@fj163.com<br><br>非常感谢,要分的话我就给分!<br><br>关于pki 我们可以讨论一下
 
导入这些函数的头文件delphi7里有吗?<br>你自个导入的?
 
flanker:你的email有问题,发不过去<br>WorldCreater:头文件Delphi没有,但是网上很多地方有下载
 
devil_li,请给我发一个pwxwabcd@371.com
 
请提供CryptoAPI的详细例子
 
既然大家需要,我就给大家帖几段吧:<br>//加密<br>class function TPvtCAPICrypto.Encrypt(const Data, Key: string): string;<br>var<br>&nbsp; hProv: HCRYPTPROV;<br>&nbsp; hKey: HCRYPTKEY;<br>&nbsp; Buffer, temp: string;<br>&nbsp; Index: Integer;<br>&nbsp; dwCount: DWORD;<br>&nbsp; Endof: Boolean;<br>&nbsp; BufferLen: DWORD;<br><br><br>&nbsp; procedure Init;<br>&nbsp; begin<br>&nbsp; &nbsp; hProv := 0;<br>&nbsp; &nbsp; hKey := 0;<br>&nbsp; &nbsp; Endof := False;<br>&nbsp; end;<br>&nbsp; procedure Clear;<br>&nbsp; begin<br>&nbsp; &nbsp; if Boolean(hKey) then<br>&nbsp; &nbsp; &nbsp; CryptDestroyKey(hKey);<br>&nbsp; &nbsp; if Boolean(hProv) then<br>&nbsp; &nbsp; &nbsp; CryptReleaseContext(hProv, 0);<br>&nbsp; end;<br>&nbsp; function Encrypt53(Data53: string): string;<br>&nbsp; begin<br>&nbsp; &nbsp; Init;<br><br>&nbsp; &nbsp; CryptAcquireContextEx(hProv);<br><br>&nbsp; &nbsp; if not CryptImportKey(hProv, PByte(PChar(Key)), Length(Key), 0, 0, @hKey) then<br>&nbsp; &nbsp; begin<br>&nbsp; &nbsp; &nbsp; Clear;<br>&nbsp; &nbsp; &nbsp; raise Exception.Create('Error during CryptImportKey');<br>&nbsp; &nbsp; end;<br><br>&nbsp; &nbsp; Index := 1;<br>&nbsp; &nbsp; Result := '';<br>&nbsp; &nbsp; BufferLen := BlockLen + 8;<br>&nbsp; &nbsp; repeat<br>&nbsp; &nbsp; &nbsp; Buffer := Copy(Data53, Index, BlockLen);<br>&nbsp; &nbsp; &nbsp; dwCount := Length(Buffer);<br>&nbsp; &nbsp; &nbsp; Inc(Index, dwCount);<br>&nbsp; &nbsp; &nbsp; Endof := Index &gt; Length(Data53);<br>&nbsp; &nbsp; &nbsp; SetLength(Buffer, BufferLen);<br>&nbsp; &nbsp; &nbsp; if not CryptEncrypt(hKey, 0, Endof, 0, PByte(PChar(Buffer)), @dwCount, BufferLen) then<br>&nbsp; &nbsp; &nbsp; begin<br>&nbsp; &nbsp; &nbsp; &nbsp; Clear;<br>&nbsp; &nbsp; &nbsp; &nbsp; raise Exception.Create('Error during CryptEncrypt');<br>&nbsp; &nbsp; &nbsp; end;<br>&nbsp; &nbsp; &nbsp; SetLength(temp, dwCount);<br>&nbsp; &nbsp; &nbsp; Move(PChar(Buffer)^, Pointer(temp)^, dwCount);<br>&nbsp; &nbsp; &nbsp; Result := Result + temp;<br>&nbsp; &nbsp; until Endof;<br>&nbsp; &nbsp; Clear;<br>&nbsp; end;<br>var<br>&nbsp; I: Integer;<br>&nbsp; SegStr: string;<br>begin<br>&nbsp; Result := '';<br>&nbsp; if Ord(Key[1]) = 1 then //对称密钥加密<br>&nbsp; &nbsp; Result := Encrypt53(Data)<br>&nbsp; else // &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 公开密钥加密<br>&nbsp; begin<br>&nbsp; &nbsp; for I := 0 to Length(Data) div EncryptLen + 1 do<br>&nbsp; &nbsp; begin<br>&nbsp; &nbsp; &nbsp; SegStr := Copy(Data, I * EncryptLen + 1, EncryptLen);<br>&nbsp; &nbsp; &nbsp; SegStr := Encrypt53(SegStr);<br>&nbsp; &nbsp; &nbsp; Result := Result + Chr(Length(SegStr)) + SegStr;<br>&nbsp; &nbsp; end;<br>&nbsp; end;<br>end;<br><br><br>//解密<br>class function TPvtCAPICrypto.Decrypt(const Data, Key: string): string;<br>var<br>&nbsp; hProv: HCRYPTPROV;<br>&nbsp; hKey: HCRYPTKEY;<br>&nbsp; Buffer, temp: string;<br>&nbsp; Index: Integer;<br>&nbsp; dwCount: DWORD;<br>&nbsp; Endof: Boolean;<br>&nbsp; BufferLen: DWORD;<br><br>&nbsp; procedure Init;<br>&nbsp; begin<br>&nbsp; &nbsp; hProv := 0;<br>&nbsp; &nbsp; hKey := 0;<br>&nbsp; end;<br>&nbsp; procedure Clear;<br>&nbsp; begin<br>&nbsp; &nbsp; if Boolean(hKey) then<br>&nbsp; &nbsp; &nbsp; CryptDestroyKey(hKey);<br>&nbsp; &nbsp; if Boolean(hProv) then<br>&nbsp; &nbsp; &nbsp; CryptReleaseContext(hProv, 0);<br>&nbsp; end;<br>&nbsp; function Decrypt53(Data53: string): string;<br>&nbsp; begin<br>&nbsp; &nbsp; Init;<br><br>&nbsp; &nbsp; CryptAcquireContextEx(hProv);<br><br>&nbsp; &nbsp; if not CryptImportKey(hProv, PByte(PChar(Key)), Length(Key), 0, 0, @hKey) then<br>&nbsp; &nbsp; begin<br>&nbsp; &nbsp; &nbsp; Clear;<br>&nbsp; &nbsp; &nbsp; raise Exception.Create('Error during CryptImportKey');<br>&nbsp; &nbsp; end;<br><br>&nbsp; &nbsp; Index := 1;<br>&nbsp; &nbsp; Result := '';<br>&nbsp; &nbsp; BufferLen := BlockLen + 8;<br>&nbsp; &nbsp; repeat<br>&nbsp; &nbsp; &nbsp; Buffer := Copy(Data53, Index, BlockLen);<br>&nbsp; &nbsp; &nbsp; dwCount := Length(Buffer);<br>&nbsp; &nbsp; &nbsp; Inc(Index, dwCount);<br>&nbsp; &nbsp; &nbsp; Endof := Index &gt; Length(Data53);<br>&nbsp; &nbsp; &nbsp; SetLength(Buffer, BufferLen);<br>&nbsp; &nbsp; &nbsp; if not CryptDecrypt(hKey, 0, Endof, 0, PByte(PChar(Buffer)), @dwCount) then<br>&nbsp; &nbsp; &nbsp; begin<br>&nbsp; &nbsp; &nbsp; &nbsp; Clear;<br>&nbsp; &nbsp; &nbsp; &nbsp; raise Exception.Create('Error during CryptDecrypt');<br>&nbsp; &nbsp; &nbsp; end;<br>&nbsp; &nbsp; &nbsp; SetLength(temp, dwCount);<br>&nbsp; &nbsp; &nbsp; Move(PChar(Buffer)^, Pointer(temp)^, dwCount);<br>&nbsp; &nbsp; &nbsp; Result := Result + temp;<br>&nbsp; &nbsp; until Endof;<br>&nbsp; &nbsp; Clear;<br>&nbsp; end;<br>var<br>&nbsp; SegPos, SegLen: Integer;<br>&nbsp; SegStr: string;<br>begin<br>&nbsp; Result := '';<br>&nbsp; if Ord(Key[1]) = 1 then //对称密钥解密<br>&nbsp; &nbsp; Result := Decrypt53(Data)<br>&nbsp; else // &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 公开密钥解密<br>&nbsp; begin<br>&nbsp; &nbsp; SegPos := 1;<br>&nbsp; &nbsp; while SegPos &lt; Length(Data) do<br>&nbsp; &nbsp; begin<br>&nbsp; &nbsp; &nbsp; SegLen := Ord(Data[SegPos]);<br>&nbsp; &nbsp; &nbsp; SegStr := Copy(Data, SegPos + 1, SegLen);<br>&nbsp; &nbsp; &nbsp; Result := Result + Decrypt53(SegStr);<br>&nbsp; &nbsp; &nbsp; Inc(SegPos, SegLen + 1);<br>&nbsp; &nbsp; end;<br>&nbsp; end;<br>end;
 
至于头文件,由于太大了,2.0有7800多行,就不贴了,大家自己去网上下载
 
微软CryptoAPI好像对密钥的长度和加密对象都有长度限制的,你最好查一下Windows SDK,那里面有非常详细的介绍。
 
请问devil_li,程序中BlockLen怎样取值.
 
我试了,用win2000也会出现公钥加密公钥也能解密的情况。
 
to &nbsp;devil_li : &nbsp;我刚刚开始学用CryptoAPI,如果仅仅实现对文件的加密的话不论是对称或者是不对称,在delphi 中如何调用CryptEncryp 和CryptDecrypt &nbsp;呢,是否就是你所说的在网上下载的头文件Wcrypt2.pas?能否把它导入到delphi6中成为一个单元,是用new component 加入吗?在你的程序中TPvtSignature是否是你自己定义的类,<br>我在一个考试系统中对客户端的考生成绩文件进行加密,但是操作系统是98 &nbsp;是否就不能实现非对称的加密<br>另外你的程序能否让我参考一下 &nbsp;谢谢 &nbsp;jimiking@163.com<br><br>最后一段程序是自己写的吗 &nbsp;Decrypt53是什么意思<br><br>
 
pwxwabcd:BlockLen我取的1000<br>我又试了一下,果然用win2000也会出现公钥加密公钥也能解密的情况。明明以前可以的。。郁闷,盼望高手解答。<br>jimiking:Wcrypt2.pas应该是这个单元了。只需要把它加到工程里面就行了。TPvtSignature是我自己定义的类,98好像是不能实现非对称加密。Decrypt53是一次加密53个字节。源于我提的问题:只能够加密大约53个字符的数据,超过长度CryptEncrypt会出错。至今还未解决此问题,因此自己循环解决。
 
能否解释一下为什么 &nbsp;if Ord(Key[1]) = 1 &nbsp; 则是 &nbsp;对称密钥解密<br><br>另外EncryptLen 的取值和意义是什么 ?~如果我借用你的程序实现对称加密 &nbsp;就不需要调用GetGenKey 了吧?· 这时我应该如何获得加密和解密返回的string &nbsp;呢
 
很有难度
 
1。能否解释一下为什么 &nbsp;if Ord(Key[1]) = 1 &nbsp; 则是 &nbsp;对称密钥解密:<br>》》对称密钥加密的密钥第一个字节是1(密钥不是任意的字符串,是要满足一定格式的,要得到满足条件的字符串,参见我以下的过程)<br>2。另外EncryptLen 的取值和意义是什么 ?<br>》》EncryptLen = 53; //公私钥加密的最大字节长度<br>3.如果我借用你的程序实现对称加密 &nbsp;就不需要调用GetGenKey 了吧?<br>》》你加密总是需要一个密钥的,但是在我的函数里面<br>class function TPvtCAPICrypto.Encrypt(const Data, Key: string): string;<br>中的key不是任意格式的字符串都可以的,如果想从一个普通字符串得到加密所需要的key,可以调用我的这个过程:<br>class function TPvtCAPICrypto.MakeKeyFromStr(const AStr: string): string;<br>var<br>&nbsp; hProv: HCRYPTPROV;<br>&nbsp; hHash: HCRYPTHASH;<br>&nbsp; hKey, hXchgKey: HCRYPTKEY;<br>&nbsp; pbKeyBlob: PByte;<br>&nbsp; dwBlobLen: DWORD;<br><br>&nbsp; procedure Init;<br>&nbsp; begin<br>&nbsp; &nbsp; hProv := 0;<br>&nbsp; &nbsp; hHash := 0;<br>&nbsp; &nbsp; hKey := 0;<br>&nbsp; &nbsp; pbKeyBlob := nil;<br>&nbsp; &nbsp; dwBlobLen := 0;<br>&nbsp; end;<br><br>&nbsp; procedure Clear;<br>&nbsp; begin<br>&nbsp; &nbsp; if (dwBlobLen &lt;&gt; 0) and (pbKeyBlob &lt;&gt; nil) then<br>&nbsp; &nbsp; begin<br>&nbsp; &nbsp; &nbsp; FillChar(pbKeyBlob^, dwBlobLen, 0);<br>&nbsp; &nbsp; &nbsp; FreeMem(pbKeyBlob);<br>&nbsp; &nbsp; &nbsp; FillChar(dwBlobLen, Sizeof(dwBlobLen), 0);<br>&nbsp; &nbsp; end;<br>&nbsp; &nbsp; if Boolean(hKey) then<br>&nbsp; &nbsp; &nbsp; CryptDestroyKey(hKey);<br>&nbsp; &nbsp; if Boolean(hHash) then<br>&nbsp; &nbsp; &nbsp; CryptDestroyHash(hHash);<br>&nbsp; &nbsp; if Boolean(hProv) then<br>&nbsp; &nbsp; &nbsp; CryptReleaseContext(hProv, 0);<br>&nbsp; end;<br>begin<br>&nbsp; Init;<br><br>&nbsp; CryptAcquireContextEx(hProv);<br><br>&nbsp; if not CryptCreateHash(hProv, CALG_MD5, 0, 0, @hHash) then //创建哈西对象<br>&nbsp; begin<br>&nbsp; &nbsp; Clear;<br>&nbsp; &nbsp; raise Exception.Create('CryptCreateHash Failed!');<br>&nbsp; end;<br><br>&nbsp; if not CryptHashData(hHash, PByte(PChar(AStr)), Length(AStr), 0) then //创建字符串的哈西值<br>&nbsp; begin<br>&nbsp; &nbsp; Clear;<br>&nbsp; &nbsp; raise Exception.Create('CryptHashData Failed!');<br>&nbsp; end;<br><br>&nbsp; if not CryptDeriveKey(hProv, CALG_RC4, hHash, CRYPT_EXPORTABLE, @hKey) then //从hash对象中分离密钥<br>&nbsp; begin<br>&nbsp; &nbsp; Clear;<br>&nbsp; &nbsp; raise Exception.Create('CryptDeriveKey Failed!');<br>&nbsp; end;<br><br>&nbsp; //==============================导出密钥======================================<br>&nbsp; if not CryptGetUserKey(hProv, AT_KEYEXCHANGE, @hXchgKey) then<br>&nbsp; begin<br>&nbsp; &nbsp; Clear;<br>&nbsp; &nbsp; raise Exception.Create('CryptGetUserKey Failed!');<br>&nbsp; end;<br><br>&nbsp; if not CryptExportKey(hKey, hXchgKey, SIMPLEBLOB, 0, nil,<br>&nbsp; &nbsp; @dwBlobLen) then //得到从密钥盒中导出私有密钥所需空间大小<br>&nbsp; begin<br>&nbsp; &nbsp; Clear;<br>&nbsp; &nbsp; raise Exception.Create('CryptExportKey Failed!');<br>&nbsp; end;<br>&nbsp; try<br>&nbsp; &nbsp; GetMem(pbKeyBlob, dwBlobLen);<br>&nbsp; except<br>&nbsp; &nbsp; on EOutOfMemory do<br>&nbsp; &nbsp; begin<br>&nbsp; &nbsp; &nbsp; Clear;<br>&nbsp; &nbsp; &nbsp; raise Exception.Create('OutOfMemory!');<br>&nbsp; &nbsp; end;<br>&nbsp; end;<br>&nbsp; if not CryptExportKey(hKey, hXchgKey, SIMPLEBLOB, 0, pbKeyBlob,<br>&nbsp; &nbsp; @dwBlobLen) then //从密钥盒中导出私有密钥<br>&nbsp; begin<br>&nbsp; &nbsp; Clear;<br>&nbsp; &nbsp; raise Exception.Create('CryptExportKey Failed!');<br>&nbsp; end;<br><br>&nbsp; SetLength(Result, dwBlobLen);<br>&nbsp; Move(pbKeyBlob^, Pointer(Result)^, dwBlobLen);<br>&nbsp; Clear;<br>end;<br><br>4.这时我应该如何获得加密和解密返回的string &nbsp;呢 &nbsp;<br>》》class function TPvtCAPICrypto.Encrypt(const Data, Key: string): string;<br>》》class function TPvtCAPICrypto.Decrypt(const Data, Key: string): string;<br>》》的返回值就是加密和解密返回的string
 
后退
顶部