DO NOT USE THIS CODE The result SHA string has an endian problem. The code at http://www.powerbasic.com/support/fo...ML/000755.html also returns incorrect hash.
I'll leave it here as an example of an easy mistake to make. Corrected code in next post.
I'll leave it here as an example of an easy mistake to make. Corrected code in next post.
Code:
'******************************************************************************* 'File: SHA-1.inc 'Contains the CalcSHA function. 'An implementation of Secure Hash Algorithm 1 (SHA-1) described in the Federal 'Information Processing Standards (FIPS) Publication 180-2, dated '2002 August 1 (supersedes FIPS 180-1). ' ' ************************************************* ' * This implementation of SHA-1 is placed in the * ' * Public Domain without warranty of any kind. * ' * - Use at your own risk. - * ' ************************************************* ' ' ## Important Note ############################################### ' # From FIPS 180-2, paragraph 8: # ' # "Only algorithm implementations that are validated by # ' # NIST will be considered as complying with this standard." # ' # # ' # While this implementation correctly calculates the examples # ' # in FIPS 180-2, Appendix A; it has NOT been validated by NIST. # ' ################################################################# ' '------------------------------------------------------------------------------- 'Credits/info as downloaded from - ' http://www.pbcrypto.com/view.php?algorithm=sha-1 'NAME: SHA-1 'CREATOR: NIST and NSA 'PB AUTHOR: Semen Matusovski 'DESCRIPTION: Creates a 160-bit hash (message digest) from messages up to '264 bits. 'NOTES: Produces a message digest of 160 bits, providing no more than 80 bits 'of security against collision attacks. 'SOURCE: http://www.powerbasic.com/support/forums/Forum7/HTML/000755.html '------------------------------------------------------------------------------- 'Modifications by Dale Yarker. ' I probably could not have written a SHA-1 function myself using only the ' information in the FIPS, and certainly not in assembly. Thanks Semen! ' While trying to read through the code to understand how it works, and to ' compare it with the FIPS, I was struck by the lack of comments and ' meaningful indentation. My objective is to make the code "over commented" for ' everyone except very beginner programmers. ' 'Comments within curly braces, "{}", describe changes I made to Semen's code. ' 'Comments within square braces, "[]", are the variable names used in ' FIPS 180-2; which may, or may not be different here. ' 'Other comments maybe Semen's or mine. '******************************************************************************* '#compile exe 'as opposed to dll. '#register none 'turn off automatic assignment of vars to CPU registers by the 'compiler due to heavy use of registers in assember section. '#dim all 'force declaration/casting of vars before use. '#Include "Win32Api.Inc" '{Didn't have this file, then turned out not to matter. See Speed Test.} '$FileNm = "Win322.hlp" '{Type name from "SHA" to "SHAtype" because it conflicted with variable ' having the same name at compile time. Long to dword.} 'type DWrd5_Type ' H0 as dword ' H1 as dword ' H2 as dword ' H3 as dword ' H4 as dword 'end type 'union DWrd5_Str_Union ' dw5 as DWrd5_Type ' Str as string * 20 'end union '------------------------------------------------------------------------------- sub CalcSHA1 alias "CALCULATE_SECURE_HASH_ALGORITHM_1" (byref Str as string, _ byref SH_Out as string * 20) export #register none '- - - - - - - - - - - - - - local lStr as long '[l message in bits], here as length in bytes dim nq as long '[N] number of blocks in Message (padded) local n as long 'Nunber of dwords in Message local adrW, adrWW as dword 'pointers to Message and Schedule arrays. 'local SH as DWrd5_Str_Union '[H0 - H4] Hash Values as dword or string local H0, H1, H2, H3, H4 as dword local pSH_Out as dword pointer dim W(0 to 79) as dword '[W] Message Schedule {colon to TO} local A, B, C, D, E as dword '[working variables] local TEMP as long '[TEMP] '- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 'Pad last block of 512 bits (is 64 bytes or 16 dwords) lStr = len(Str) nq = fix((lStr + 8) / 64) + 1 'calc number of blocks n = 16 * nq 'calc number of dwords in WW() redim WW(0 to n - 1) as dword '[M] The Message, last block padded with "0"s. WW(n - 1) = lStr * 8 'Put count of last block Message bits in last dword. adrW = varptr(W(0)) adrWW = varptr(WW(0)) A = strptr(Str) 'Labels CalcSHA_Lbl01 thru CalcSHA_Lbl04 used to form loops. 'Labels CalcSHA_Lbl05 thru CalcSHA_Lbl08 are jump targets, conditionally 'skipping sections of code (all jumps forward). 'save current EDI and ESI to stack before using those registers ! PUSH EDI ! PUSH ESI ! MOV EDI, adrWW ! MOV ESI, A ! MOV ECX, lStr ! REP MOVSB 'repeat string operation 'Append a "1" bit after last Message bit in last block ! MOV CL, &H80 ! MOV [EDI], CL 'Loop 1 setup ! MOV EDI, adrWW ! MOV ECX, 2 'Start Loop 1, copy Str to WW() CalcSHA_Lbl01: ! MOV AX, [EDI] ! MOV DX, [EDI + 2] ! MOV [EDI], DH ! MOV [EDI + 1], DL ! MOV [EDI + 2], AH ! MOV [EDI + 3], AL ! ADD EDI, 4 ! INC ECX ! CMP ECX, n ! JNE CalcSHA_Lbl01 'End Loop 1 'set initial hash value ! MOV H0, &H67452301& ! MOV H1, &HEFCDAB89& ! MOV H2, &H98BADCFE& ! MOV H3, &H10325476& ! MOV H4, &HC3D2E1F0& 'Start Loop 2, move a block from Message into Message schedule CalcSHA_Lbl02: ! MOV EDI, adrW ! MOV ESI, adrWW ! MOV ECX, 64 ! REP MOVSB ! MOV adrWW, ESI 'Loop 3 setup ! MOV ECX, 0 'Start Loop 3 CalcSHA_Lbl03: ! MOV ESI, ECX ! ADD ESI, ESI ! ADD ESI, ESI ! ADD ESI, adrW ! MOV EAX, [ESI + 52] ! XOR EAX, [ESI + 32] ! XOR EAX, [ESI + 8] ! XOR EAX, [ESI] ! MOV EDX, EAX ! SHL EAX, 1 ! SHR EDX, 31 ! OR EAX, EDX ! MOV [ESI + 64], EAX ! INC ECX ! CMP ECX, 64 ! JNE CalcSHA_Lbl03 'End Loop 3 ! MOV EAX, H0 ! MOV A, EAX ! MOV EAX, H1 ! MOV B, EAX ! MOV EAX, H2 ! MOV C, EAX ! MOV EAX, H3 ! MOV D, EAX ! MOV EAX, H4 ! MOV E, EAX 'Loop 4 setup ! MOV EDI, 0 'Start Loop 4 CalcSHA_Lbl04: ! CMP EDI, 19 ! JA CalcSHA_Lbl05 ! MOV ECX, B ! AND ECX, C ! MOV EAX, B ! NOT EAX ! AND EAX, D ! OR ECX, EAX ! ADD ECX, &H5A827999& ! JMP CalcSHA_Lbl08 CalcSHA_Lbl05: ! CMP EDI, 39 ! JA CalcSHA_Lbl06 ! MOV ECX, B ! XOR ECX, C ! XOR ECX, D ! ADD ECX, &H6ED9EBA1& ! JMP CalcSHA_Lbl08 CalcSHA_Lbl06: ! CMP EDI, 59 ! JA CalcSHA_Lbl07 ! MOV EAX, B ! AND EAX, C ! MOV ECX, B ! AND ECX, D ! MOV EDX, C ! AND EDX, D ! OR ECX, EAX ! OR ECX, EDX ! ADD ECX, &H8F1BBCDC& ! JMP CalcSHA_Lbl08 CalcSHA_Lbl07: ! MOV ECX, B ! XOR ECX, C ! XOR ECX, D ! ADD ECX, &HCA62C1D6& CalcSHA_Lbl08: ! MOV EAX, A ! MOV EDX, EAX ! SHL EAX, 5 ! SHR EDX, 27 ! OR EAX, EDX ! ADD EAX, E ! ADD ECX, EAX ! MOV ESI, EDI ! ADD ESI, ESI ! ADD ESI, ESI ! ADD ESI, adrW ! MOV ESI, [ESI] ! MOV TEMP, ESI ! ADD Temp, ECX ! MOV EAX, D ! MOV E, EAX ! MOV EAX, C ! MOV D, EAX ! MOV EAX, B ! MOV EDX, EAX ! SHL EAX, 30 ! SHR EDX, 2 ! OR EAX, EDX ! MOV C, EAX ! MOV EAX, A ! MOV B, EAX ! MOV EAX, TEMP ! MOV A, EAX ! INC EDI ! CMP EDI, 80 ! JNE CalcSHA_Lbl04 'End Loop 4 ! MOV EAX, A ! ADD H0, EAX ! MOV EAX, B ! ADD H1, EAX ! MOV EAX, C ! ADD H2, EAX ! MOV EAX, D ! ADD H3, EAX ! MOV EAX, E ! ADD H4, EAX ! SUB nq, 1 ! JNE CalcSHA_Lbl02 'done if nq = 0 'End Loop 2 'restore previous ESI and EDI from stack ! POP ESI ! POP EDI 'set return hash pSH_Out = varptr(SH_Out) @pSH_Out = H0 incr pSH_Out @pSH_Out = H1 incr pSH_Out @pSH_Out = H2 incr pSH_Out @pSH_Out = H3 incr pSH_Out @pSH_Out = H4 incr pSH_Out end sub '-------------------------------------------------------------------------------
Comment