如何使用Delphi的标准函数对ASCII字符串进行单向散列?

如何使用Delphi的标准函数对ASCII字符串进行单向散列?,delphi,encryption,Delphi,Encryption,我是Delphi新手。我正在尝试对ASCII字符串进行单向散列。是否有任何方法可以在不向项目中添加Indy或任何其他加密库的情况下,仅通过标准函数对ASCII字符串进行加密 如果有任何方法可以使用windows API,我该怎么做 如果可能的话,请给我举个例子。您可以使用Windows加密库来实现这一点。例如,这里有一个计算MD5哈希的最小单位: unit MD5; interface uses SysUtils, Math, Windows, Classes; type TMD5

我是Delphi新手。我正在尝试对ASCII字符串进行单向散列。是否有任何方法可以在不向项目中添加Indy或任何其他加密库的情况下,仅通过标准函数对ASCII字符串进行加密

如果有任何方法可以使用windows API,我该怎么做


如果可能的话,请给我举个例子。

您可以使用Windows加密库来实现这一点。例如,这里有一个计算MD5哈希的最小单位:

unit MD5;

interface

uses
  SysUtils, Math, Windows, Classes;

type
  TMD5Hash = array [0..15] of Byte;

function MD5Hash(Stream: TStream): TMD5Hash; overload;
function MD5Hash(const Bytes: TBytes): TMD5Hash; overload;
function MD5Hash(const Str: RawByteString): TMD5Hash; overload;
function MD5ToString(const Hash: TMD5Hash): string;

implementation

type
  HCRYPTPROV = type NativeUInt;
  HCRYPTKEY = type NativeUInt;
  HCRYPTHASH = type NativeUInt;
  ALG_ID = Cardinal;

const
  PROV_RSA_FULL = 1;
  CRYPT_VERIFYCONTEXT = $F0000000;
  ALG_CLASS_HASH = 4 shl 13;
  ALG_TYPE_ANY = 0;
  ALG_SID_MD5 = 3;
  CALG_MD5 = ALG_CLASS_HASH or ALG_TYPE_ANY or ALG_SID_MD5;
  HP_HASHVAL = $0002;

function CryptAcquireContextW(
  out phProv: HCRYPTPROV;
  pszContainer: PWideChar;
  pszProvider: PWideChar;
  dwProvType: DWORD;
  dwFlags: DWORD
): BOOL; stdcall; external 'Advapi32.dll';

function CryptReleaseContext(
  hProv: HCRYPTPROV;
  dwFlags: DWORD
): BOOL; stdcall; external 'Advapi32.dll';

function CryptCreateHash(
  hProv: HCRYPTPROV;
  Algid: ALG_ID;
  hKey: HCRYPTKEY;
  dwFlags: DWORD;
  out phHash: HCRYPTHASH
): BOOL; stdcall; external 'Advapi32.dll';

function CryptDestroyHash(
  hHash: HCRYPTHASH
): BOOL; stdcall; external 'Advapi32.dll';

function CryptHashData(
  hHash: HCRYPTHASH;
  pbData: Pointer;
  dwDataLen: DWORD;
  dwFlags: DWORD
): BOOL; stdcall; external 'Advapi32.dll';

function CryptGetHashParam(
  hHash: HCRYPTHASH;
  dwParam: DWORD;
  pbData: Pointer;
  var pdwDataLen: DWORD;
  dwFlags: DWORD
): BOOL; stdcall; external 'Advapi32.dll';

function MD5Hash(Stream: TStream): TMD5Hash;
const
  BuffSize = 1024;
var
  hProv: HCRYPTPROV;
  hHash: HCRYPTHASH;
  Buff: array [0..BuffSize] of Byte;
  BytesLeft: Int64;
  BytesToRead: Integer;
  HashSize: DWORD;
begin
  Win32Check(CryptAcquireContextW(hProv, nil, nil, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT));
  try
    Win32Check(CryptCreateHash(hProv, CALG_MD5, 0, 0, hHash));
    try
      BytesLeft := Stream.Size-Stream.Position;
      while BytesLeft>0 do begin
        BytesToRead := Min(BytesLeft, BuffSize);
        Stream.ReadBuffer(Buff, BytesToRead);
        Win32Check(CryptHashData(hHash, @Buff, BytesToRead, 0));
        dec(BytesLeft, BytesToRead);
      end;
      HashSize := SizeOf(Result);
      Win32Check(CryptGetHashParam(hHash, HP_HASHVAL, @Result, HashSize, 0));
    finally
      Win32Check(CryptDestroyHash(hHash));
    end;
  finally
    Win32Check(CryptReleaseContext(hProv, 0));
  end;
end;

function MD5Hash(const Str: RawByteString): TMD5Hash;
var
  Stream: TStringStream;
begin
  Stream := TStringStream.Create(Str);
  try
    Result := MD5Hash(Stream);
  finally
    Stream.Free;
  end;
end;

function MD5Hash(const Bytes: TBytes): TMD5Hash;
var
  Stream: TBytesStream;
begin
  Stream := TBytesStream.Create(Bytes);
  try
    Result := MD5Hash(Stream);
  finally
    Stream.Free;
  end;
end;

function MD5ToString(const Hash: TMD5Hash): string;
begin
  SetLength(Result, SizeOf(Hash)*2);
  BinToHex(Pointer(@Hash)^, PChar(Result), SizeOf(Hash));
end;

end.

Zeid,我不相信它是加密安全的,但是Delphi在System.Generics.Defaults单元中有一个名为BobJenkinsHash(!!!)的散列函数。它也不是用户友好的(要求您提供要传递给它的内存块的长度(大小?)并返回一个整数值。但是,如果您的要求是1)Delphi,2)没有第三方库,3)您不想自己实现另一个哈希,我相信这是您唯一的选择

function BobJenkinsHash(const Data; Len, InitData: Integer): Integer;

您需要将字符串作为第一个参数传递,将字符串长度*字符大小作为第二个参数传递,并将任何其他数字(通常为零)作为最后一个参数传递

使用第三方库有什么问题?此外,印地也有德尔福。提示:第三方库只是您不必自己编写的代码。散列非常简单。有很多这样的图书馆。你找过了吗?你试过什么?散列的要求是什么?询问代码的问题应该表明对要解决的问题的最低理解。@alcalde问题是有很多经过良好测试的简单C代码来实现哈希。将其编译为对象并将其链接起来并不需要太多。甚至可以翻译成德尔福。但我总是编译已知可以工作的代码,而不是翻译。请参阅Delphi MD5 library
MessageDigest_5.pas对ansistring进行哈希处理的示例,该库自2009年2月随Delphi提供。我注意到XE3中的源是偶然丢失的。我必须说我对这里的否决票感到非常惊讶。我认为这是一个有用的演示,演示了如何以最少的努力获得非常灵活的MD5。我看不出这一点如何能轻易得到改善。我猜否决票意味着我做错了什么,我真的想纠正它。我可以看到这个答案将来会被提及。这应该是固定的。开车经过的选民。问题本身是+2/-2。我给了你一票。@DavidHeffernan对我来说“最小的努力”就是把它建进去。:-)老实说,看起来您花了很多精力,包括翻译函数头。我不知道为什么会投反对票。@alcalde好吧,我说的是最少的,而不是不太多!;-)是的,花了我30分钟左右。但这是MSDN示例的直接翻译。这是一个非常干净且经过深思熟虑的库,因此标题翻译很简单。我不喜欢使用绝地单位,因为根据我的经验,他们有太多额外的负担。@LURD这些标准哈希很容易实现。我想我会尽量为你写一些简单的、便于携带的东西。这确实是个好答案,但大卫的答案对我更有用。再次感谢你的时间和分享。