⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 icssha1.pas

📁 BaiduMp3 search baidu mp3
💻 PAS
📖 第 1 页 / 共 2 页
字号:
// ============================================================================
// D5-implementation of "US Secure Hash Algorithm 1 (SHA1)" (RFC3174)
// Copyright (c) 2001, Juergen Haible.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
// ============================================================================

{------------------------------------------------------------------------------
Update by F. Piette for ICS (http://www.overbyte.be)
Jan 10, 2004 Defined uint32_t as LongWord instead of LongInt
Jul 23, 2004 Revised SHA1Reset to check for nil reference to comply with RFC-3174
             Made the unit compatible with Delphi 2
------------------------------------------------------------------------------}


unit IcsSha1; // "US Secure Hash Algorithm 1 (SHA1)" (RFC3174)

{------------------------------------------------------------------------------

   Based on the reference implementation in RFC 3174

------------------------------------------------------------------------------}

interface
{$I ICSDEFS.INC}
{$R-}
{$Q-}

uses
   SysUtils, Classes;

const
   IcsSHA1Version     = 100;
   CopyRight : String = ' IcsSHA1 (c) 2004-2005 F. Piette V1.00 ';

const
   shaSuccess      = 0;
   shaNull         = 1;
   shaInputTooLong = 2;
   shaStateError   = 3;
   SHA1HashSize    = 20;

type
   {$IFNDEF DELPHI2_UP}
   {$IFNDEF FPC}
   Bomb('This code requires Delphi 2 or later'};
   {$ENDIF}
   {$ENDIF}
   {$IFDEF DELPHI4_UP}
   uint32_t      = LongWord; //Cardinal; // [Should be] unsigned 32 bit integer
   {$ELSE}
   uint32_t      = LongInt;
   {$ENDIF}
   uint8_t       = Byte;     // unsigned 8 bit integer (i.e., unsigned char)
   int_least16_t = LongInt;  // integer of >= 16 bits

   SHA1Digest = array[0..SHA1HashSize-1] of Char;
   SHA1DigestString = AnsiString;  // string containing 20 chars

   // This structure will hold context information for the SHA-1
   // hashing operation
   SHA1Context = record
        Intermediate_Hash: array[0..SHA1HashSize div 4-1] of uint32_t; // Message Digest
        Length_Low : uint32_t;                  // Message length in bits
        Length_High: uint32_t;                  // Message length in bits
        Message_Block_Index: int_least16_t;     // Index into message block array
        Message_Block: array[0..63] of uint8_t; // 512-bit message blocks
        Computed: Integer;                      // Is the digest computed?
        Corrupted: Integer;                     // Is the message digest corrupted?
   end;

function SHA1Reset ( var context       : SHA1Context ): Integer;
function SHA1Input ( var context       : SHA1Context;
                     message_array     : PChar;
                     length            : Cardinal ): Integer;
function SHA1Result( var context       : SHA1Context;
                     var Message_Digest: SHA1Digest ): Integer;

function SHA1ofStr   ( const s: String            ): SHA1DigestString;
function SHA1ofBuf   ( const buf; buflen: Integer ): SHA1DigestString;
function SHA1ofStream( const strm: TStream        ): SHA1DigestString;

function SHA1toHex( const digest: SHA1DigestString ): String;

procedure HMAC_SHA1( const Data; DataLen: Integer;
                     const Key;  KeyLen : Integer;
                     {$IFDEF DELPHI3_UP}out
                     {$ELSE}var{$ENDIF} Digest : SHA1Digest );
function  HMAC_SHA1_EX( const Data: String;
                     const Key : String ): String; //overload;

implementation

// Define the SHA1 circular left shift macro
function SHA1CircularShift( const bits, word: uint32_t ): uint32_t;
begin
   Result := (((word) shl (bits)) or ((word) shr (32-(bits))));
end;

// This function will process the next 512 bits of the message
// stored in the Message_Block array.
procedure SHA1ProcessMessageBlock( var context: SHA1Context );
const K: array[0..3] of uint32_t = (  //* Constants defined in SHA-1   */
                                      $5A827999,
                                      $6ED9EBA1,
                                      $8F1BBCDC,
                                      $CA62C1D6
                                   );
var
    t: Integer;                  //* Loop counter                */
    temp: uint32_t;              //* Temporary word value        */
    W: array[0..79] of uint32_t; //* Word sequence               */
    A, B, C, D, E: uint32_t;     //* Word buffers                */
begin

    // Initialize the first 16 words in the array W
    for t := 0 to 15 do begin
        W[t] := context.Message_Block[t * 4    ] shl 24
             or context.Message_Block[t * 4 + 1] shl 16
             or context.Message_Block[t * 4 + 2] shl 8
             or context.Message_Block[t * 4 + 3];
    end;

    for t := 16 to 79 do begin
       W[t] := SHA1CircularShift(1,W[t-3] xor W[t-8] xor W[t-14] xor W[t-16]);
    end;

    A := context.Intermediate_Hash[0];
    B := context.Intermediate_Hash[1];
    C := context.Intermediate_Hash[2];
    D := context.Intermediate_Hash[3];
    E := context.Intermediate_Hash[4];

    for t := 0 to 19 do begin
        temp :=  SHA1CircularShift(5,A) +
                 ((B and C) or ((not B) and D)) + E + W[t] + K[0];
        E := D;
        D := C;
        C := SHA1CircularShift(30,B);
        B := A;
        A := temp;
    end;

    for t := 20 to 39 do begin
        temp := SHA1CircularShift(5,A) + (B xor C xor D) + E + W[t] + K[1];
        E := D;
        D := C;
        C := SHA1CircularShift(30,B);
        B := A;
        A := temp;
    end;

    for t := 40 to 59 do begin
        temp := SHA1CircularShift(5,A) +
                ((B and C) or (B and D) or (C and D)) + E + W[t] + K[2];
        E := D;
        D := C;
        C := SHA1CircularShift(30,B);
        B := A;
        A := temp;
    end;

    for t := 60 to 79 do begin
        temp := SHA1CircularShift(5,A) + (B xor C xor D) + E + W[t] + K[3];
        E := D;
        D := C;
        C := SHA1CircularShift(30,B);
        B := A;
        A := temp;
    end;

    inc( context.Intermediate_Hash[0], A );
    inc( context.Intermediate_Hash[1], B );
    inc( context.Intermediate_Hash[2], C );
    inc( context.Intermediate_Hash[3], D );
    inc( context.Intermediate_Hash[4], E );

    context.Message_Block_Index := 0;
end;

// According to the standard, the message must be padded to an even
// 512 bits.  The first padding bit must be a '1'.  The last 64
// bits represent the length of the original message.  All bits in
// between should be 0.  This function will pad the message
// according to those rules by filling the Message_Block array
// accordingly.  It will also call the ProcessMessageBlock function
// provided appropriately.  When it returns, it can be assumed that
// the message digest has been computed.
procedure SHA1PadMessage( var context: SHA1Context );
begin
   (*
    *  Check to see if the current message block is too small to hold
    *  the initial padding bits and length.  If so, we will pad the
    *  block, process it, and then continue padding into a second
    *  block.
    *)
    if (context.Message_Block_Index > 55) then begin
        context.Message_Block[context.Message_Block_Index] := $80;
        inc( context.Message_Block_Index );
        while (context.Message_Block_Index < 64) do begin
            context.Message_Block[context.Message_Block_Index] := 0;
            inc( context.Message_Block_Index );
        end;

        SHA1ProcessMessageBlock( context );

        while (context.Message_Block_Index < 56) do begin
            context.Message_Block[context.Message_Block_Index] := 0;
            inc( context.Message_Block_Index );
        end;
    end else begin
        context.Message_Block[context.Message_Block_Index] := $80;
        inc( context.Message_Block_Index );
        while (context.Message_Block_Index < 56) do begin
            context.Message_Block[context.Message_Block_Index] := 0;
            inc( context.Message_Block_Index );
        end;
    end;

    // Store the message length as the last 8 octets
    context.Message_Block[56] := context.Length_High shr 24;
    context.Message_Block[57] := context.Length_High shr 16;
    context.Message_Block[58] := context.Length_High shr 8;
    context.Message_Block[59] := context.Length_High;
    context.Message_Block[60] := context.Length_Low shr 24;
    context.Message_Block[61] := context.Length_Low shr 16;
    context.Message_Block[62] := context.Length_Low shr 8;
    context.Message_Block[63] := context.Length_Low;

    SHA1ProcessMessageBlock(context);
end;

// This function will initialize the SHA1Context in preparation
// for computing a new SHA1 message digest.
function SHA1Reset( var context: SHA1Context ): Integer;
begin
   //FPiette
   if @context = nil then begin
       Result := shaNull;
       Exit;
   end;

   context.Length_Low           := 0;
   context.Length_High          := 0;
   context.Message_Block_Index  := 0;

   context.Intermediate_Hash[0] := $67452301;
   context.Intermediate_Hash[1] := $EFCDAB89;
   context.Intermediate_Hash[2] := $98BADCFE;
   context.Intermediate_Hash[3] := $10325476;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -