OSDN Git Service

2ちゃんねるのトリップ仕様の拡張に対応
[gikonavigoeson/gikonavi.git] / SHA1Unit.pas
diff --git a/SHA1Unit.pas b/SHA1Unit.pas
new file mode 100644 (file)
index 0000000..e485efa
--- /dev/null
@@ -0,0 +1,194 @@
+unit SHA1Unit;
+
+interface
+
+uses
+       Windows, SysUtils;
+
+const
+    SHA1_A = DWORD( $67452301 );
+    SHA1_B = DWORD( $EFCDAB89 );
+    SHA1_C = DWORD( $98BADCFE );
+    SHA1_D = DWORD( $10325476 );
+    SHA1_E = DWORD( $C3D2E1F0 );
+    SHA1_K1 = DWORD( $5A827999 );
+    SHA1_K2 = DWORD( $6ED9EBA1 );
+    SHA1_K3 = DWORD( $8F1BBCDC );
+    SHA1_K4 = DWORD( $CA62C1D6 );
+    LBMASK_HI = DWORD( $FF0000 );
+    LBMASK_LO = DWORD( $FF00 );
+
+type
+    TSHA1Digest = array [0..19] of Byte;
+    TSHA1Context = record
+        sdHi    : DWord;
+        sdLo    : DWord;
+        sdIndex : DWord;
+        sdHash  : array [0..4] of DWord;
+        sdBuf   : array [0..63] of Byte;
+    end;
+
+    function SHA1SwapByteOrder( n : DWORD ) : DWORD;
+    procedure HashSHA1( var Digest : TSHA1Digest; const Buf; BufSize : Longint );
+    procedure StringHashSHA1(var Digest : TSHA1Digest; const Str : string);
+    procedure SHA1Hash( var Context : TSHA1Context );
+
+implementation
+//! \95\8e\9a\97ñ\97pSHA1\83n\83b\83V\83\85\8eæ\93¾
+procedure StringHashSHA1(var Digest : TSHA1Digest; const Str : string);
+begin
+    HashSHA1(Digest, Str[1], Length(Str));
+end;
+//! SHA1\83n\83b\83V\83\85\8eæ\93¾
+procedure HashSHA1( var Digest : TSHA1Digest; const Buf; BufSize : Longint );
+var
+    Context : TSHA1Context;
+    PBuf: ^Byte;
+    procedure UpdateLen( var Context : TSHA1Context; Len : DWord );
+    begin
+        Inc( Context.sdLo,( Len shl 3 ));
+        if Context.sdLo < ( Len shl 3 ) then
+            Inc( Context.sdHi );
+        Inc( Context.sdHi, Len shr 29 );
+    end;
+begin
+    //0\96\84\82ß
+    fillchar( Context, SizeOf( Context ), 0 );
+    // \83}\83W\83b\83N\83i\83\93\83o\81[\82Å\8f\89\8aú\89»\82·\82é
+    Context.sdHash[ 0 ] := SHA1_A;
+    Context.sdHash[ 1 ] := SHA1_B;
+    Context.sdHash[ 2 ] := SHA1_C;
+    Context.sdHash[ 3 ] := SHA1_D;
+    Context.sdHash[ 4 ] := SHA1_E;
+
+    UpdateLen( Context, BufSize );
+    PBuf := @Buf;
+    while BufSize > 0 do begin
+        if ( Sizeof( Context.sdBuf ) - Context.sdIndex ) <= DWord( BufSize ) then begin
+            Move( PBuf^, Context.sdBuf[ Context.sdIndex ], Sizeof( Context.sdBuf ) - Context.sdIndex );
+            Dec( BufSize, Sizeof( Context.sdBuf ) - Context.sdIndex );
+            Inc( PBuf, Sizeof( Context.sdBuf ) - Context.sdIndex );
+            SHA1Hash( Context );
+        end else begin
+            Move( PBuf^, Context.sdBuf[ Context.sdIndex ], BufSize );
+            Inc( Context.sdIndex, BufSize );
+            BufSize := 0;
+        end;
+    end;
+
+    Context.sdBuf[ Context.sdIndex ] := $80;
+
+    if Context.sdIndex >= 56 then
+        SHA1Hash( Context );
+
+    PDWord( @Context.sdBuf[ 56 ])^ := SHA1SwapByteOrder( Context.sdHi );
+    PDWord( @Context.sdBuf[ 60 ])^ := SHA1SwapByteOrder( Context.sdLo );
+
+    SHA1Hash( Context );
+
+    Context.sdHash[ 0 ] := SHA1SwapByteOrder( Context.sdHash[ 0 ]);
+    Context.sdHash[ 1 ] := SHA1SwapByteOrder( Context.sdHash[ 1 ]);
+    Context.sdHash[ 2 ] := SHA1SwapByteOrder( Context.sdHash[ 2 ]);
+    Context.sdHash[ 3 ] := SHA1SwapByteOrder( Context.sdHash[ 3 ]);
+    Context.sdHash[ 4 ] := SHA1SwapByteOrder( Context.sdHash[ 4 ]);
+
+    Move( Context.sdHash, Digest, Sizeof( Digest ));
+end;
+//! \83n\83b\83V\83\85\8f\88\97\9d
+procedure SHA1Hash( var Context : TSHA1Context );
+var
+    A : DWord;
+    B : DWord;
+    C : DWord;
+    D : DWord;
+    E : DWord;
+
+    temp : DWord;
+    W : array[ 0..79 ] of DWord;
+
+    i : Longint;
+    function SHA1CircularShift(I, C : DWord) : DWord; register;
+    asm
+        mov  ecx, edx
+        rol  eax, cl
+    end;
+begin
+    with Context do begin
+        sdIndex:= 0;
+        Move( sdBuf, W, Sizeof( W ));
+
+        // Initialize the first 16 words in the array W
+        for i := 0 to 15 do begin
+            W[ i ]:= SHA1SwapByteOrder( W[ i ] );
+        end;
+
+        // Transform Message block from 16 32 bit words to 80 32 bit words
+        // Wt, = ( Wt-3 xor Wt-8 xor Wt-13 xor Wt-16 ) rolL 1 : Wt is W sub t
+        for i:= 16 to 79 do begin
+            W[i]:= SHA1CircularShift( W[ i - 3 ] xor W[ i - 8 ] xor W[ i - 14 ] xor W[ i - 16 ], 1 );
+        end;
+
+        A := sdHash[ 0 ];
+        B := sdHash[ 1 ];
+        C := sdHash[ 2 ];
+        D := sdHash[ 3 ];
+        E := sdHash[ 4 ];
+
+        // the four rounds
+        for i:= 0 to 19 do begin
+            temp    := SHA1CircularShift( A, 5 ) + ( D xor ( B and ( C xor D ))) + E + W[ i ] + SHA1_K1;
+            E       := D;
+            D       := C;
+            C       := SHA1CircularShift( B, 30 );
+            B       := A;
+            A       := temp;
+        end;
+
+        for i:= 20 to 39 do begin
+            temp    := SHA1CircularShift( A, 5 ) + ( B xor C xor D ) + E + W[ i ] + SHA1_K2;
+            E       := D;
+            D       := C;
+            C       := SHA1CircularShift( B, 30 );
+            B       := A;
+            A       := temp;
+        end;
+
+        for i:= 40 to 59 do begin
+            temp    := SHA1CircularShift( A, 5 ) + (( B and C ) or ( D and ( B or C ))) + E + W[ i ] + SHA1_K3;
+            E       := D;
+            D       := C;
+            C       := SHA1CircularShift( B, 30 );
+            B       := A;
+            A       := temp;
+        end;
+
+        for i:= 60 to 79 do
+        begin
+            temp    := SHA1CircularShift( A, 5 ) + ( B xor C xor D ) + E + W[ i ] + SHA1_K4;
+            E       := D;
+            D       := C;
+            C       := SHA1CircularShift( B, 30 );
+            B       := A;
+            A       := temp;
+        end;
+
+        sdHash[ 0 ]:= sdHash[ 0 ] + A;
+        sdHash[ 1 ]:= sdHash[ 1 ] + B;
+        sdHash[ 2 ]:= sdHash[ 2 ] + C;
+        sdHash[ 3 ]:= sdHash[ 3 ] + D;
+        sdHash[ 4 ]:= sdHash[ 4 ] + E;
+
+        FillChar( W, Sizeof( W ), 0 );
+        FillChar( sdBuf, Sizeof( sdBuf ), 0 );
+    end;
+end;
+
+//! \8fã\88Ê\83o\83C\83g\82Æ\89º\88Ê\83o\83C\83g\82Ì\93ü\82ê\91Ö\82¦
+function SHA1SwapByteOrder( n : DWORD ) : DWORD;
+begin
+    n := ( n shr 24 ) or (( n shr 8 ) and LBMASK_LO )
+       or (( n shl 8 ) and LBMASK_HI ) or ( n shl 24 );
+    Result := n;
+end;
+
+end.