{Copyright:      Hagen Reddmann  mailto:HaReddmann@AOL.COM
 Author:         Hagen Reddmann
 Remarks:        freeware, but this Copyright must be included
 known Problems: none
 Version:        3.0,  Part I from Delphi Encryption Compendium (DEC Part I)
                 Delphi 2-4, BCB 3-4
 Description:    Include Objects for calculating various Hash's (fingerprints)
                 used Hash-Algorithm:
                   MD4, MD5, SHA, SHA1, RipeMD

 Comments:       for Designer's, the Buffer from Method Transform must be readonly

 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

Digest size, Result from DigestKeySize and Datasize for Digest
   MD4         16 byte   128 bit   4x Integer
   MD5         16 byte   128 bit   4x Integer
   SHA         20 byte   160 bit   5x Integer
   SHA1        20 byte   160 bit   5x Integer
   RMD160      20 byte   160 bit   5x Integer
}

{$IFNDEF CLR}

{$I Dac.inc}

unit CRHash;
{$ENDIF}

interface
{$A+,Q-,R-,Y-}
uses
{$IFDEF CLR}
  System.Runtime.InteropServices,
{$ELSE}
  CLRClasses,
{$ENDIF}
  SysUtils, CRTypes, CRFunctions, CRDECUtil, CRHashAlgorithm;

type
{all Hash Classes}
  THash_MD4             = class;
  THash_MD5             = class;
  THash_RipeMD160       = class;
  THash_SHA             = class;
  THash_SHA1            = class;

  THash_MD4 = class(THashAlgorithm)
  private
    FCount: LongWord;
    FBuffer: array[0..15] of LongWord;
    FDigest: array[0..9] of LongWord;
  {$IFDEF CLR}
    FBufferGC: GCHandle;
  {$ENDIF}

  protected
    procedure Transform({$IFDEF CLR}const{$ENDIF} Buffer: TIntArray); virtual;

  public
    constructor Create; override;
    destructor Destroy; override;

    class function DigestKeySize: Integer; override;
    procedure Init; override;
    procedure Done; override;
    procedure Calc(Data: IntPtr; DataSize: Integer); overload; override;
    procedure Calc(const Data: TBytes; Offset: Integer; DataSize: Integer); overload; override;
    function DigestKey: TIntArray; override;
  end;

  THash_MD5 = class(THash_MD4)
  protected
    procedure Transform({$IFDEF CLR}const{$ENDIF} Buffer: TIntArray); override;
  end;

  THash_RipeMD160 = class(THash_MD4)
  protected
    procedure Transform({$IFDEF CLR}const{$ENDIF} Buffer: TIntArray); override;
  public
    class function DigestKeySize: Integer; override;
  end;

  THash_SHA = class(THash_RipeMD160)
  protected
    FRotate: Boolean;
    procedure Transform({$IFDEF CLR}const{$ENDIF} Buffer: TIntArray); override;
  public
    procedure Done; override;
  end;

  THash_SHA1 = class(THash_SHA)
  public
    procedure Init; override;
  end;

implementation

const
  NullArray: array[0..15] of LongWord = (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);

constructor THash_MD4.Create;
begin
  inherited;

{$IFDEF CLR}
  FBufferGC := GCHandle.Alloc(FBuffer, GCHandleType.Pinned);
{$ENDIF}
end;

destructor THash_MD4.Destroy;
begin
{$IFDEF CLR}
  FBufferGC.Free;
{$ENDIF}

  inherited;
end;

procedure THash_MD4.Transform({$IFDEF CLR}const{$ENDIF} Buffer: TIntArray);
{calculate the Digest, fast}
var
  A, B, C, D: LongWord;
begin
  A := FDigest[0];
  B := FDigest[1];
  C := FDigest[2];
  D := FDigest[3];

  Inc(A, Buffer[ 0] + (B and C or not B and D)); A := A shl  3 or A shr 29;
  Inc(D, Buffer[ 1] + (A and B or not A and C)); D := D shl  7 or D shr 25;
  Inc(C, Buffer[ 2] + (D and A or not D and B)); C := C shl 11 or C shr 21;
  Inc(B, Buffer[ 3] + (C and D or not C and A)); B := B shl 19 or B shr 13;
  Inc(A, Buffer[ 4] + (B and C or not B and D)); A := A shl  3 or A shr 29;
  Inc(D, Buffer[ 5] + (A and B or not A and C)); D := D shl  7 or D shr 25;
  Inc(C, Buffer[ 6] + (D and A or not D and B)); C := C shl 11 or C shr 21;
  Inc(B, Buffer[ 7] + (C and D or not C and A)); B := B shl 19 or B shr 13;
  Inc(A, Buffer[ 8] + (B and C or not B and D)); A := A shl  3 or A shr 29;
  Inc(D, Buffer[ 9] + (A and B or not A and C)); D := D shl  7 or D shr 25;
  Inc(C, Buffer[10] + (D and A or not D and B)); C := C shl 11 or C shr 21;
  Inc(B, Buffer[11] + (C and D or not C and A)); B := B shl 19 or B shr 13;
  Inc(A, Buffer[12] + (B and C or not B and D)); A := A shl  3 or A shr 29;
  Inc(D, Buffer[13] + (A and B or not A and C)); D := D shl  7 or D shr 25;
  Inc(C, Buffer[14] + (D and A or not D and B)); C := C shl 11 or C shr 21;
  Inc(B, Buffer[15] + (C and D or not C and A)); B := B shl 19 or B shr 13;

  Inc(A, Buffer[ 0] + $5A827999 + (B and C or B and D or C and D)); A := A shl  3 or A shr 29;
  Inc(D, Buffer[ 4] + $5A827999 + (A and B or A and C or B and C)); D := D shl  5 or D shr 27;
  Inc(C, Buffer[ 8] + $5A827999 + (D and A or D and B or A and B)); C := C shl  9 or C shr 23;
  Inc(B, Buffer[12] + $5A827999 + (C and D or C and A or D and A)); B := B shl 13 or B shr 19;
  Inc(A, Buffer[ 1] + $5A827999 + (B and C or B and D or C and D)); A := A shl  3 or A shr 29;
  Inc(D, Buffer[ 5] + $5A827999 + (A and B or A and C or B and C)); D := D shl  5 or D shr 27;
  Inc(C, Buffer[ 9] + $5A827999 + (D and A or D and B or A and B)); C := C shl  9 or C shr 23;
  Inc(B, Buffer[13] + $5A827999 + (C and D or C and A or D and A)); B := B shl 13 or B shr 19;
  Inc(A, Buffer[ 2] + $5A827999 + (B and C or B and D or C and D)); A := A shl  3 or A shr 29;
  Inc(D, Buffer[ 6] + $5A827999 + (A and B or A and C or B and C)); D := D shl  5 or D shr 27;
  Inc(C, Buffer[10] + $5A827999 + (D and A or D and B or A and B)); C := C shl  9 or C shr 23;
  Inc(B, Buffer[14] + $5A827999 + (C and D or C and A or D and A)); B := B shl 13 or B shr 19;
  Inc(A, Buffer[ 3] + $5A827999 + (B and C or B and D or C and D)); A := A shl  3 or A shr 29;
  Inc(D, Buffer[ 7] + $5A827999 + (A and B or A and C or B and C)); D := D shl  5 or D shr 27;
  Inc(C, Buffer[11] + $5A827999 + (D and A or D and B or A and B)); C := C shl  9 or C shr 23;
  Inc(B, Buffer[15] + $5A827999 + (C and D or C and A or D and A)); B := B shl 13 or B shr 19;

  Inc(A, Buffer[ 0] + $6ED9EBA1 + (B xor C xor D)); A := A shl  3 or A shr 29;
  Inc(D, Buffer[ 8] + $6ED9EBA1 + (A xor B xor C)); D := D shl  9 or D shr 23;
  Inc(C, Buffer[ 4] + $6ED9EBA1 + (D xor A xor B)); C := C shl 11 or C shr 21;
  Inc(B, Buffer[12] + $6ED9EBA1 + (C xor D xor A)); B := B shl 15 or B shr 17;
  Inc(A, Buffer[ 2] + $6ED9EBA1 + (B xor C xor D)); A := A shl  3 or A shr 29;
  Inc(D, Buffer[10] + $6ED9EBA1 + (A xor B xor C)); D := D shl  9 or D shr 23;
  Inc(C, Buffer[ 6] + $6ED9EBA1 + (D xor A xor B)); C := C shl 11 or C shr 21;
  Inc(B, Buffer[14] + $6ED9EBA1 + (C xor D xor A)); B := B shl 15 or B shr 17;
  Inc(A, Buffer[ 1] + $6ED9EBA1 + (B xor C xor D)); A := A shl  3 or A shr 29;
  Inc(D, Buffer[ 9] + $6ED9EBA1 + (A xor B xor C)); D := D shl  9 or D shr 23;
  Inc(C, Buffer[ 5] + $6ED9EBA1 + (D xor A xor B)); C := C shl 11 or C shr 21;
  Inc(B, Buffer[13] + $6ED9EBA1 + (C xor D xor A)); B := B shl 15 or B shr 17;
  Inc(A, Buffer[ 3] + $6ED9EBA1 + (B xor C xor D)); A := A shl  3 or A shr 29;
  Inc(D, Buffer[11] + $6ED9EBA1 + (A xor B xor C)); D := D shl  9 or D shr 23;
  Inc(C, Buffer[ 7] + $6ED9EBA1 + (D xor A xor B)); C := C shl 11 or C shr 21;
  Inc(B, Buffer[15] + $6ED9EBA1 + (C xor D xor A)); B := B shl 15 or B shr 17;

  Inc(FDigest[0], A);
  Inc(FDigest[1], B);
  Inc(FDigest[2], C);
  Inc(FDigest[3], D);
end;

class function THash_MD4.DigestKeySize: Integer;
begin
  Result := 16;
end;

function THash_MD4.DigestKey: TIntArray;
begin
  Result := {$IFNDEF CLR}@{$ENDIF}FDigest;
end;

procedure THash_MD4.Init;
begin
{$IFNDEF CLR}
  FillChar(FBuffer, SizeOf(FBuffer), 0);
{$ELSE}
  &Array.Clear(FBuffer, 0, Length(FBuffer));
{$ENDIF}

{all Descend from MD4 (MD4, SHA1, RipeMD) use this Init-Key}
  FDigest[0] := $67452301;
  FDigest[1] := $EFCDAB89;
  FDigest[2] := $98BADCFE;
  FDigest[3] := $10325476;
  FDigest[4] := $C3D2E1F0;
{for RMD320}
  FDigest[5] := $76543210;
  FDigest[6] := $FEDCBA98;
  FDigest[7] := $89ABCDEF;
  FDigest[8] := $01234567;
  FDigest[9] := $3C2D1E0F;
  FCount := 0;
  Protect(True);
end;

procedure THash_MD4.Done;
var
  I: Integer;
  S: Int64;
begin
  I := FCount and $3F;
  Buffer.SetByte({$IFNDEF CLR}@{$ENDIF}FBuffer, I, $80);
  Inc(I);
  if I > 64 - 8 then
  begin
    Buffer.BlockCopy(NullArray, 0, FBuffer, I, 64 - I); // Fill 0
    Transform({$IFNDEF CLR}@{$ENDIF}FBuffer);
    I := 0;
  end;
  Buffer.BlockCopy(NullArray, 0, FBuffer, I, 64 - I);
  S := UInt64(FCount) shl 3;
  FBuffer[16 - 2] := Longword(S);
  FBuffer[16 - 1] := Longword(S shr 32);

  Transform({$IFNDEF CLR}@{$ENDIF}FBuffer);

{$IFNDEF CLR}
  FillChar(FBuffer, SizeOf(FBuffer), 0);
{$ELSE}
  &Array.Clear(FBuffer, 0, Length(FBuffer));
{$ENDIF}
  Protect(False);
end;

procedure THash_MD4.Calc(Data: IntPtr; DataSize: Integer);
var
  Index: Integer;
{$IFDEF CLR}
  Pos: Integer;
{$ELSE}
  Buf: TIntArray;
{$ENDIF}
begin
  if DataSize <= 0 then Exit;

  Index := FCount and $3F;
  Inc(FCount, DataSize);
  if Index > 0 then
  begin
    if DataSize < 64 - Index then
    begin
      CopyBuffer(Data, PtrOffset({$IFDEF CLR}Marshal.UnsafeAddrOfPinnedArrayElement(FBuffer, 0){$ELSE}@FBuffer{$ENDIF}, Index), DataSize);
      Exit;
    end;
    CopyBuffer(Data, PtrOffset({$IFDEF CLR}Marshal.UnsafeAddrOfPinnedArrayElement(FBuffer, 0){$ELSE}@FBuffer{$ENDIF}, Index), 64 - Index);
    Transform({$IFNDEF CLR}@{$ENDIF}FBuffer);
    Index := 64 - Index;
    Dec(DataSize, Index);
  end;

{$IFDEF CLR}
  Pos := Index;
{$ELSE}
  Buf := PtrOffset(Data, Index);
{$ENDIF}

  Inc(Index, DataSize and not $3F);
  while DataSize >= 64 do
  begin
  {$IFDEF CLR}
    CopyBuffer(PtrOffset(Data, Pos), {$IFDEF CLR}Marshal.UnsafeAddrOfPinnedArrayElement(FBuffer, 0){$ELSE}@FBuffer{$ENDIF}, 64);
  {$ENDIF}

    Transform({$IFDEF CLR}FBuffer{$ELSE}Buf{$ENDIF});
    Inc({$IFDEF CLR}Pos{$ELSE}PAnsiChar(Buf){$ENDIF}, 64);
    Dec(DataSize, 64);
  end;
  CopyBuffer(PtrOffset(Data, Index), {$IFDEF CLR}Marshal.UnsafeAddrOfPinnedArrayElement(FBuffer, 0){$ELSE}@FBuffer{$ENDIF}, DataSize);
end;

procedure THash_MD4.Calc(const Data: TBytes; Offset: Integer; DataSize: Integer);
var
  Index: Integer;
{$IFDEF CLR}
  Pos: Integer;
{$ELSE}
  Buf: TIntArray;
{$ENDIF}
begin
  if DataSize <= 0 then Exit;

  Index := FCount and $3F;
  Inc(FCount, DataSize);
  if Index > 0 then
  begin
    if DataSize < 64 - Index then
    begin
      Buffer.BlockCopy(Data, Offset, FBuffer, Index, DataSize);
      Exit;
    end;
    Buffer.BlockCopy(Data, Offset, FBuffer, Index, 64 - Index);
    Transform({$IFNDEF CLR}@{$ENDIF}FBuffer);
    Index := 64 - Index;
    Dec(DataSize, Index);
  end;

{$IFDEF CLR}
  Pos := Index + Offset;
{$ELSE}
  if DataSize >= 64 then
    Buf := @Data[Index + Offset]
  else
    Buf := nil;
{$ENDIF}

  Inc(Index, DataSize and not $3F);
  while DataSize >= 64 do
  begin
  {$IFDEF CLR}
    Buffer.BlockCopy(Data, Pos, FBuffer, 0, 64);
  {$ENDIF}

    Transform({$IFDEF CLR}FBuffer{$ELSE}Buf{$ENDIF});
    Inc({$IFDEF CLR}Pos{$ELSE}PAnsiChar(Buf){$ENDIF}, 64);
    Dec(DataSize, 64);
  end;
  Buffer.BlockCopy(Data, Index + Offset, FBuffer, 0, DataSize);
end;

procedure THash_MD5.Transform({$IFDEF CLR}const{$ENDIF} Buffer: TIntArray);
var
  A, B, C, D: LongWord;
begin
  A := FDigest[0];
  B := FDigest[1];
  C := FDigest[2];
  D := FDigest[3];

  Inc(A, Buffer[ 0] + $D76AA478 + (D xor (B and (C xor D)))); A := A shl  7 or A shr 25 + B;
  Inc(D, Buffer[ 1] + $E8C7B756 + (C xor (A and (B xor C)))); D := D shl 12 or D shr 20 + A;
  Inc(C, Buffer[ 2] + $242070DB + (B xor (D and (A xor B)))); C := C shl 17 or C shr 15 + D;
  Inc(B, Buffer[ 3] + $C1BDCEEE + (A xor (C and (D xor A)))); B := B shl 22 or B shr 10 + C;
  Inc(A, Buffer[ 4] + $F57C0FAF + (D xor (B and (C xor D)))); A := A shl  7 or A shr 25 + B;
  Inc(D, Buffer[ 5] + $4787C62A + (C xor (A and (B xor C)))); D := D shl 12 or D shr 20 + A;
  Inc(C, Buffer[ 6] + $A8304613 + (B xor (D and (A xor B)))); C := C shl 17 or C shr 15 + D;
  Inc(B, Buffer[ 7] + $FD469501 + (A xor (C and (D xor A)))); B := B shl 22 or B shr 10 + C;
  Inc(A, Buffer[ 8] + $698098D8 + (D xor (B and (C xor D)))); A := A shl  7 or A shr 25 + B;
  Inc(D, Buffer[ 9] + $8B44F7AF + (C xor (A and (B xor C)))); D := D shl 12 or D shr 20 + A;
  Inc(C, Buffer[10] + $FFFF5BB1 + (B xor (D and (A xor B)))); C := C shl 17 or C shr 15 + D;
  Inc(B, Buffer[11] + $895CD7BE + (A xor (C and (D xor A)))); B := B shl 22 or B shr 10 + C;
  Inc(A, Buffer[12] + $6B901122 + (D xor (B and (C xor D)))); A := A shl  7 or A shr 25 + B;
  Inc(D, Buffer[13] + $FD987193 + (C xor (A and (B xor C)))); D := D shl 12 or D shr 20 + A;
  Inc(C, Buffer[14] + $A679438E + (B xor (D and (A xor B)))); C := C shl 17 or C shr 15 + D;
  Inc(B, Buffer[15] + $49B40821 + (A xor (C and (D xor A)))); B := B shl 22 or B shr 10 + C;

  Inc(A, Buffer[ 1] + $F61E2562 + (C xor (D and (B xor C)))); A := A shl  5 or A shr 27 + B;
  Inc(D, Buffer[ 6] + $C040B340 + (B xor (C and (A xor B)))); D := D shl  9 or D shr 23 + A;
  Inc(C, Buffer[11] + $265E5A51 + (A xor (B and (D xor A)))); C := C shl 14 or C shr 18 + D;
  Inc(B, Buffer[ 0] + $E9B6C7AA + (D xor (A and (C xor D)))); B := B shl 20 or B shr 12 + C;
  Inc(A, Buffer[ 5] + $D62F105D + (C xor (D and (B xor C)))); A := A shl  5 or A shr 27 + B;
  Inc(D, Buffer[10] + $02441453 + (B xor (C and (A xor B)))); D := D shl  9 or D shr 23 + A;
  Inc(C, Buffer[15] + $D8A1E681 + (A xor (B and (D xor A)))); C := C shl 14 or C shr 18 + D;
  Inc(B, Buffer[ 4] + $E7D3FBC8 + (D xor (A and (C xor D)))); B := B shl 20 or B shr 12 + C;
  Inc(A, Buffer[ 9] + $21E1CDE6 + (C xor (D and (B xor C)))); A := A shl  5 or A shr 27 + B;
  Inc(D, Buffer[14] + $C33707D6 + (B xor (C and (A xor B)))); D := D shl  9 or D shr 23 + A;
  Inc(C, Buffer[ 3] + $F4D50D87 + (A xor (B and (D xor A)))); C := C shl 14 or C shr 18 + D;
  Inc(B, Buffer[ 8] + $455A14ED + (D xor (A and (C xor D)))); B := B shl 20 or B shr 12 + C;
  Inc(A, Buffer[13] + $A9E3E905 + (C xor (D and (B xor C)))); A := A shl  5 or A shr 27 + B;
  Inc(D, Buffer[ 2] + $FCEFA3F8 + (B xor (C and (A xor B)))); D := D shl  9 or D shr 23 + A;
  Inc(C, Buffer[ 7] + $676F02D9 + (A xor (B and (D xor A)))); C := C shl 14 or C shr 18 + D;
  Inc(B, Buffer[12] + $8D2A4C8A + (D xor (A and (C xor D)))); B := B shl 20 or B shr 12 + C;

  Inc(A, Buffer[ 5] + $FFFA3942 + (B xor C xor D)); A := A shl  4 or A shr 28 + B;
  Inc(D, Buffer[ 8] + $8771F681 + (A xor B xor C)); D := D shl 11 or D shr 21 + A;
  Inc(C, Buffer[11] + $6D9D6122 + (D xor A xor B)); C := C shl 16 or C shr 16 + D;
  Inc(B, Buffer[14] + $FDE5380C + (C xor D xor A)); B := B shl 23 or B shr  9 + C;
  Inc(A, Buffer[ 1] + $A4BEEA44 + (B xor C xor D)); A := A shl  4 or A shr 28 + B;
  Inc(D, Buffer[ 4] + $4BDECFA9 + (A xor B xor C)); D := D shl 11 or D shr 21 + A;
  Inc(C, Buffer[ 7] + $F6BB4B60 + (D xor A xor B)); C := C shl 16 or C shr 16 + D;
  Inc(B, Buffer[10] + $BEBFBC70 + (C xor D xor A)); B := B shl 23 or B shr  9 + C;
  Inc(A, Buffer[13] + $289B7EC6 + (B xor C xor D)); A := A shl  4 or A shr 28 + B;
  Inc(D, Buffer[ 0] + $EAA127FA + (A xor B xor C)); D := D shl 11 or D shr 21 + A;
  Inc(C, Buffer[ 3] + $D4EF3085 + (D xor A xor B)); C := C shl 16 or C shr 16 + D;
  Inc(B, Buffer[ 6] + $04881D05 + (C xor D xor A)); B := B shl 23 or B shr  9 + C;
  Inc(A, Buffer[ 9] + $D9D4D039 + (B xor C xor D)); A := A shl  4 or A shr 28 + B;
  Inc(D, Buffer[12] + $E6DB99E5 + (A xor B xor C)); D := D shl 11 or D shr 21 + A;
  Inc(C, Buffer[15] + $1FA27CF8 + (D xor A xor B)); C := C shl 16 or C shr 16 + D;
  Inc(B, Buffer[ 2] + $C4AC5665 + (C xor D xor A)); B := B shl 23 or B shr  9 + C;

  Inc(A, Buffer[ 0] + $F4292244 + (C xor (B or not D))); A := A shl  6 or A shr 26 + B;
  Inc(D, Buffer[ 7] + $432AFF97 + (B xor (A or not C))); D := D shl 10 or D shr 22 + A;
  Inc(C, Buffer[14] + $AB9423A7 + (A xor (D or not B))); C := C shl 15 or C shr 17 + D;
  Inc(B, Buffer[ 5] + $FC93A039 + (D xor (C or not A))); B := B shl 21 or B shr 11 + C;
  Inc(A, Buffer[12] + $655B59C3 + (C xor (B or not D))); A := A shl  6 or A shr 26 + B;
  Inc(D, Buffer[ 3] + $8F0CCC92 + (B xor (A or not C))); D := D shl 10 or D shr 22 + A;
  Inc(C, Buffer[10] + $FFEFF47D + (A xor (D or not B))); C := C shl 15 or C shr 17 + D;
  Inc(B, Buffer[ 1] + $85845DD1 + (D xor (C or not A))); B := B shl 21 or B shr 11 + C;
  Inc(A, Buffer[ 8] + $6FA87E4F + (C xor (B or not D))); A := A shl  6 or A shr 26 + B;
  Inc(D, Buffer[15] + $FE2CE6E0 + (B xor (A or not C))); D := D shl 10 or D shr 22 + A;
  Inc(C, Buffer[ 6] + $A3014314 + (A xor (D or not B))); C := C shl 15 or C shr 17 + D;
  Inc(B, Buffer[13] + $4E0811A1 + (D xor (C or not A))); B := B shl 21 or B shr 11 + C;
  Inc(A, Buffer[ 4] + $F7537E82 + (C xor (B or not D))); A := A shl  6 or A shr 26 + B;
  Inc(D, Buffer[11] + $BD3AF235 + (B xor (A or not C))); D := D shl 10 or D shr 22 + A;
  Inc(C, Buffer[ 2] + $2AD7D2BB + (A xor (D or not B))); C := C shl 15 or C shr 17 + D;
  Inc(B, Buffer[ 9] + $EB86D391 + (D xor (C or not A))); B := B shl 21 or B shr 11 + C;

  Inc(FDigest[0], A);
  Inc(FDigest[1], B);
  Inc(FDigest[2], C);
  Inc(FDigest[3], D);
end;

procedure THash_RipeMD160.Transform({$IFDEF CLR}const{$ENDIF} Buffer: TIntArray);
var
  A1, B1, C1, D1, E1: LongWord;
  A, B, C, D, E: LongWord;
begin
  A := FDigest[0];
  B := FDigest[1];
  C := FDigest[2];
  D := FDigest[3];
  E := FDigest[4];

  Inc(A, Buffer[ 0] + (B xor C xor D)); A := A shl 11 or A shr 21 + E; C := C shl 10 or C shr 22;
  Inc(E, Buffer[ 1] + (A xor B xor C)); E := E shl 14 or E shr 18 + D; B := B shl 10 or B shr 22;
  Inc(D, Buffer[ 2] + (E xor A xor B)); D := D shl 15 or D shr 17 + C; A := A shl 10 or A shr 22;
  Inc(C, Buffer[ 3] + (D xor E xor A)); C := C shl 12 or C shr 20 + B; E := E shl 10 or E shr 22;
  Inc(B, Buffer[ 4] + (C xor D xor E)); B := B shl  5 or B shr 27 + A; D := D shl 10 or D shr 22;
  Inc(A, Buffer[ 5] + (B xor C xor D)); A := A shl  8 or A shr 24 + E; C := C shl 10 or C shr 22;
  Inc(E, Buffer[ 6] + (A xor B xor C)); E := E shl  7 or E shr 25 + D; B := B shl 10 or B shr 22;
  Inc(D, Buffer[ 7] + (E xor A xor B)); D := D shl  9 or D shr 23 + C; A := A shl 10 or A shr 22;
  Inc(C, Buffer[ 8] + (D xor E xor A)); C := C shl 11 or C shr 21 + B; E := E shl 10 or E shr 22;
  Inc(B, Buffer[ 9] + (C xor D xor E)); B := B shl 13 or B shr 19 + A; D := D shl 10 or D shr 22;
  Inc(A, Buffer[10] + (B xor C xor D)); A := A shl 14 or A shr 18 + E; C := C shl 10 or C shr 22;
  Inc(E, Buffer[11] + (A xor B xor C)); E := E shl 15 or E shr 17 + D; B := B shl 10 or B shr 22;
  Inc(D, Buffer[12] + (E xor A xor B)); D := D shl  6 or D shr 26 + C; A := A shl 10 or A shr 22;
  Inc(C, Buffer[13] + (D xor E xor A)); C := C shl  7 or C shr 25 + B; E := E shl 10 or E shr 22;
  Inc(B, Buffer[14] + (C xor D xor E)); B := B shl  9 or B shr 23 + A; D := D shl 10 or D shr 22;
  Inc(A, Buffer[15] + (B xor C xor D)); A := A shl  8 or A shr 24 + E; C := C shl 10 or C shr 22;

  Inc(E, Buffer[ 7] + $5A827999 + ((A and B) or (not A and C))); E := E shl  7 or E shr 25 + D; B := B shl 10 or B shr 22;
  Inc(D, Buffer[ 4] + $5A827999 + ((E and A) or (not E and B))); D := D shl  6 or D shr 26 + C; A := A shl 10 or A shr 22;
  Inc(C, Buffer[13] + $5A827999 + ((D and E) or (not D and A))); C := C shl  8 or C shr 24 + B; E := E shl 10 or E shr 22;
  Inc(B, Buffer[ 1] + $5A827999 + ((C and D) or (not C and E))); B := B shl 13 or B shr 19 + A; D := D shl 10 or D shr 22;
  Inc(A, Buffer[10] + $5A827999 + ((B and C) or (not B and D))); A := A shl 11 or A shr 21 + E; C := C shl 10 or C shr 22;
  Inc(E, Buffer[ 6] + $5A827999 + ((A and B) or (not A and C))); E := E shl  9 or E shr 23 + D; B := B shl 10 or B shr 22;
  Inc(D, Buffer[15] + $5A827999 + ((E and A) or (not E and B))); D := D shl  7 or D shr 25 + C; A := A shl 10 or A shr 22;
  Inc(C, Buffer[ 3] + $5A827999 + ((D and E) or (not D and A))); C := C shl 15 or C shr 17 + B; E := E shl 10 or E shr 22;
  Inc(B, Buffer[12] + $5A827999 + ((C and D) or (not C and E))); B := B shl  7 or B shr 25 + A; D := D shl 10 or D shr 22;
  Inc(A, Buffer[ 0] + $5A827999 + ((B and C) or (not B and D))); A := A shl 12 or A shr 20 + E; C := C shl 10 or C shr 22;
  Inc(E, Buffer[ 9] + $5A827999 + ((A and B) or (not A and C))); E := E shl 15 or E shr 17 + D; B := B shl 10 or B shr 22;
  Inc(D, Buffer[ 5] + $5A827999 + ((E and A) or (not E and B))); D := D shl  9 or D shr 23 + C; A := A shl 10 or A shr 22;
  Inc(C, Buffer[ 2] + $5A827999 + ((D and E) or (not D and A))); C := C shl 11 or C shr 21 + B; E := E shl 10 or E shr 22;
  Inc(B, Buffer[14] + $5A827999 + ((C and D) or (not C and E))); B := B shl  7 or B shr 25 + A; D := D shl 10 or D shr 22;
  Inc(A, Buffer[11] + $5A827999 + ((B and C) or (not B and D))); A := A shl 13 or A shr 19 + E; C := C shl 10 or C shr 22;
  Inc(E, Buffer[ 8] + $5A827999 + ((A and B) or (not A and C))); E := E shl 12 or E shr 20 + D; B := B shl 10 or B shr 22;

  Inc(D, Buffer[ 3] + $6ED9EBA1 + ((E or not A) xor B)); D := D shl 11 or D shr 21 + C; A := A shl 10 or A shr 22;
  Inc(C, Buffer[10] + $6ED9EBA1 + ((D or not E) xor A)); C := C shl 13 or C shr 19 + B; E := E shl 10 or E shr 22;
  Inc(B, Buffer[14] + $6ED9EBA1 + ((C or not D) xor E)); B := B shl  6 or B shr 26 + A; D := D shl 10 or D shr 22;
  Inc(A, Buffer[ 4] + $6ED9EBA1 + ((B or not C) xor D)); A := A shl  7 or A shr 25 + E; C := C shl 10 or C shr 22;
  Inc(E, Buffer[ 9] + $6ED9EBA1 + ((A or not B) xor C)); E := E shl 14 or E shr 18 + D; B := B shl 10 or B shr 22;
  Inc(D, Buffer[15] + $6ED9EBA1 + ((E or not A) xor B)); D := D shl  9 or D shr 23 + C; A := A shl 10 or A shr 22;
  Inc(C, Buffer[ 8] + $6ED9EBA1 + ((D or not E) xor A)); C := C shl 13 or C shr 19 + B; E := E shl 10 or E shr 22;
  Inc(B, Buffer[ 1] + $6ED9EBA1 + ((C or not D) xor E)); B := B shl 15 or B shr 17 + A; D := D shl 10 or D shr 22;
  Inc(A, Buffer[ 2] + $6ED9EBA1 + ((B or not C) xor D)); A := A shl 14 or A shr 18 + E; C := C shl 10 or C shr 22;
  Inc(E, Buffer[ 7] + $6ED9EBA1 + ((A or not B) xor C)); E := E shl  8 or E shr 24 + D; B := B shl 10 or B shr 22;
  Inc(D, Buffer[ 0] + $6ED9EBA1 + ((E or not A) xor B)); D := D shl 13 or D shr 19 + C; A := A shl 10 or A shr 22;
  Inc(C, Buffer[ 6] + $6ED9EBA1 + ((D or not E) xor A)); C := C shl  6 or C shr 26 + B; E := E shl 10 or E shr 22;
  Inc(B, Buffer[13] + $6ED9EBA1 + ((C or not D) xor E)); B := B shl  5 or B shr 27 + A; D := D shl 10 or D shr 22;
  Inc(A, Buffer[11] + $6ED9EBA1 + ((B or not C) xor D)); A := A shl 12 or A shr 20 + E; C := C shl 10 or C shr 22;
  Inc(E, Buffer[ 5] + $6ED9EBA1 + ((A or not B) xor C)); E := E shl  7 or E shr 25 + D; B := B shl 10 or B shr 22;
  Inc(D, Buffer[12] + $6ED9EBA1 + ((E or not A) xor B)); D := D shl  5 or D shr 27 + C; A := A shl 10 or A shr 22;

  Inc(C, Buffer[ 1] + $8F1BBCDC + ((D and A) or (E and not A))); C := C shl 11 or C shr 21 + B; E := E shl 10 or E shr 22;
  Inc(B, Buffer[ 9] + $8F1BBCDC + ((C and E) or (D and not E))); B := B shl 12 or B shr 20 + A; D := D shl 10 or D shr 22;
  Inc(A, Buffer[11] + $8F1BBCDC + ((B and D) or (C and not D))); A := A shl 14 or A shr 18 + E; C := C shl 10 or C shr 22;
  Inc(E, Buffer[10] + $8F1BBCDC + ((A and C) or (B and not C))); E := E shl 15 or E shr 17 + D; B := B shl 10 or B shr 22;
  Inc(D, Buffer[ 0] + $8F1BBCDC + ((E and B) or (A and not B))); D := D shl 14 or D shr 18 + C; A := A shl 10 or A shr 22;
  Inc(C, Buffer[ 8] + $8F1BBCDC + ((D and A) or (E and not A))); C := C shl 15 or C shr 17 + B; E := E shl 10 or E shr 22;
  Inc(B, Buffer[12] + $8F1BBCDC + ((C and E) or (D and not E))); B := B shl  9 or B shr 23 + A; D := D shl 10 or D shr 22;
  Inc(A, Buffer[ 4] + $8F1BBCDC + ((B and D) or (C and not D))); A := A shl  8 or A shr 24 + E; C := C shl 10 or C shr 22;
  Inc(E, Buffer[13] + $8F1BBCDC + ((A and C) or (B and not C))); E := E shl  9 or E shr 23 + D; B := B shl 10 or B shr 22;
  Inc(D, Buffer[ 3] + $8F1BBCDC + ((E and B) or (A and not B))); D := D shl 14 or D shr 18 + C; A := A shl 10 or A shr 22;
  Inc(C, Buffer[ 7] + $8F1BBCDC + ((D and A) or (E and not A))); C := C shl  5 or C shr 27 + B; E := E shl 10 or E shr 22;
  Inc(B, Buffer[15] + $8F1BBCDC + ((C and E) or (D and not E))); B := B shl  6 or B shr 26 + A; D := D shl 10 or D shr 22;
  Inc(A, Buffer[14] + $8F1BBCDC + ((B and D) or (C and not D))); A := A shl  8 or A shr 24 + E; C := C shl 10 or C shr 22;
  Inc(E, Buffer[ 5] + $8F1BBCDC + ((A and C) or (B and not C))); E := E shl  6 or E shr 26 + D; B := B shl 10 or B shr 22;
  Inc(D, Buffer[ 6] + $8F1BBCDC + ((E and B) or (A and not B))); D := D shl  5 or D shr 27 + C; A := A shl 10 or A shr 22;
  Inc(C, Buffer[ 2] + $8F1BBCDC + ((D and A) or (E and not A))); C := C shl 12 or C shr 20 + B; E := E shl 10 or E shr 22;

  Inc(B, Buffer[ 4] + $A953FD4E + (C xor (D or not E))); B := B shl  9 or B shr 23 + A; D := D shl 10 or D shr 22;
  Inc(A, Buffer[ 0] + $A953FD4E + (B xor (C or not D))); A := A shl 15 or A shr 17 + E; C := C shl 10 or C shr 22;
  Inc(E, Buffer[ 5] + $A953FD4E + (A xor (B or not C))); E := E shl  5 or E shr 27 + D; B := B shl 10 or B shr 22;
  Inc(D, Buffer[ 9] + $A953FD4E + (E xor (A or not B))); D := D shl 11 or D shr 21 + C; A := A shl 10 or A shr 22;
  Inc(C, Buffer[ 7] + $A953FD4E + (D xor (E or not A))); C := C shl  6 or C shr 26 + B; E := E shl 10 or E shr 22;
  Inc(B, Buffer[12] + $A953FD4E + (C xor (D or not E))); B := B shl  8 or B shr 24 + A; D := D shl 10 or D shr 22;
  Inc(A, Buffer[ 2] + $A953FD4E + (B xor (C or not D))); A := A shl 13 or A shr 19 + E; C := C shl 10 or C shr 22;
  Inc(E, Buffer[10] + $A953FD4E + (A xor (B or not C))); E := E shl 12 or E shr 20 + D; B := B shl 10 or B shr 22;
  Inc(D, Buffer[14] + $A953FD4E + (E xor (A or not B))); D := D shl  5 or D shr 27 + C; A := A shl 10 or A shr 22;
  Inc(C, Buffer[ 1] + $A953FD4E + (D xor (E or not A))); C := C shl 12 or C shr 20 + B; E := E shl 10 or E shr 22;
  Inc(B, Buffer[ 3] + $A953FD4E + (C xor (D or not E))); B := B shl 13 or B shr 19 + A; D := D shl 10 or D shr 22;
  Inc(A, Buffer[ 8] + $A953FD4E + (B xor (C or not D))); A := A shl 14 or A shr 18 + E; C := C shl 10 or C shr 22;
  Inc(E, Buffer[11] + $A953FD4E + (A xor (B or not C))); E := E shl 11 or E shr 21 + D; B := B shl 10 or B shr 22;
  Inc(D, Buffer[ 6] + $A953FD4E + (E xor (A or not B))); D := D shl  8 or D shr 24 + C; A := A shl 10 or A shr 22;
  Inc(C, Buffer[15] + $A953FD4E + (D xor (E or not A))); C := C shl  5 or C shr 27 + B; E := E shl 10 or E shr 22;
  Inc(B, Buffer[13] + $A953FD4E + (C xor (D or not E))); B := B shl  6 or B shr 26 + A; D := D shl 10 or D shr 22;

  A1 := A;
  B1 := B;
  C1 := C;
  D1 := D;
  E1 := E;

  A := FDigest[0];
  B := FDigest[1];
  C := FDigest[2];
  D := FDigest[3];
  E := FDigest[4];

  Inc(A, Buffer[ 5] + $50A28BE6 + (B xor (C or not D))); A := A shl  8 or A shr 24 + E; C := C shl 10 or C shr 22;
  Inc(E, Buffer[14] + $50A28BE6 + (A xor (B or not C))); E := E shl  9 or E shr 23 + D; B := B shl 10 or B shr 22;
  Inc(D, Buffer[ 7] + $50A28BE6 + (E xor (A or not B))); D := D shl  9 or D shr 23 + C; A := A shl 10 or A shr 22;
  Inc(C, Buffer[ 0] + $50A28BE6 + (D xor (E or not A))); C := C shl 11 or C shr 21 + B; E := E shl 10 or E shr 22;
  Inc(B, Buffer[ 9] + $50A28BE6 + (C xor (D or not E))); B := B shl 13 or B shr 19 + A; D := D shl 10 or D shr 22;
  Inc(A, Buffer[ 2] + $50A28BE6 + (B xor (C or not D))); A := A shl 15 or A shr 17 + E; C := C shl 10 or C shr 22;
  Inc(E, Buffer[11] + $50A28BE6 + (A xor (B or not C))); E := E shl 15 or E shr 17 + D; B := B shl 10 or B shr 22;
  Inc(D, Buffer[ 4] + $50A28BE6 + (E xor (A or not B))); D := D shl  5 or D shr 27 + C; A := A shl 10 or A shr 22;
  Inc(C, Buffer[13] + $50A28BE6 + (D xor (E or not A))); C := C shl  7 or C shr 25 + B; E := E shl 10 or E shr 22;
  Inc(B, Buffer[ 6] + $50A28BE6 + (C xor (D or not E))); B := B shl  7 or B shr 25 + A; D := D shl 10 or D shr 22;
  Inc(A, Buffer[15] + $50A28BE6 + (B xor (C or not D))); A := A shl  8 or A shr 24 + E; C := C shl 10 or C shr 22;
  Inc(E, Buffer[ 8] + $50A28BE6 + (A xor (B or not C))); E := E shl 11 or E shr 21 + D; B := B shl 10 or B shr 22;
  Inc(D, Buffer[ 1] + $50A28BE6 + (E xor (A or not B))); D := D shl 14 or D shr 18 + C; A := A shl 10 or A shr 22;
  Inc(C, Buffer[10] + $50A28BE6 + (D xor (E or not A))); C := C shl 14 or C shr 18 + B; E := E shl 10 or E shr 22;
  Inc(B, Buffer[ 3] + $50A28BE6 + (C xor (D or not E))); B := B shl 12 or B shr 20 + A; D := D shl 10 or D shr 22;
  Inc(A, Buffer[12] + $50A28BE6 + (B xor (C or not D))); A := A shl  6 or A shr 26 + E; C := C shl 10 or C shr 22;

  Inc(E, Buffer[ 6] + $5C4DD124 + ((A and C) or (B and not C))); E := E shl  9 or E shr 23 + D; B := B shl 10 or B shr 22;
  Inc(D, Buffer[11] + $5C4DD124 + ((E and B) or (A and not B))); D := D shl 13 or D shr 19 + C; A := A shl 10 or A shr 22;
  Inc(C, Buffer[ 3] + $5C4DD124 + ((D and A) or (E and not A))); C := C shl 15 or C shr 17 + B; E := E shl 10 or E shr 22;
  Inc(B, Buffer[ 7] + $5C4DD124 + ((C and E) or (D and not E))); B := B shl  7 or B shr 25 + A; D := D shl 10 or D shr 22;
  Inc(A, Buffer[ 0] + $5C4DD124 + ((B and D) or (C and not D))); A := A shl 12 or A shr 20 + E; C := C shl 10 or C shr 22;
  Inc(E, Buffer[13] + $5C4DD124 + ((A and C) or (B and not C))); E := E shl  8 or E shr 24 + D; B := B shl 10 or B shr 22;
  Inc(D, Buffer[ 5] + $5C4DD124 + ((E and B) or (A and not B))); D := D shl  9 or D shr 23 + C; A := A shl 10 or A shr 22;
  Inc(C, Buffer[10] + $5C4DD124 + ((D and A) or (E and not A))); C := C shl 11 or C shr 21 + B; E := E shl 10 or E shr 22;
  Inc(B, Buffer[14] + $5C4DD124 + ((C and E) or (D and not E))); B := B shl  7 or B shr 25 + A; D := D shl 10 or D shr 22;
  Inc(A, Buffer[15] + $5C4DD124 + ((B and D) or (C and not D))); A := A shl  7 or A shr 25 + E; C := C shl 10 or C shr 22;
  Inc(E, Buffer[ 8] + $5C4DD124 + ((A and C) or (B and not C))); E := E shl 12 or E shr 20 + D; B := B shl 10 or B shr 22;
  Inc(D, Buffer[12] + $5C4DD124 + ((E and B) or (A and not B))); D := D shl  7 or D shr 25 + C; A := A shl 10 or A shr 22;
  Inc(C, Buffer[ 4] + $5C4DD124 + ((D and A) or (E and not A))); C := C shl  6 or C shr 26 + B; E := E shl 10 or E shr 22;
  Inc(B, Buffer[ 9] + $5C4DD124 + ((C and E) or (D and not E))); B := B shl 15 or B shr 17 + A; D := D shl 10 or D shr 22;
  Inc(A, Buffer[ 1] + $5C4DD124 + ((B and D) or (C and not D))); A := A shl 13 or A shr 19 + E; C := C shl 10 or C shr 22;
  Inc(E, Buffer[ 2] + $5C4DD124 + ((A and C) or (B and not C))); E := E shl 11 or E shr 21 + D; B := B shl 10 or B shr 22;

  Inc(D, Buffer[15] + $6D703EF3 + ((E or not A) xor B)); D := D shl  9 or D shr 23 + C; A := A shl 10 or A shr 22;
  Inc(C, Buffer[ 5] + $6D703EF3 + ((D or not E) xor A)); C := C shl  7 or C shr 25 + B; E := E shl 10 or E shr 22;
  Inc(B, Buffer[ 1] + $6D703EF3 + ((C or not D) xor E)); B := B shl 15 or B shr 17 + A; D := D shl 10 or D shr 22;
  Inc(A, Buffer[ 3] + $6D703EF3 + ((B or not C) xor D)); A := A shl 11 or A shr 21 + E; C := C shl 10 or C shr 22;
  Inc(E, Buffer[ 7] + $6D703EF3 + ((A or not B) xor C)); E := E shl  8 or E shr 24 + D; B := B shl 10 or B shr 22;
  Inc(D, Buffer[14] + $6D703EF3 + ((E or not A) xor B)); D := D shl  6 or D shr 26 + C; A := A shl 10 or A shr 22;
  Inc(C, Buffer[ 6] + $6D703EF3 + ((D or not E) xor A)); C := C shl  6 or C shr 26 + B; E := E shl 10 or E shr 22;
  Inc(B, Buffer[ 9] + $6D703EF3 + ((C or not D) xor E)); B := B shl 14 or B shr 18 + A; D := D shl 10 or D shr 22;
  Inc(A, Buffer[11] + $6D703EF3 + ((B or not C) xor D)); A := A shl 12 or A shr 20 + E; C := C shl 10 or C shr 22;
  Inc(E, Buffer[ 8] + $6D703EF3 + ((A or not B) xor C)); E := E shl 13 or E shr 19 + D; B := B shl 10 or B shr 22;
  Inc(D, Buffer[12] + $6D703EF3 + ((E or not A) xor B)); D := D shl  5 or D shr 27 + C; A := A shl 10 or A shr 22;
  Inc(C, Buffer[ 2] + $6D703EF3 + ((D or not E) xor A)); C := C shl 14 or C shr 18 + B; E := E shl 10 or E shr 22;
  Inc(B, Buffer[10] + $6D703EF3 + ((C or not D) xor E)); B := B shl 13 or B shr 19 + A; D := D shl 10 or D shr 22;
  Inc(A, Buffer[ 0] + $6D703EF3 + ((B or not C) xor D)); A := A shl 13 or A shr 19 + E; C := C shl 10 or C shr 22;
  Inc(E, Buffer[ 4] + $6D703EF3 + ((A or not B) xor C)); E := E shl  7 or E shr 25 + D; B := B shl 10 or B shr 22;
  Inc(D, Buffer[13] + $6D703EF3 + ((E or not A) xor B)); D := D shl  5 or D shr 27 + C; A := A shl 10 or A shr 22;

  Inc(C, Buffer[ 8] + $7A6D76E9 + ((D and E) or (not D and A))); C := C shl 15 or C shr 17 + B; E := E shl 10 or E shr 22;
  Inc(B, Buffer[ 6] + $7A6D76E9 + ((C and D) or (not C and E))); B := B shl  5 or B shr 27 + A; D := D shl 10 or D shr 22;
  Inc(A, Buffer[ 4] + $7A6D76E9 + ((B and C) or (not B and D))); A := A shl  8 or A shr 24 + E; C := C shl 10 or C shr 22;
  Inc(E, Buffer[ 1] + $7A6D76E9 + ((A and B) or (not A and C))); E := E shl 11 or E shr 21 + D; B := B shl 10 or B shr 22;
  Inc(D, Buffer[ 3] + $7A6D76E9 + ((E and A) or (not E and B))); D := D shl 14 or D shr 18 + C; A := A shl 10 or A shr 22;
  Inc(C, Buffer[11] + $7A6D76E9 + ((D and E) or (not D and A))); C := C shl 14 or C shr 18 + B; E := E shl 10 or E shr 22;
  Inc(B, Buffer[15] + $7A6D76E9 + ((C and D) or (not C and E))); B := B shl  6 or B shr 26 + A; D := D shl 10 or D shr 22;
  Inc(A, Buffer[ 0] + $7A6D76E9 + ((B and C) or (not B and D))); A := A shl 14 or A shr 18 + E; C := C shl 10 or C shr 22;
  Inc(E, Buffer[ 5] + $7A6D76E9 + ((A and B) or (not A and C))); E := E shl  6 or E shr 26 + D; B := B shl 10 or B shr 22;
  Inc(D, Buffer[12] + $7A6D76E9 + ((E and A) or (not E and B))); D := D shl  9 or D shr 23 + C; A := A shl 10 or A shr 22;
  Inc(C, Buffer[ 2] + $7A6D76E9 + ((D and E) or (not D and A))); C := C shl 12 or C shr 20 + B; E := E shl 10 or E shr 22;
  Inc(B, Buffer[13] + $7A6D76E9 + ((C and D) or (not C and E))); B := B shl  9 or B shr 23 + A; D := D shl 10 or D shr 22;
  Inc(A, Buffer[ 9] + $7A6D76E9 + ((B and C) or (not B and D))); A := A shl 12 or A shr 20 + E; C := C shl 10 or C shr 22;
  Inc(E, Buffer[ 7] + $7A6D76E9 + ((A and B) or (not A and C))); E := E shl  5 or E shr 27 + D; B := B shl 10 or B shr 22;
  Inc(D, Buffer[10] + $7A6D76E9 + ((E and A) or (not E and B))); D := D shl 15 or D shr 17 + C; A := A shl 10 or A shr 22;
  Inc(C, Buffer[14] + $7A6D76E9 + ((D and E) or (not D and A))); C := C shl  8 or C shr 24 + B; E := E shl 10 or E shr 22;

  Inc(B, Buffer[12] + (C xor D xor E)); B := B shl  8 or B shr 24 + A; D := D shl 10 or D shr 22;
  Inc(A, Buffer[15] + (B xor C xor D)); A := A shl  5 or A shr 27 + E; C := C shl 10 or C shr 22;
  Inc(E, Buffer[10] + (A xor B xor C)); E := E shl 12 or E shr 20 + D; B := B shl 10 or B shr 22;
  Inc(D, Buffer[ 4] + (E xor A xor B)); D := D shl  9 or D shr 23 + C; A := A shl 10 or A shr 22;
  Inc(C, Buffer[ 1] + (D xor E xor A)); C := C shl 12 or C shr 20 + B; E := E shl 10 or E shr 22;
  Inc(B, Buffer[ 5] + (C xor D xor E)); B := B shl  5 or B shr 27 + A; D := D shl 10 or D shr 22;
  Inc(A, Buffer[ 8] + (B xor C xor D)); A := A shl 14 or A shr 18 + E; C := C shl 10 or C shr 22;
  Inc(E, Buffer[ 7] + (A xor B xor C)); E := E shl  6 or E shr 26 + D; B := B shl 10 or B shr 22;
  Inc(D, Buffer[ 6] + (E xor A xor B)); D := D shl  8 or D shr 24 + C; A := A shl 10 or A shr 22;
  Inc(C, Buffer[ 2] + (D xor E xor A)); C := C shl 13 or C shr 19 + B; E := E shl 10 or E shr 22;
  Inc(B, Buffer[13] + (C xor D xor E)); B := B shl  6 or B shr 26 + A; D := D shl 10 or D shr 22;
  Inc(A, Buffer[14] + (B xor C xor D)); A := A shl  5 or A shr 27 + E; C := C shl 10 or C shr 22;
  Inc(E, Buffer[ 0] + (A xor B xor C)); E := E shl 15 or E shr 17 + D; B := B shl 10 or B shr 22;
  Inc(D, Buffer[ 3] + (E xor A xor B)); D := D shl 13 or D shr 19 + C; A := A shl 10 or A shr 22;
  Inc(C, Buffer[ 9] + (D xor E xor A)); C := C shl 11 or C shr 21 + B; E := E shl 10 or E shr 22;
  Inc(B, Buffer[11] + (C xor D xor E)); B := B shl 11 or B shr 21 + A; D := D shl 10 or D shr 22;

  Inc(D, C1 + FDigest[1]);
  FDigest[1] := FDigest[2] + D1 + E;
  FDigest[2] := FDigest[3] + E1 + A;
  FDigest[3] := FDigest[4] + A1 + B;
  FDigest[4] := FDigest[0] + B1 + C;
  FDigest[0] := D;
end;

class function THash_RipeMD160.DigestKeySize: Integer;
begin
  Result := 20;
end;

{$IFDEF UseASM}
procedure SHABuffer386(S, D: Pointer; Rotate: Boolean); assembler;
asm
     PUSH  EBX
     PUSH  ECX
     MOV   EBX,EAX
     XOR   ECX,ECX
@@1: MOV   EAX,[EDX + ECX * 4]
     XCHG  AL,AH
     ROL   EAX,16
     XCHG  AL,AH
     MOV   [EBX],EAX
     ADD   EBX,4
     INC   ECX
     CMP   ECX,16
     JNZ   @@1
     MOV   ECX,64
     POP   EDX
     CMP   DL,0
     JZ    @@3
@@2: MOV   EAX,[EBX -  3 * 4]
     XOR   EAX,[EBX -  8 * 4]
     XOR   EAX,[EBX - 14 * 4]
     XOR   EAX,[EBX - 16 * 4]
     ROL   EAX,1
     MOV   [EBX],EAX
     ADD   EBX,4
     DEC   ECX
     JNZ   @@2
     JMP   @@4

@@3: MOV   EAX,[EBX -  3 * 4]
     XOR   EAX,[EBX -  8 * 4]
     XOR   EAX,[EBX - 14 * 4]
     XOR   EAX,[EBX - 16 * 4]
     MOV   [EBX],EAX
     ADD   EBX,4
     DEC   ECX
     JNZ   @@3

@@4: POP   EBX
end;
{$ENDIF}

procedure SHABuffer486(const S, D: TIntArray; Rotate: Boolean); {$IFDEF UseASM}assembler;{$ENDIF}
{$IFNDEF UseASM}
var
  n: Longword;
  i: Integer;
begin
  for i := 0 to 15 do
    S[i] := SwapInteger(D[i]);

  for i := 16 to 80 -1 do begin
    n := S[i - 3] xor S[i - 8] xor S[i - 14] xor S[i - 16];
    if Rotate then
      S[i] := (n shl 1) or (n shr 31)
    else
      S[i] := n;
  end;
{$ELSE}
asm
     PUSH  EBX
     PUSH  ECX
     MOV   EBX,EAX
     XOR   ECX,ECX
@@1: MOV   EAX,[EDX + ECX * 4]
     BSWAP EAX
     MOV   [EBX],EAX
     ADD   EBX,4
     INC   ECX
     CMP   ECX,16
     JNZ   @@1
     MOV   ECX,64
     POP   EDX
     CMP   DL,0
     JZ    @@3
@@2: MOV   EAX,[EBX -  3 * 4]
     XOR   EAX,[EBX -  8 * 4]
     XOR   EAX,[EBX - 14 * 4]
     XOR   EAX,[EBX - 16 * 4]
     ROL   EAX,1
     MOV   [EBX],EAX
     ADD   EBX,4
     DEC   ECX
     JNZ   @@2
     JMP   @@4

@@3: MOV   EAX,[EBX -  3 * 4]
     XOR   EAX,[EBX -  8 * 4]
     XOR   EAX,[EBX - 14 * 4]
     XOR   EAX,[EBX - 16 * 4]
     MOV   [EBX],EAX
     ADD   EBX,4
     DEC   ECX
     JNZ   @@3

@@4: POP   EBX
{$ENDIF}
end;

const
  SHABuffer: procedure(const S, D: TIntArray; Rotate: Boolean) = SHABuffer486;

procedure THash_SHA.Transform({$IFDEF CLR}const{$ENDIF} Buffer: TIntArray);
var
  A, B, C, D, E: LongWord;
  W: array[0..79] of LongWord;
begin
  SHABuffer({$IFNDEF CLR}@{$ENDIF}W, Buffer, FRotate);

  A := FDigest[0];
  B := FDigest[1];
  C := FDigest[2];
  D := FDigest[3];
  E := FDigest[4];

  Inc(E, (A shl 5 or A shr 27) + (D xor (B and (C xor D))) + W[ 0] + $5A827999); B := B shr 2 or B shl 30;
  Inc(D, (E shl 5 or E shr 27) + (C xor (A and (B xor C))) + W[ 1] + $5A827999); A := A shr 2 or A shl 30;
  Inc(C, (D shl 5 or D shr 27) + (B xor (E and (A xor B))) + W[ 2] + $5A827999); E := E shr 2 or E shl 30;
  Inc(B, (C shl 5 or C shr 27) + (A xor (D and (E xor A))) + W[ 3] + $5A827999); D := D shr 2 or D shl 30;
  Inc(A, (B shl 5 or B shr 27) + (E xor (C and (D xor E))) + W[ 4] + $5A827999); C := C shr 2 or C shl 30;
  Inc(E, (A shl 5 or A shr 27) + (D xor (B and (C xor D))) + W[ 5] + $5A827999); B := B shr 2 or B shl 30;
  Inc(D, (E shl 5 or E shr 27) + (C xor (A and (B xor C))) + W[ 6] + $5A827999); A := A shr 2 or A shl 30;
  Inc(C, (D shl 5 or D shr 27) + (B xor (E and (A xor B))) + W[ 7] + $5A827999); E := E shr 2 or E shl 30;
  Inc(B, (C shl 5 or C shr 27) + (A xor (D and (E xor A))) + W[ 8] + $5A827999); D := D shr 2 or D shl 30;
  Inc(A, (B shl 5 or B shr 27) + (E xor (C and (D xor E))) + W[ 9] + $5A827999); C := C shr 2 or C shl 30;
  Inc(E, (A shl 5 or A shr 27) + (D xor (B and (C xor D))) + W[10] + $5A827999); B := B shr 2 or B shl 30;
  Inc(D, (E shl 5 or E shr 27) + (C xor (A and (B xor C))) + W[11] + $5A827999); A := A shr 2 or A shl 30;
  Inc(C, (D shl 5 or D shr 27) + (B xor (E and (A xor B))) + W[12] + $5A827999); E := E shr 2 or E shl 30;
  Inc(B, (C shl 5 or C shr 27) + (A xor (D and (E xor A))) + W[13] + $5A827999); D := D shr 2 or D shl 30;
  Inc(A, (B shl 5 or B shr 27) + (E xor (C and (D xor E))) + W[14] + $5A827999); C := C shr 2 or C shl 30;
  Inc(E, (A shl 5 or A shr 27) + (D xor (B and (C xor D))) + W[15] + $5A827999); B := B shr 2 or B shl 30;
  Inc(D, (E shl 5 or E shr 27) + (C xor (A and (B xor C))) + W[16] + $5A827999); A := A shr 2 or A shl 30;
  Inc(C, (D shl 5 or D shr 27) + (B xor (E and (A xor B))) + W[17] + $5A827999); E := E shr 2 or E shl 30;
  Inc(B, (C shl 5 or C shr 27) + (A xor (D and (E xor A))) + W[18] + $5A827999); D := D shr 2 or D shl 30;
  Inc(A, (B shl 5 or B shr 27) + (E xor (C and (D xor E))) + W[19] + $5A827999); C := C shr 2 or C shl 30;

  Inc(E, (A shl 5 or A shr 27) + (D xor B xor C) + W[20] + $6ED9EBA1); B := B shr 2 or B shl 30;
  Inc(D, (E shl 5 or E shr 27) + (C xor A xor B) + W[21] + $6ED9EBA1); A := A shr 2 or A shl 30;
  Inc(C, (D shl 5 or D shr 27) + (B xor E xor A) + W[22] + $6ED9EBA1); E := E shr 2 or E shl 30;
  Inc(B, (C shl 5 or C shr 27) + (A xor D xor E) + W[23] + $6ED9EBA1); D := D shr 2 or D shl 30;
  Inc(A, (B shl 5 or B shr 27) + (E xor C xor D) + W[24] + $6ED9EBA1); C := C shr 2 or C shl 30;
  Inc(E, (A shl 5 or A shr 27) + (D xor B xor C) + W[25] + $6ED9EBA1); B := B shr 2 or B shl 30;
  Inc(D, (E shl 5 or E shr 27) + (C xor A xor B) + W[26] + $6ED9EBA1); A := A shr 2 or A shl 30;
  Inc(C, (D shl 5 or D shr 27) + (B xor E xor A) + W[27] + $6ED9EBA1); E := E shr 2 or E shl 30;
  Inc(B, (C shl 5 or C shr 27) + (A xor D xor E) + W[28] + $6ED9EBA1); D := D shr 2 or D shl 30;
  Inc(A, (B shl 5 or B shr 27) + (E xor C xor D) + W[29] + $6ED9EBA1); C := C shr 2 or C shl 30;
  Inc(E, (A shl 5 or A shr 27) + (D xor B xor C) + W[30] + $6ED9EBA1); B := B shr 2 or B shl 30;
  Inc(D, (E shl 5 or E shr 27) + (C xor A xor B) + W[31] + $6ED9EBA1); A := A shr 2 or A shl 30;
  Inc(C, (D shl 5 or D shr 27) + (B xor E xor A) + W[32] + $6ED9EBA1); E := E shr 2 or E shl 30;
  Inc(B, (C shl 5 or C shr 27) + (A xor D xor E) + W[33] + $6ED9EBA1); D := D shr 2 or D shl 30;
  Inc(A, (B shl 5 or B shr 27) + (E xor C xor D) + W[34] + $6ED9EBA1); C := C shr 2 or C shl 30;
  Inc(E, (A shl 5 or A shr 27) + (D xor B xor C) + W[35] + $6ED9EBA1); B := B shr 2 or B shl 30;
  Inc(D, (E shl 5 or E shr 27) + (C xor A xor B) + W[36] + $6ED9EBA1); A := A shr 2 or A shl 30;
  Inc(C, (D shl 5 or D shr 27) + (B xor E xor A) + W[37] + $6ED9EBA1); E := E shr 2 or E shl 30;
  Inc(B, (C shl 5 or C shr 27) + (A xor D xor E) + W[38] + $6ED9EBA1); D := D shr 2 or D shl 30;
  Inc(A, (B shl 5 or B shr 27) + (E xor C xor D) + W[39] + $6ED9EBA1); C := C shr 2 or C shl 30;

  Inc(E, (A shl 5 or A shr 27) + ((B and C) or (D and (B or C))) + W[40] + $8F1BBCDC); B := B shr 2 or B shl 30;
  Inc(D, (E shl 5 or E shr 27) + ((A and B) or (C and (A or B))) + W[41] + $8F1BBCDC); A := A shr 2 or A shl 30;
  Inc(C, (D shl 5 or D shr 27) + ((E and A) or (B and (E or A))) + W[42] + $8F1BBCDC); E := E shr 2 or E shl 30;
  Inc(B, (C shl 5 or C shr 27) + ((D and E) or (A and (D or E))) + W[43] + $8F1BBCDC); D := D shr 2 or D shl 30;
  Inc(A, (B shl 5 or B shr 27) + ((C and D) or (E and (C or D))) + W[44] + $8F1BBCDC); C := C shr 2 or C shl 30;
  Inc(E, (A shl 5 or A shr 27) + ((B and C) or (D and (B or C))) + W[45] + $8F1BBCDC); B := B shr 2 or B shl 30;
  Inc(D, (E shl 5 or E shr 27) + ((A and B) or (C and (A or B))) + W[46] + $8F1BBCDC); A := A shr 2 or A shl 30;
  Inc(C, (D shl 5 or D shr 27) + ((E and A) or (B and (E or A))) + W[47] + $8F1BBCDC); E := E shr 2 or E shl 30;
  Inc(B, (C shl 5 or C shr 27) + ((D and E) or (A and (D or E))) + W[48] + $8F1BBCDC); D := D shr 2 or D shl 30;
  Inc(A, (B shl 5 or B shr 27) + ((C and D) or (E and (C or D))) + W[49] + $8F1BBCDC); C := C shr 2 or C shl 30;
  Inc(E, (A shl 5 or A shr 27) + ((B and C) or (D and (B or C))) + W[50] + $8F1BBCDC); B := B shr 2 or B shl 30;
  Inc(D, (E shl 5 or E shr 27) + ((A and B) or (C and (A or B))) + W[51] + $8F1BBCDC); A := A shr 2 or A shl 30;
  Inc(C, (D shl 5 or D shr 27) + ((E and A) or (B and (E or A))) + W[52] + $8F1BBCDC); E := E shr 2 or E shl 30;
  Inc(B, (C shl 5 or C shr 27) + ((D and E) or (A and (D or E))) + W[53] + $8F1BBCDC); D := D shr 2 or D shl 30;
  Inc(A, (B shl 5 or B shr 27) + ((C and D) or (E and (C or D))) + W[54] + $8F1BBCDC); C := C shr 2 or C shl 30;
  Inc(E, (A shl 5 or A shr 27) + ((B and C) or (D and (B or C))) + W[55] + $8F1BBCDC); B := B shr 2 or B shl 30;
  Inc(D, (E shl 5 or E shr 27) + ((A and B) or (C and (A or B))) + W[56] + $8F1BBCDC); A := A shr 2 or A shl 30;
  Inc(C, (D shl 5 or D shr 27) + ((E and A) or (B and (E or A))) + W[57] + $8F1BBCDC); E := E shr 2 or E shl 30;
  Inc(B, (C shl 5 or C shr 27) + ((D and E) or (A and (D or E))) + W[58] + $8F1BBCDC); D := D shr 2 or D shl 30;
  Inc(A, (B shl 5 or B shr 27) + ((C and D) or (E and (C or D))) + W[59] + $8F1BBCDC); C := C shr 2 or C shl 30;

  Inc(E, (A shl 5 or A shr 27) + (D xor B xor C) + W[60] + $CA62C1D6); B := B shr 2 or B shl 30;
  Inc(D, (E shl 5 or E shr 27) + (C xor A xor B) + W[61] + $CA62C1D6); A := A shr 2 or A shl 30;
  Inc(C, (D shl 5 or D shr 27) + (B xor E xor A) + W[62] + $CA62C1D6); E := E shr 2 or E shl 30;
  Inc(B, (C shl 5 or C shr 27) + (A xor D xor E) + W[63] + $CA62C1D6); D := D shr 2 or D shl 30;
  Inc(A, (B shl 5 or B shr 27) + (E xor C xor D) + W[64] + $CA62C1D6); C := C shr 2 or C shl 30;
  Inc(E, (A shl 5 or A shr 27) + (D xor B xor C) + W[65] + $CA62C1D6); B := B shr 2 or B shl 30;
  Inc(D, (E shl 5 or E shr 27) + (C xor A xor B) + W[66] + $CA62C1D6); A := A shr 2 or A shl 30;
  Inc(C, (D shl 5 or D shr 27) + (B xor E xor A) + W[67] + $CA62C1D6); E := E shr 2 or E shl 30;
  Inc(B, (C shl 5 or C shr 27) + (A xor D xor E) + W[68] + $CA62C1D6); D := D shr 2 or D shl 30;
  Inc(A, (B shl 5 or B shr 27) + (E xor C xor D) + W[69] + $CA62C1D6); C := C shr 2 or C shl 30;
  Inc(E, (A shl 5 or A shr 27) + (D xor B xor C) + W[70] + $CA62C1D6); B := B shr 2 or B shl 30;
  Inc(D, (E shl 5 or E shr 27) + (C xor A xor B) + W[71] + $CA62C1D6); A := A shr 2 or A shl 30;
  Inc(C, (D shl 5 or D shr 27) + (B xor E xor A) + W[72] + $CA62C1D6); E := E shr 2 or E shl 30;
  Inc(B, (C shl 5 or C shr 27) + (A xor D xor E) + W[73] + $CA62C1D6); D := D shr 2 or D shl 30;
  Inc(A, (B shl 5 or B shr 27) + (E xor C xor D) + W[74] + $CA62C1D6); C := C shr 2 or C shl 30;
  Inc(E, (A shl 5 or A shr 27) + (D xor B xor C) + W[75] + $CA62C1D6); B := B shr 2 or B shl 30;
  Inc(D, (E shl 5 or E shr 27) + (C xor A xor B) + W[76] + $CA62C1D6); A := A shr 2 or A shl 30;
  Inc(C, (D shl 5 or D shr 27) + (B xor E xor A) + W[77] + $CA62C1D6); E := E shr 2 or E shl 30;
  Inc(B, (C shl 5 or C shr 27) + (A xor D xor E) + W[78] + $CA62C1D6); D := D shr 2 or D shl 30;
  Inc(A, (B shl 5 or B shr 27) + (E xor C xor D) + W[79] + $CA62C1D6); C := C shr 2 or C shl 30;

  Inc(FDigest[0], A);
  Inc(FDigest[1], B);
  Inc(FDigest[2], C);
  Inc(FDigest[3], D);
  Inc(FDigest[4], E);
end;

procedure THash_SHA.Done;
var
  I: Integer;
  S: Int64;
begin
  I := FCount and $3F;
  Buffer.SetByte({$IFNDEF CLR}@{$ENDIF}FBuffer, I, $80);
  Inc(I);
  if I > 64 - 8 then
  begin
    Buffer.BlockCopy(NullArray, 0, FBuffer, I, 64 - I); // Fill 0
    Transform({$IFNDEF CLR}@{$ENDIF}FBuffer);
    I := 0;
  end;
  Buffer.BlockCopy(NullArray, 0, FBuffer, I, 64 - I);
  S := UInt64(FCount) shl 3;
  FBuffer[16 - 1] := SwapInteger(Longword(S));
  FBuffer[16 - 2] := SwapInteger(Longword(S shr 32));

  Transform({$IFNDEF CLR}@{$ENDIF}FBuffer);

{$IFNDEF CLR}
  FillChar(FBuffer, SizeOf(FBuffer), 0);
{$ELSE}
  &Array.Clear(FBuffer, 0, Length(FBuffer));
{$ENDIF}

{and here the Endian conversion}
  SwapIntegerBuffer({$IFNDEF CLR}@{$ENDIF}FDigest, {$IFNDEF CLR}@{$ENDIF}FDigest, 5);
  Protect(False);
end;

procedure THash_SHA1.Init;
begin
  FRotate := True;
  inherited Init;
end;

end.

