Here a Class for SHA256 based on Code by Greg Turgeon. It is a very fast code for this generator.
I tested a file with 11.3Gb. Duration: 226 seconds. This corresponds 50MB/s on i5 M460 @2x2,53 GHz
Program for test
I tested a file with 11.3Gb. Duration: 226 seconds. This corresponds 50MB/s on i5 M460 @2x2,53 GHz
Code:
[B][COLOR="YellowGreen"]'===================================================================== ' This class '[B]SHA256hash.inc[/B]' was generated ' from the following code: '===================================================================== '-- SHA256c.INC '-- WIN32 API not required '-- Uses no global data '-- http://www.powerbasic.com/support/pbforums/showthread.php?t=39850 '=====================================================================[/COLOR][/B] %TRUE = 1 %FALSE = 0 %RETURN_LITTLE_ENDIAN = %TRUE [COLOR="YellowGreen"][B]'-- Set to %FALSE to return big-endian hash$ (as in 2001 code)[/B][/COLOR] %ALIGNMENT = 16 %HASHLEN = 32 [B][COLOR="YellowGreen"] 'bytes[/COLOR][/B] %BLOCKSIZE = 64 [B][COLOR="YellowGreen"]'bytes[/COLOR][/B] %FILE_BUFFERSIZE = 32000 [B][COLOR="YellowGreen"]'bytes[/COLOR][/B] %S_ARRAY_SIZE = (%HASHLEN) %W_ARRAY_SIZE = (%BLOCKSIZE*4) TYPE SHA256_CONTEXT state AS STRING * (%HASHLEN+%ALIGNMENT) pstate AS DWORD PTR pdata AS BYTE PTR lendata AS DWORD HasSSE2 AS LONG HasMMX AS LONG k_array AS LONG PTR s_array AS LONG PTR w_array AS LONG PTR Workspace AS STRING * (%S_ARRAY_SIZE + %W_ARRAY_SIZE + (%ALIGNMENT * 2)) [COLOR="YellowGreen"][B]'w_array&() + s+_array&()[/B][/COLOR] END TYPE MACRO align(p,alignment)=((p+(alignment-1)) AND (NOT(alignment-1))) ASMDATA Init_Values DD &h6A09E667???, &hBB67AE85???, &h3C6EF372???, &hA54FF53A??? DD &h510E527F???, &h9B05688C???, &h1F83D9AB???, &h5BE0CD19??? END ASMDATA ASMDATA K_Array_Data DD &h428a2f98???, &h71374491???, &hb5c0fbcf???, &he9b5dba5???, &h3956c25b???, &h59f111f1??? DD &h923f82a4???, &hab1c5ed5???, &hd807aa98???, &h12835b01???, &h243185be???, &h550c7dc3??? DD &h72be5d74???, &h80deb1fe???, &h9bdc06a7???, &hc19bf174???, &he49b69c1???, &hefbe4786??? DD &h0fc19dc6???, &h240ca1cc???, &h2de92c6f???, &h4a7484aa???, &h5cb0a9dc???, &h76f988da??? DD &h983e5152???, &ha831c66d???, &hb00327c8???, &hbf597fc7???, &hc6e00bf3???, &hd5a79147??? DD &h06ca6351???, &h14292967???, &h27b70a85???, &h2e1b2138???, &h4d2c6dfc???, &h53380d13??? DD &h650a7354???, &h766a0abb???, &h81c2c92e???, &h92722c85???, &ha2bfe8a1???, &ha81a664b??? DD &hc24b8b70???, &hc76c51a3???, &hd192e819???, &hd6990624???, &hf40e3585???, &h106aa070??? DD &h19a4c116???, &h1e376c08???, &h2748774c???, &h34b0bcb5???, &h391c0cb3???, &h4ed8aa4a??? DD &h5b9cca4f???, &h682e6ff3???, &h748f82ee???, &h78a5636f???, &h84c87814???, &h8cc70208??? DD &h90befffa???, &ha4506ceb???, &hbef9a3f7???, &hc67178f2??? END ASMDATA CLASS cSHA256hash INSTANCE m_ctx AS SHA256_CONTEXT INSTANCE m_compress AS LONG INSTANCE m_filesize AS QUAD INSTANCE m_bytesleft AS QUAD INSTANCE m_buffer AS STRING INSTANCE m_padding AS STRING INSTANCE m_hHash AS DWORD INSTANCE m_infile AS LONG INSTANCE m_lastpass AS LONG INSTANCE m_maxstring AS LONG '==================== CLASS METHOD Init() LOCAL pInit, pworkspace, pstate AS LONG RESET m_ctx m_ctx.k_array = CODEPTR(K_Array_Data) pInit = CODEPTR(Init_Values) pworkspace = align(VARPTR(m_ctx.Workspace), %ALIGNMENT) m_ctx.s_array = pworkspace m_ctx.w_array = pworkspace + %S_ARRAY_SIZE m_ctx.pstate = align(VARPTR(m_ctx.state), %ALIGNMENT) pstate = m_ctx.pstate ! push esi ! push edi ! mov esi, pInit ! mov edi, pstate ! mov ecx, 8 ! cld ! rep movsd ! pop edi ! pop esi END METHOD '==================== CLASS METHOD Compress128() #REGISTER NONE LOCAL k_array, s_array, w_array AS LONG LOCAL pstate, pdata, wi, ki, i AS LONG '-- Copy for inline assembler w_array = m_ctx.w_array s_array = m_ctx.s_array k_array = m_ctx.k_array pstate = m_ctx.pstate pdata = m_ctx.pdata ! push esi ! push edi ! push ebx '-- Copy current state into s&() ! mov esi, pstate ;esi -> pm_ctx.state0 ! mov edi, s_array ! movdqa xmm0, [esi] ! movdqa xmm1, [esi+16] ! movdqa [edi], xmm0 ! movdqa [edi+16],xmm1 '-- Copy current data block to w&() w/little-to-big endian conversion ! mov esi, pdata ! mov edi, w_array ! movdqu xmm0, [esi] ! movdqu xmm2, [esi+16] ! movdqu xmm4, [esi+32] ! movdqu xmm6, [esi+48] ! pshufhw xmm1, xmm0, &b10110001 ! pshufhw xmm3, xmm2, &b10110001 ! pshufhw xmm5, xmm4, &b10110001 ! pshufhw xmm7, xmm6, &b10110001 ! pshuflw xmm0, xmm1, &b10110001 ! pshuflw xmm2, xmm3, &b10110001 ! pshuflw xmm4, xmm5, &b10110001 ! pshuflw xmm6, xmm7, &b10110001 ! movdqa xmm1, xmm0 ! movdqa xmm3, xmm2 ! movdqa xmm5, xmm4 ! movdqa xmm7, xmm6 ! psllw xmm0, 8 ! psllw xmm2, 8 ! psllw xmm4, 8 ! psllw xmm6, 8 ! psrlw xmm1, 8 ! psrlw xmm3, 8 ! psrlw xmm5, 8 ! psrlw xmm7, 8 ! por xmm0, xmm1 ! por xmm2, xmm3 ! por xmm4, xmm5 ! por xmm6, xmm7 ! movdqa [edi], xmm0 ! movdqa [edi+16],xmm2 ! movdqa [edi+32],xmm4 ! movdqa [edi+48],xmm6 '-- Fill W[16to63] ! mov esi, w_array ! push ebp ! mov ebp, 16 #ALIGN 4 FillTop: ! mov ebx, ebp ! sub ebx, 2 ! mov eax, [esi+ebx*4] ! mov ecx, eax ! mov edx, ecx ! sub ebx, 13 ;prep for next access: (-2)+(-13) = -15 ! ror eax, 17 ! ror ecx, 19 ! shr edx, 10 ! xor eax, ecx ! xor eax, edx ! mov edi, eax ;edi = temp total ! mov eax, [esi+ebx*4] ! mov ecx, eax ! mov edx, ecx ! ror eax, 7 ! ror ecx, 18 ! shr edx, 3 ! add ebx, 8 ;= (-15)+8 = -7 ! xor eax, ecx ! xor eax, edx ! add edi, eax ! mov eax, [esi+ebx*4] ! sub ebx, 9 ;= (-7)+(-9) = -16 ! add edi, eax ! mov eax, [esi+ebx*4] ! mov ebx, ebp ! add eax, edi ! inc ebp ! mov [esi+ebx*4], eax ! test ebp, &b111111 ;<64? ! jnz FillTop ! pop ebp '-- Compress: i& = 0 to 63 ! xor eax, eax ! mov esi, s_array ;here to CompressDone & END SUB: esi -> s[0] ! mov i, eax #ALIGN 4 CompressTop: ! mov ebx, eax ! mov edx, w_array ! mov eax, [edx+ebx*4] ! mov wi, eax ! mov edx, k_array ! mov eax, [edx+ebx*4] ! mov ki, eax ! mov eax, [esi+16] ! mov ecx, [esi+20] ! mov ebx, eax ! mov edx, eax ! and eax, [esi+20] ! not edx ! and edx, [esi+24] ! xor eax, edx ! mov ecx, ebx ! mov ebx, eax ! mov eax, ecx ! mov edx, ecx ! ror eax, 6 ! ror ecx, 11 ! ror edx, 25 ! add ebx, ki ! xor eax, ecx ! add ebx, wi ! xor eax, edx ! add eax, ebx ! add eax, [esi+28] ! movd xmm6, eax ;xmm6 = t0 ! mov eax, [esi] ! mov ecx, [esi+4] ! mov ebx, eax ! mov edx, eax ! and eax, ecx ! and edx, [esi+8] ! xor eax, edx ! and ecx, [esi+8] ! xor eax, ecx ! mov edx, eax ! mov eax, ebx ! mov ecx, ebx ! ror eax, 2 ! ror ecx, 13 ! ror ebx, 22 ! xor eax, ecx ! xor eax, ebx ! add eax, edx ! movd xmm7, eax ;xmm7 = t1 ' @s[7] = @s[6] : @s[6] = @s[5] : @s[5] = @s[4] : @s[4] = @s[3] + t0& ' @s[3] = @s[2] : @s[2] = @s[1] : @s[1] = @s[0] : @s[0] = t0& + t1& #ALIGN 16 ! movdqa xmm0, [esi] ! movdqa xmm1, [esi+16] ! movd xmm3, [esi+12] ;xmm3 = @s[3] ! pslldq xmm1, 4 ! pslldq xmm0, 4 ! paddd xmm1, xmm3 ;xmm1[0] = @s{3] ! paddd xmm0, xmm6 ;+t0 ! paddd xmm1, xmm6 ;+t0 ! paddd xmm0, xmm7 ;+t1 ! movdqa [esi+16],xmm1 ! movdqa [esi], xmm0 ! mov eax, i ! inc eax ! test eax, &b111111 ;<64? ! mov i, eax ! jnz CompressTop '-- Add current state s() to context ' for i& = 0 to 7 : [email protected][i&] = [email protected][i&] + @s[i&] : next i& ! mov edi, pstate ! movdqa xmm0, [edi] ! movdqa xmm1, [edi+16] ! paddd xmm0, [esi] ! paddd xmm1, [esi+16] ! movdqa [edi], xmm0 ! movdqa [edi+16],xmm1 ! pop ebx ! pop edi ! pop esi END METHOD '==================== CLASS METHOD Compress64() #REGISTER NONE LOCAL k_array, s_array, w_array AS LONG LOCAL pstate, pdata, wi, ki, i AS LONG '-- Copy for inline assembler w_array = m_ctx.w_array s_array = m_ctx.s_array k_array = m_ctx.k_array pstate = m_ctx.pstate pdata = m_ctx.pdata ! push esi ! push edi ! push ebx '-- Copy current state into s&() ! mov esi, pstate ;esi -> pm_ctx.state0 ! mov edi, s_array ! movq mm0, [esi] ! movq mm1, [esi+8] ! movq mm2, [esi+16] ! movq mm3, [esi+24] ! movq [edi], mm0 ! movq [edi+8], mm1 ! movq [edi+16],mm2 ! movq [edi+24],mm3 '-- Copy current data block to w&() w/little-to-big endian conversion ! mov esi, pdata ! mov edi, w_array ! mov ecx, %BLOCKSIZE #ALIGN 4 BSwapCopyTop: ! sub ecx, 4 ! mov eax, [esi+ecx] ! sub ecx, 4 ! bswap eax ! mov edx, [esi+ecx] ! mov [edi+ecx+4], eax ! bswap edx ! test ecx, ecx ! mov [edi+ecx], edx ! jnz BSwapCopyTop '-- Fill W[16to63] ! mov esi, w_array ! push ebp ! mov ebp, 16 #ALIGN 4 FillTop: ! mov ebx, ebp ! sub ebx, 2 ! mov eax, [esi+ebx*4] ! mov ecx, eax ! mov edx, ecx ! sub ebx, 13 ;prep for next access: (-2)+(-13) = -15 ! ror eax, 17 ! ror ecx, 19 ! shr edx, 10 ! xor eax, ecx ! xor eax, edx ! mov edi, eax ;edi = temp total ! mov eax, [esi+ebx*4] ! mov ecx, eax ! mov edx, ecx ! ror eax, 7 ! ror ecx, 18 ! shr edx, 3 ! add ebx, 8 ;= (-15)+8 = -7 ! xor eax, ecx ! xor eax, edx ! add edi, eax ! mov eax, [esi+ebx*4] ! sub ebx, 9 ;= (-7)+(-9) = -16 ! add edi, eax ! mov eax, [esi+ebx*4] ! mov ebx, ebp ! add eax, edi ! inc ebp ! mov [esi+ebx*4], eax ! test ebp, &b111111 ;<64? ! jnz FillTop ! pop ebp '-- Compress: i& = 0 to 63 ! xor eax, eax ! mov esi, s_array ;here to CompressDone & END SUB: esi -> s[0] ! mov i, eax #ALIGN 4 CompressTop: ! mov ebx, eax ! mov edx, w_array ! mov eax, [edx+ebx*4] ! mov wi, eax ! mov edx, k_array ! mov eax, [edx+ebx*4] ! mov ki, eax ! mov eax, [esi+16] ! mov ecx, [esi+20] ! mov ebx, eax ! mov edx, eax ! and eax, [esi+20] ! not edx ! and edx, [esi+24] ! xor eax, edx ! mov ecx, ebx ! mov ebx, eax ! mov eax, ecx ! mov edx, ecx ! ror eax, 6 ! ror ecx, 11 ! ror edx, 25 ! add ebx, ki ! xor eax, ecx ! add ebx, wi ! xor eax, edx ! add eax, ebx ! add eax, [esi+28] ! movd mm6, eax ;mm6 = t0 ! mov eax, [esi] ! mov ecx, [esi+4] ! mov ebx, eax ! mov edx, eax ! and eax, ecx ! and edx, [esi+8] ! xor eax, edx ! and ecx, [esi+8] ! xor eax, ecx ! mov edx, eax ! mov eax, ebx ! mov ecx, ebx ! ror eax, 2 ! ror ecx, 13 ! ror ebx, 22 ! xor eax, ecx ! xor eax, ebx ! add eax, edx ! movd mm7, eax ;mm7 = t1 ' @s[7] = @s[6] : @s[6] = @s[5] : @s[5] = @s[4] : @s[4] = @s[3] + t0& ' @s[3] = @s[2] : @s[2] = @s[1] : @s[1] = @s[0] : @s[0] = t0& + t1& #ALIGN 8 ! movq mm3, [esi+20] ;mm3 = @s[6-5] ! movq mm2, [esi+12] ;mm2 = @s[4-3] ! movq mm1, [esi+4] ;mm1 = @s[2-1] ! movq mm0, [esi] ;mm0 = @s[1-0] ! psllq mm0, 32 ;mm0 = @s[0- ] ! paddd mm2, mm6 ;+t0 ! paddd mm0, mm6 ;+t0 ! paddd mm0, mm7 ;+t1 ! movq [esi+24],mm3 ! movq [esi+16],mm2 ! movq [esi+8], mm1 ! movq [esi], mm0 ! mov eax, i ! inc eax ! test eax, &b111111 ;<64? ! mov i, eax ! jnz CompressTop '-- Add current state s() to context ' for i& = 0 to 7 : [email protected][i&] = [email protected][i&] + @s[i&] : next i& ! mov edi, pstate ! movq mm0, [edi] ! movq mm1, [edi+8] ! movq mm2, [edi+16] ! movq mm3, [edi+24] ! paddd mm0, [esi] ! paddd mm1, [esi+8] ! paddd mm2, [esi+16] ! paddd mm3, [esi+24] ! movq [edi], mm0 ! movq [edi+8], mm1 ! movq [edi+16],mm2 ! movq [edi+24],mm3 ! emms ! pop ebx ! pop edi ! pop esi END METHOD '==================== CLASS METHOD Compress32() #REGISTER NONE LOCAL k_array, s_array, w_array AS LONG LOCAL pstate, pdata AS LONG LOCAL t0, t1, wi, ki, i AS LONG '-- Copy for inline assembler w_array = m_ctx.w_array s_array = m_ctx.s_array k_array = m_ctx.k_array pstate = m_ctx.pstate pdata = m_ctx.pdata ! push esi ! push edi ! push ebx '-- Copy current state into s&() ! mov esi, pstate ;esi -> pm_ctx.state0 ! mov edi, s_array ! mov ecx, 8 ! cld ! rep movsd '-- Copy current data block to w&() w/little-to-big endian conversion ! mov esi, pdata ! mov edi, w_array ! mov ecx, %BLOCKSIZE #ALIGN 4 BSwapCopyTop: ! sub ecx, 4 ! mov eax, [esi+ecx] ! sub ecx, 4 ! bswap eax ! mov edx, [esi+ecx] ! mov [edi+ecx+4],eax ! bswap edx ! test ecx, ecx ! mov [edi+ecx], edx ! jnz BSwapCopyTop '-- Fill W[16to63] ! mov esi, w_array ! push ebp ! mov ebp, 16 #ALIGN 4 FillTop: ! mov ebx, ebp ! sub ebx, 2 ! mov eax, [esi]+[ebx*4] ! mov ecx, eax ! mov edx, ecx ! sub ebx, 13 ;prep for next access: (-2)+(-13) = -15 ! ror eax, 17 ! ror ecx, 19 ! shr edx, 10 ! xor eax, ecx ! xor eax, edx ! mov edi, eax ;edi = temp total ! mov eax, [esi]+[ebx*4] ! mov ecx, eax ! mov edx, ecx ! ror eax, 7 ! ror ecx, 18 ! shr edx, 3 ! add ebx, 8 ;= (-15)+8 = -7 ! xor eax, ecx ! xor eax, edx ! add edi, eax ! mov eax, [esi]+[ebx*4] ! sub ebx, 9 ;= (-7)+(-9) = -16 ! add edi, eax ! mov eax, [esi]+[ebx*4] ! mov ebx, ebp ! add eax, edi ! inc ebp ! mov [esi]+[ebx*4], eax ! cmp ebp, 63 ! jg FillDone ! jmp FillTop FillDone: ! pop ebp '-- Compress: i& = 0 to 63 ! xor eax, eax ! mov esi, s_array ;here to CompressDone & END SUB: esi -> s[0] ! mov i, eax #ALIGN 4 CompressTop: ! mov ebx, eax ! mov edx, w_array ! mov eax, [edx]+[ebx*4] ! mov wi, eax ! mov edx, k_array& ! mov eax, [edx]+[ebx*4] ! mov ki, eax ! mov eax, [esi+16] ! mov ecx, [esi+20] ! mov ebx, eax ! mov edx, eax ! and eax, [esi+20] ! not edx ! and edx, [esi+24] ! xor eax, edx ! mov ecx, ebx ! mov ebx, eax ! mov eax, ecx ! mov edx, ecx ! ror eax, 6 ! ror ecx, 11 ! ror edx, 25 ! add ebx, ki ! xor eax, ecx ! add ebx, wi ! xor eax, edx ! add eax, ebx ! add eax, [esi+28] ! mov t0&, eax ! mov eax, [esi] ! mov ecx, [esi+4] ! mov ebx, eax ! mov edx, eax ! and eax, ecx ! and edx, [esi+8] ! xor eax, edx ! and ecx, [esi+8] ! xor eax, ecx ! mov edx, eax ! mov eax, ebx ! mov ecx, ebx ! ror eax, 2 ! ror ecx, 13 ! ror ebx, 22 ! xor eax, ecx ! xor eax, ebx ! add eax, edx ! mov t1, eax ' @s[7] = @s[6] : @s[6] = @s[5] : @s[5] = @s[4] : @s[4] = @s[3] + t0& ' @s[3] = @s[2] : @s[2] = @s[1] : @s[1] = @s[0] : @s[0] = t0& + t1& ! mov edi, esi ! mov ecx, t0 ! mov eax, [esi+24] ;@s[7] = @s[6] ! mov ebx, [esi+20] ;@s[6] = @s[5] ! mov edx, [esi+16] ;@s[5] = @s[4] ! mov [edi+28], eax ! mov [edi+24], ebx ! mov [edi+20], edx ! mov eax, [esi+12] ;@s[4] = @s[3] + T0& ! mov ebx, [esi+8] ;@s[3] = @s[2] ! add eax, ecx ! mov edx, [esi] ;@s[1] = @s[0] ! mov [edi+12],ebx ! mov [edi+16],eax ! mov ebx, ecx ;@s[0] = T0& + T1& ! mov eax, [esi+4] ;@s[2] = @s[1] ! mov [edi+4], edx ! add ebx, t1 ! mov [edi+8], eax ! mov [edi], ebx ! mov eax, i ! inc eax ! test eax, &b111111 ;<64? ! mov i, eax ! jnz CompressTop '-- Add current state s() to context ' for i& = 0 to 7 : [email protected][i&] = [email protected][i&] + @s[i&] : next i& ! mov edi, pstate ! mov ecx, %HASHLEN #ALIGN 4 AddCopyTop: ! sub ecx, 4 ! mov eax, [edi+ecx] ! add eax, [esi+ecx] ! mov [edi+ecx], eax ! test ecx, ecx ! jnz AddCopyTop ! pop ebx ! pop edi ! pop esi END METHOD '==================== '-- Expects parameter Hash to point to buffer of correct size of %HASHLEN bytes (256bits\8) CLASS METHOD calcBuffer (BYVAL hData AS DWORD, BYVAL Length AS DWORD, BYVAL hHash AS DWORD) AS LONG REGISTER i AS DWORD LOCAL pstate AS LONG LOCAL lastbuff AS STRING LOCAL DataBuffer AS BYTE PTR LOCAL phash AS DWORD PTR DataBuffer = hData m_hHash = hHash i = Length AND (%BLOCKSIZE-1) lastbuff = PEEK$((DataBuffer+Length)-i, i) lastbuff = lastbuff + me.MakePadding(Length) m_ctx.lendata = Length m_ctx.pdata = DataBuffer i = Length AND (NOT %BLOCKSIZE-1) DO WHILE i > 0 SELECT CASE m_compress CASE 128: CALL me.Compress128() CASE 64: CALL me.Compress64() CASE ELSE: CALL me.Compress32() END SELECT m_ctx.pdata = m_ctx.pdata + %BLOCKSIZE i = i - %BLOCKSIZE LOOP m_ctx.pdata = STRPTR(lastbuff) m_ctx.lendata = LEN(lastbuff) DO WHILE m_ctx.lendata > 0 SELECT CASE m_compress CASE 128: CALL me.Compress128() CASE 64: CALL me.Compress64() CASE ELSE: CALL me.Compress32() END SELECT m_ctx.pdata = m_ctx.pdata + %BLOCKSIZE m_ctx.lendata = m_ctx.lendata - %BLOCKSIZE LOOP phash = m_hHash pstate = m_ctx.pstate '-- Copy current state from s&() to Hash 'for i = 0 to (%HASHLEN\4)-1 : @phash[i] = [email protected][i] : next i: exit method #IF %RETURN_LITTLE_ENDIAN ! push edi ! mov edx, pstate ;esi -> m_ctx.state0 ! mov edi, phash ! mov ecx, (%HASHLEN\4)-1 ;here -1 #ALIGN 4 LoopTop: ! mov eax, [edx+ecx*4] ! bswap eax ! mov [edi+ecx*4],eax ! dec ecx ! jns LoopTop ! pop edi #ELSE ! push esi ! push edi ! mov esi, pstate ;esi -> m_ctx.state0 ! mov edi, phash ! mov ecx, 8 ! cld ! rep movsd ! pop edi ! pop esi #ENDIF END METHOD '==================== '-- Returns 0 on success or PB (not OS) error code CLASS METHOD calcFileOpen (pFile AS WSTRINGZ, BYVAL hHash AS DWORD) AS LONG ON ERROR GOTO FN_ERR LOCAL ecode AS LONG IF ( m_infile <> 0 ) THEN METHOD = %ERR_FILEISOPEN : EXIT METHOD IF ISFILE(pFile) = 0 THEN METHOD = %ERR_FILENOTFOUND : EXIT METHOD m_buffer = STRING$(%FILE_BUFFERSIZE, 0) m_maxstring = %FILE_BUFFERSIZE m_ctx.lendata = %BLOCKSIZE m_lastpass = 0 m_hHash = hHash m_infile = FREEFILE OPEN pFile FOR BINARY LOCK SHARED AS m_infile BASE=0 m_filesize = LOF(m_infile) m_bytesleft = m_filesize m_padding = me.MakePadding (m_bytesleft) FN_EXIT: METHOD = ecode EXIT METHOD FN_ERR: ecode = ERRCLEAR RESUME FN_EXIT END METHOD CLASS METHOD calcFileProcess() AS LONG REGISTER i AS LONG IF ( m_lastpass < 1 ) THEN 'Resize if necessary & flag final buffer IF m_bytesleft =< m_maxstring THEN m_maxstring = CLNG(m_bytesleft) m_buffer = STRING$(m_maxstring, 0) INCR m_lastpass END IF GET m_infile,, m_buffer : IF ERR THEN METHOD = ERRCLEAR: EXIT METHOD IF m_lastpass THEN m_buffer = m_buffer + m_padding m_ctx.pdata = STRPTR(m_buffer) SELECT CASE m_compress CASE 128 FOR i = 1 TO (LEN(m_buffer)\%BLOCKSIZE) CALL me.Compress128() m_ctx.pdata = m_ctx.pdata + %BLOCKSIZE NEXT i CASE 64 FOR i = 1 TO (LEN(m_buffer)\%BLOCKSIZE) CALL me.Compress64() m_ctx.pdata = m_ctx.pdata + %BLOCKSIZE NEXT i CASE ELSE FOR i = 1 TO (LEN(m_buffer)\%BLOCKSIZE) CALL me.Compress32() m_ctx.pdata = m_ctx.pdata + %BLOCKSIZE NEXT i END SELECT m_bytesleft = m_bytesleft - m_maxstring END IF METHOD = 0 END METHOD CLASS METHOD calcFileClose() AS LONG LOCAL pstate AS LONG LOCAL phash AS DWORD PTR IF ( m_infile = 0 ) THEN EXIT METHOD CLOSE m_infile IF ERR THEN METHOD = ERRCLEAR: EXIT METHOD m_infile = 0 IF ( m_lastpass = 0 ) THEN EXIT METHOD phash = m_hHash pstate = m_ctx.pstate '-- Copy current state 'LOCAL i AS LONG : for i = 0 to (%HASHLEN\4)-1 : @phash[i] = [email protected][i] : next i : exit method #IF %RETURN_LITTLE_ENDIAN ! push edi ! mov edx, pstate ;esi -> m_ctx.state0 ! mov edi, phash ! mov ecx, (%HASHLEN\4)-1 ;here -1 #ALIGN 4 LoopTop: ! mov eax, [edx+ecx*4] ! bswap eax ! mov [edi+ecx*4],eax ! dec ecx ! jns LoopTop ! pop edi #ELSE ! push esi ! push edi ! mov esi, pstate ;esi -> m_ctx.state0 ! mov edi, phash ! mov ecx, 8 ! cld ! rep movsd ! pop edi ! pop esi #ENDIF METHOD = 0 END METHOD '========================= '-- Creates the necessary string to append to targeted data buffer CLASS METHOD MakePadding (BYVAL TotalBytes AS QUAD) AS STRING REGISTER i AS LONG, padBytes AS LONG LOCAL buffbits AS QUAD LOCAL padding AS STRING LOCAL pbyte1 AS BYTE PTR LOCAL pbyte2 AS BYTE PTR buffbits = TotalBytes * 8 padding = NUL$(8) pbyte1 = STRPTR(padding) pbyte2 = VARPTR(buffbits) '-- Copy bytes in reverse FOR i = 0 TO 7 @pbyte1[i] = @pbyte2[7 - i] NEXT i padBytes = %BLOCKSIZE - ((TotalBytes+9) AND (%BLOCKSIZE-1)) METHOD = CHR$(&h80) + NUL$(padBytes) + padding END METHOD '=================== CLASS METHOD HasSSE2() AS LONG ! mov eax, 1 ! cpuid ! xor eax, eax ! test edx, &h04000000 ;bit 26 ! setnz al ;rem to force downgrade to MMX ! mov METHOD, eax END METHOD '=================== CLASS METHOD HasMMX() AS LONG ! mov eax, 1 ! cpuid ! xor eax, eax ! test edx, &h800000 ;bit 23 ! setnz al ;rem to force downgrade to 32-bit ! mov METHOD, eax END METHOD '=================== CLASS METHOD CREATE() IF me.HasSSE2() THEN m_compress = 128 ELSEIF me.HasMMX() THEN m_compress = 64 ELSE m_compress = 32 END IF END METHOD '=================== CLASS METHOD DESTROY() END METHOD ' ==================================================== INTERFACE iSHA256hash : INHERIT IUNKNOWN ' ==================================================== ' ------------------------------------------------------------------------------- ' This properties was intended for files with progress indicator. ' ------------------------------------------------------------------------------- PROPERTY GET FileSize () AS QUAD PROPERTY = m_filesize END PROPERTY PROPERTY GET BytesInProcess () AS QUAD PROPERTY = m_bytesleft END PROPERTY PROPERTY GET Percent () AS LONG PROPERTY = ( (m_filesize - m_bytesleft) * 100 ) / m_filesize END PROPERTY PROPERTY GET fLastpass () AS LONG PROPERTY = m_lastpass END PROPERTY ' ------------------------------------------------------------------------------- ' Methods that might be needed. ' ------------------------------------------------------------------------------- METHOD ByteArrayToHexString (BYVAL bArrayPtr AS DWORD) AS STRING LOCAL bHash AS BYTE PTR LOCAL sHash AS STRING LOCAL i AS LONG IF ( bArrayPtr ) THEN bHash = bArrayPtr FOR i = 0 TO %HASHLEN-1 sHash = sHash + HEX$(@bHash[i],2) NEXT i END IF METHOD = LCASE$(sHash) END METHOD METHOD HexStringToByteArray (BYVAL HexString AS STRING, BYVAL bArrayPtr AS DWORD) LOCAL bHash AS BYTE PTR LOCAL i,j AS LONG IF ( bArrayPtr ) AND ( LEN(HexString) <= %HASHLEN * 2 ) THEN bHash = bArrayPtr FOR i = 1 TO LEN(HexString) STEP 2 @bHash[j] = VAL("&h" + MID$(HexString,i,2)) INCR j NEXT i END IF END METHOD ' ------------------------------------------------------------------------------- ' This methods was intended for files with progress indicator. ' ------------------------------------------------------------------------------- METHOD calc_fileOpen (pFile AS WSTRINGZ,BYVAL hashPtr AS DWORD) AS LONG CALL me.Init() METHOD = me.calcFileOpen (pFile, hashPtr) END METHOD METHOD calc_fileProcess() AS LONG METHOD = me.calcFileProcess() END METHOD METHOD calc_fileClose() AS LONG METHOD = me.calcFileClose() END METHOD ' ------------------------------------------------------------------------------- ' This method is for files and if not needed progress bar. ' ------------------------------------------------------------------------------- METHOD calc_file (pFile AS WSTRINGZ,BYVAL hashPtr AS DWORD) AS LONG LOCAL ecode AS LONG CALL me.Init() ecode = me.calcFileOpen (pFile, hashPtr) WHILE ( (ecode = 0) AND (m_lastpass = 0) ) ecode = me.calcFileProcess() WEND CALL me.calcFileClose() METHOD = ecode END METHOD ' ------------------------------------------------------------------------------- ' This method is intended for strings, or byte arrays. ' ------------------------------------------------------------------------------- METHOD calc_buffer (BYVAL dataPtr AS LONG, BYVAL dataLen AS DWORD, BYVAL hashPtr AS DWORD) CALL me.Init() CALL me.calcBuffer (dataPtr, dataLen, hashPtr) END METHOD END INTERFACE END CLASS
Code:
[COLOR="YellowGreen"][B]' SHA256hash.bas[/B][/COLOR] #COMPILER PBWIN 10 #COMPILE EXE "SHA256hash.exe" #DIM ALL %UNICODE = 1 #INCLUDE "SHA256hash.inc" $REFERENCE_FILE = "" FUNCTION GetFile (pFile AS WSTRINGZ, a() AS BYTE) AS QUAD LOCAL bytes AS QUAD LOCAL f AS LONG IF ( ISFILE(pFile) ) THEN f = FREEFILE OPEN pFile FOR BINARY AS #f bytes = LOF(#f) IF ( bytes > 0 AND bytes < 1024*1024*1000 ) THEN REDIM a(1 TO bytes) GET #f,,a() END IF CLOSE #f END IF FUNCTION = bytes END FUNCTION FUNCTION PBMAIN () AS LONG LOCAL o AS iSHA256hash LOCAL hTxt AS LONG LOCAL file AS WSTRINGZ * %MAX_PATH LOCAL hash AS STRING LOCAL bytes AS QUAD LOCAL ecode AS LONG LOCAL oldper AS LONG LOCAL time AS SINGLE LOCAL refresh AS SINGLE LOCAL stext AS STRING DIM afile(0) AS BYTE file = TRIM$(COMMAND$,$$DQ) IF file = "" THEN file = $REFERENCE_FILE IF file = "" THEN DISPLAY OPENFILE 0, , , "", "", CHR$("All files (*.*)", 0 , "*.*", 0), "", "", %OFN_EXPLORER OR %OFN_FILEMUSTEXIST OR %OFN_ENABLESIZING TO file IF file = "" THEN EXIT FUNCTION bytes = GetFile (file, afile()) TXT.WINDOW("SHA256hash - " + file + " (" + FORMAT$(bytes,"#,") + " Bytes)", 150, 100) TO hTxt ' ------------------------------------------------------------------------------------- o = CLASS "cSHA256hash" DIM ahash(1 TO 32) AS BYTE DIM atext(1 TO 5) AS BYTE ARRAY ASSIGN atext() = ASC("H"), ASC("e"), ASC("l"), ASC("l"), ASC("o") CALL o.calc_buffer (VARPTR(atext(1)), 5, VARPTR(ahash(1))) hash = o.ByteArrayToHexString (VARPTR(ahash(1))) TXT.PRINT LEFT$(hash,32) + " Hello" TXT.PRINT RIGHT$(hash,32) TXT.PRINT "" TXT.PRINT "185f8db32271fe25f561a6fc938b2e26 Reference" TXT.PRINT "4306ec304eda518007d1764826381969" TXT.PRINT "" TXT.PRINT "---------------------------------------------" TXT.PRINT "" stext = "World" CALL o.calc_buffer (STRPTR(stext), LEN(stext), VARPTR(ahash(1))) hash = o.ByteArrayToHexString (VARPTR(ahash(1))) TXT.PRINT LEFT$(hash,32) + " World" TXT.PRINT RIGHT$(hash,32) TXT.PRINT "" TXT.PRINT "78ae647dc5544d227130a0682a51e30b Reference" TXT.PRINT "c7777fbb6d8a8f17007463a3ecd1d524" TXT.PRINT "" TXT.PRINT "" TXT.PRINT "" TXT.PRINT "Press any key..." TXT.WAITKEY$ TXT.CLS ' ------------------------------------------------------------------------------------- RESET ahash() TXT.PRINT file + " (" + FORMAT$(bytes,"#,") + " Bytes)" time = TIMER ecode = o.calc_file (file, VARPTR(ahash(1))) time = TIMER-time hash = o.ByteArrayToHexString (VARPTR(ahash(1))) TXT.PRINT "" TXT.PRINT LEFT$(hash,32) + " calc_file()" TXT.PRINT RIGHT$(hash,32) TXT.PRINT ">>> Time: " + FORMAT$(time,"#.###") + " s" IF LCASE$(file) = LCASE$($REFERENCE_FILE) THEN TXT.PRINT "" TXT.PRINT "671c3f49aab0c1f4018aa3d2faec85c8 Reference" TXT.PRINT "196c8b93186e931a8099dcb0df9f7a44" END IF ' ------------------------------------------------------------------------------------- IF bytes < 1024*1024*1000 THEN RESET ahash() time = TIMER CALL o.calc_buffer (VARPTR(afile(1)), bytes, VARPTR(ahash(1))) time = TIMER-time hash = o.ByteArrayToHexString (VARPTR(ahash(1))) TXT.PRINT "" TXT.PRINT LEFT$(hash,32) + " calc_buffer()" TXT.PRINT RIGHT$(hash,32) TXT.PRINT ">>> Time: " + FORMAT$(time,"#.###") + " s" END IF TXT.PRINT "" TXT.PRINT "" TXT.PRINT "Press any key..." TXT.WAITKEY$ TXT.CLS ' ------------------------------------------------------------------------------------- TXT.PRINT LEFT$(hash,32) + " last hash" TXT.PRINT RIGHT$(hash,32) TXT.PRINT "" TXT.PRINT "----------------------------------------------------------------" TXT.PRINT "" RESET ahash() refresh = TIMER time = TIMER ecode = o.calc_fileOpen (file, VARPTR(ahash(1))) : IF ecode <> 0 THEN GOTO FN_ERR TXT.PRINT file + " (" + FORMAT$(o.FileSize,"#,") + " Bytes)" TXT.PRINT "" WHILE ( (ecode = 0) AND (o.fLastpass = 0) ) ecode = o.calc_fileProcess() : IF ecode <> 0 THEN GOTO FN_ERR IF ( (TIMER-refresh) > 1.9 ) THEN refresh = TIMER IF ( oldper <> o.Percent ) THEN oldper = o.Percent TXT.PRINT FORMAT$(o.Percent,"000") + "% "; END IF END IF IF TXT.INSTAT THEN IF TXT.INKEY$ = $ESC THEN EXIT LOOP END IF END IF WEND TXT.PRINT "" ecode = o.calc_fileClose() : IF ecode <> 0 THEN GOTO FN_ERR time = TIMER-time hash = o.ByteArrayToHexString (VARPTR(ahash(1))) TXT.PRINT "" TXT.PRINT LEFT$(hash,32) TXT.PRINT RIGHT$(hash,32) TXT.PRINT ">>> Time: " + FORMAT$(time,"#.###") + " s" IF LCASE$(file) = LCASE$($REFERENCE_FILE) THEN TXT.PRINT "" TXT.PRINT "671c3f49aab0c1f4018aa3d2faec85c8 Reference" TXT.PRINT "196c8b93186e931a8099dcb0df9f7a44" END IF o = NOTHING FN_EXIT: TXT.PRINT "" TXT.PRINT "" TXT.PRINT "" TXT.PRINT "Press any key..." TXT.WAITKEY$ EXIT FUNCTION FN_ERR: TXT.PRINT "" TXT.PRINT "" TXT.PRINT ERROR$(ecode) TXT.PRINT "" TXT.PRINT "" TXT.PRINT "Press any key..." TXT.WAITKEY$ END FUNCTION
Comment