CryptEncrypt获取哈希数据

时间:2013-05-06 10:37:23

标签: delphi

Delphi Xe4。 使用函数Win CryptoAPI - CryptEncrypt& CryptDecrypt。

http://msdn.microsoft.com/en-us/library/windows/desktop/aa379924(v=vs.85).aspx(Enc) http://msdn.microsoft.com/en-us/library/windows/desktop/aa379913(v=vs.85).aspx(DeCr)

一切正常,加密和解密字符串。 但是我看到所有的例子都没有使用选项“HCRYPTHASH hHash”而且是0。 而且我需要加密而不是加密的字符串发出它的哈希值(不单独计算,使用CryptEncrypt(hProv,哈希,...)。并且解密 - 获取源字符串的哈希值。< / p>

我不知道如何实现它。

如果有人在Delphi中展示一个例子,我将不胜感激。

P.S。更新已删除 *

1 个答案:

答案 0 :(得分:3)

我想你正试图加密&amp;哈希明文数据一次通过? 如果是,那么首先你必须创建一个Hash对象并将它的句柄传递给CryptEncrypt API。然后使用CryptGetHashParam检索哈希。

这是一个伪代码(未经过测试,但会让您了解如何继续):

procedure doSomeEncryption()
var
  HASHOBJ: HCRYPTHASH;
  hProv: HCRYPTPROV;
  bHash: tBytes;
  dwHashBytes: DWORD;
begin
  if not CryptAcquireContext(@hProv, nil, nil, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT) then
    raiseLastOsError;

  if not CryptCreateHash(hProv, CALG_SHA, 0, 0, @HASHOBJ) then
    raiseLastOsError;

  // Your encrypt stuff here
  CryptEncrypt(yourHKey, HASHOBJ, ...) // 

  setLength(bHash, 255);  // Allocate the buffer
  if CryptGetHashParam(HASHOBJ, HP_HASHVAL, @bHash[0], @dwHashBytes, 0) then
  begin
    setLength(bHash, dwHashBytes);  // bHash now contains the hash bytes
  end
  else
    setLength(bHash, 0);

  //  Release HASHOBJ
  CryptDestroyHash(HASHOBJ);

  //  Release Provider Context
  CryptReleaseContext(hProv, 0);

end;
  • 在我的伪代码中,我依赖Jedi API project (JWA),因为它包含几乎所有Windows API和类型(包括Crypt API)的翻译。您可以将其包含在项目中。
  • 伪代码需要对API错误处理进行一些改进。
  • bHash包含数据明文版本的哈希值。 请注意 Hashing(以及加密)是面向字节的操作。那就是它不“理解”字符串编码。 在视觉上,以UTF16,UTF8和ASCII编码的相同字符串值将具有不同的字节表示,因此它将具有不同的哈希值。请记住Hashing / Encrypting时的编码。

BTW this behavior is documented for CryptEncrypt API in MSDN

  

hHash [in]哈希对象的句柄。如果要对数据进行哈希处理   同时加密,可以传入哈希对象的句柄   hHash参数。使用明文更新哈希值   传入。在生成签名和加密时,此选项很有用   文本。在调用CryptEncrypt之前,应用程序必须获取一个   通过调用CryptCreateHash函数来处理散列对象。   加密完成后,可以通过获取哈希值   使用CryptGetHashParam函数,或哈希可以通过签名   使用CryptSignHash函数。如果没有哈希要做,这个   参数必须为NULL。

<强>更新

加密后H1将是加密前数据的哈希值,即H1 = HASH('aaa')

解密后H2将是解密数据的散列(明文值)。

因此,在您的情况下,如果解密成功,则H2将等于HASH('aaa'),即H1 = H2。

H1&amp; H2是检查数据完整性。通常,Decrypt函数不会告诉您解密是否成功。如果您尝试使用错误的密码解密数据,则会收到垃圾字节。所以有问题 - 如何知道解密是否成功?一种方法是使用输入和输出上的数据哈希。如果匹配 - 您的解密成功。如果哈希值不同,那么由于密码错误(例如),解密可能会无声地失败。 CryptEncrypt / CryptDecrypt提供了一种方便的方法来在一次操作中获取这些哈希值,而不是单独散列它。