0

德尔福 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, Hash , ...) . 和解密 - 获取源字符串的哈希值。

我不知道如何实现它。

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

ps更新已删除*

4

1 回答 1

4

我想您正在尝试一次性加密和散列明文数据?如果是,那么首先您必须创建一个 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 项目 (JWA),因为它包含几乎所有 Windows API 和类型(包括 Crypt API)的翻译。您可以将其包含在您的项目中。
  • 伪代码需要对 API 错误处理进行一些改进。
  • bHash 包含数据明文版本的哈希值。请注意,散列(以及加密)是面向字节的操作。那就是它不“理解”字符串编码。视觉上用 UTF16、UTF8 和 ASCII 编码的相同字符串值会有不同的字节表示,因此会有不同的 Hash 值。在散列/加密时记住编码。

顺便说一句,MSDN 中的 CryptEncrypt API 记录了这种行为

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

更新

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

解密后 H2 将是解密数据的哈希值(明文值)。

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

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

于 2013-05-06T13:52:29.273 回答