August 8: Added SHA256FileFingerprint( filename$, [ ,*progress ] )
August 15: Program is updated to be faster and SHA256FileFingerprint will now handle files > 2gb in size.
August 15: Added two commands, SHA224Fingerprint() and SHA224FileFingerprint()
August 16: Optimized the code by replacing procedures with inlined asm, program is faster now
August 17: Significant speed upgrade today, almost all the sha256_process() procedure is rewritten in asm to use registers instead of variables for the states
August 30: Wilbert has created a MacOS-friendly version of this program, you can find it here:http://www.purebasic.fr/english/viewtop ... 19&t=47388
When I first wrote this program, it was all Purebasic code. It ran fine. However, in the course of testing sha256FileFingerprint for accuracy I tested the result against
that produced by the Hashslash file hasher, and I was dismayed to find that the 50mb file I was testing with took 24 seconds with my code and Hashslash had it done
in 4.5 seconds. So back to the drawingboard and quite some lines of inlined asm later, the code now processes the 50mb in under 3 seconds. Take that, Hashslash!
Also, for some reason the code will no longer run after compiling with Tailbite. So that option is gone for now, just use as an include.
If you are using a progress bar or such (unnecessary for data less than about 50+ mb) it should be written like so:
Code: Select all
Procedure progress(value)
Static lastvalue
If value<>lastvalue
; StatusBarProgress(0,0,value)
lastvalue=value
EndIf
EndProcedure
Code: Select all
;================================================================
;
; Library Commands: Sha256FingerPrint()
; Sha256FileFingerPrint()
; Sha224FingerPrint()
; Sha224FileFingerPrint()
;
; Author: Lloyd Gallant (netmaestro)
;
; Contributors: Thanks to Danilo and kenmo for
; help with the ROTR and SHR macros,
; idle and wilbert for their help
; with asm routines.
; and to Christopher Devine for the
; c code this program is based on.
;
; Date: August 7, 2011
; Target Compiler: Purebasic 4 and up
; Target OS: Windows, Linux, MacOS
;
; License: GNU General Public License
;
; This program is free software; you can redistribute it and/or modify
; it under the terms of the GNU General Public License As published by
; the Free Software Foundation; either version 2 of the License, or
; (at your option) any later version.
;
; This program is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY Or FITNESS For A PARTICULAR PURPOSE. See the
; GNU General Public License For more details.
;
; The logic for this program is based on sha256.c found here:
;
; http://www.spale.com/download/scrypt/scrypt1.0/
;
; You can test the accuracy of this program by generating
; test data at:
;
; http://hashgenerator.de/
;
;================================================================
;
;
; Usage:
;
; result$ = SHA256Fingerprint(*address, length, [ ,*progress ] )
; result$ = SHA256FileFingerprint(file$, [ ,*progress ] )
;
; result$ = SHA224Fingerprint(*address, length, [ ,*progress ] )
; result$ = SHA224FileFingerprint(file$, [ ,*progress ] )
;
; Progress callback function:
;
; Procedure MyCallBack(value.i)
; ; value is 0 to 100 representing percentage completed
; Endprocedure
;
;
;================================================================
; STRUCTURES
;================================================================
Structure UINT8_BUFFER
b.a[64]
EndStructure
Structure sha256_context
state.l [8]
buffer.a [64]
total.q
totalprocessed.q
EndStructure
;================================================================
; HELPER MACROS
;================================================================
Macro R_(t)
!mov ebx, [ebp+(4*t)]
!bswap ebx
!mov [edi+(4*t)], ebx
EndMacro
Macro R(t)
!mov ebx, [edi+(4*t)-64]
!add ebx, [edi+(4*t)-28]
!mov eax, [edi+(4*t)-60]
!mov ecx, eax
!mov edx, eax
!ror eax, 7
!ror ecx, 18
!shr edx, 3
!xor eax, ecx
!xor eax, edx
!add ebx, eax
!mov eax, [edi+(4*t)-8]
!mov ecx, eax
!mov edx, eax
!ror eax, 17
!ror ecx, 19
!shr edx, 10
!xor eax, ecx
!xor eax, edx
!add ebx, eax
!mov [edi+(4*t)], ebx
EndMacro
Macro P(a,b,c,d,e,f,g,h,x,K)
!movd eax, h ; h = h + Sigma3(e) + F1(e,f,g) + K + x
!add ebx, eax
!add ebx, k
!movd eax, e ; F1
!movd edx, f
!movd ecx, g
!xor edx, ecx
!and edx, eax
!xor edx, ecx
!add ebx, edx
!movd eax, e ; Sigma3
!mov edx, eax
!mov ecx, eax
!ror eax, 6
!ror edx, 11
!ror ecx, 25
!xor eax, edx
!xor eax, ecx
!add ebx, eax
!movd h, ebx
!paddd d, h ; d = d + h
!movd eax, a ; F0 ; h = h + Sigma2(a) + F0(a,b,c)
!movd edx, b
!movd ecx, c
!or eax, edx
!and eax, ecx
!movd ecx, a
!and ecx, edx
!or eax, ecx
!add ebx, eax
!movd eax, a ; Sigma2
!mov edx, eax
!mov ecx, eax
!ror eax, 2
!ror edx, 13
!ror ecx, 22
!xor eax, edx
!xor eax, ecx
!add ebx, eax
!movd h, ebx
EndMacro
;================================================================
; LOCAL FUNCTIONS
;================================================================
Procedure sha224_starts( *ctx.sha256_context )
*ctx\state[0] = $c1059ed8
*ctx\state[1] = $367cd507
*ctx\state[2] = $3070dd17
*ctx\state[3] = $f70e5939
*ctx\state[4] = $ffc00b31
*ctx\state[5] = $68581511
*ctx\state[6] = $64f98fa7
*ctx\state[7] = $befa4fa4
*ctx\totalprocessed=0
EndProcedure
Procedure sha256_starts( *ctx.sha256_context )
*ctx\state[0] = $6A09E667
*ctx\state[1] = $BB67AE85
*ctx\state[2] = $3C6EF372
*ctx\state[3] = $A54FF53A
*ctx\state[4] = $510E527F
*ctx\state[5] = $9B05688C
*ctx\state[6] = $1F83D9AB
*ctx\state[7] = $5BE0CD19
*ctx\totalprocessed=0
EndProcedure
Procedure sha256_process_addr__()
!mov eax, sha256_process_start
ProcedureReturn
!sha256_process_start:
!push ebp
!push ebx
!push edi
!push esi
!mov esi, [esp+20] ; *ctx
!mov ebp, [esp+24] ; *bytes
!sub esp, 272 ; Allocate 256 bytes of memory for 64 dwords
!mov edi, esp
!add edi, 15
!and edi, 0xfffffff0
!movd xmm0, [esi]
!movd xmm1, [esi+4]
!movd xmm2, [esi+8]
!movd xmm3, [esi+12]
!movd xmm4, [esi+16]
!movd xmm5, [esi+20]
!movd xmm6, [esi+24]
!movd xmm7, [esi+28]
R_(0)
P( xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, 0, 0x428A2F98 )
R_(1)
P( xmm7, xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, 1, 0x71374491 )
R_(2)
P( xmm6, xmm7, xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, 2, 0xB5C0FBCF )
R_(3)
P( xmm5, xmm6, xmm7, xmm0, xmm1, xmm2, xmm3, xmm4, 3, 0xE9B5DBA5 )
R_(4)
P( xmm4, xmm5, xmm6, xmm7, xmm0, xmm1, xmm2, xmm3, 4, 0x3956C25B )
R_(5)
P( xmm3, xmm4, xmm5, xmm6, xmm7, xmm0, xmm1, xmm2, 5, 0x59F111F1 )
R_(6)
P( xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm0, xmm1, 6, 0x923F82A4 )
R_(7)
P( xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm0, 7, 0xAB1C5ED5 )
R_(8)
P( xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, 8, 0xD807AA98 )
R_(9)
P( xmm7, xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, 9, 0x12835B01 )
R_(10)
P( xmm6, xmm7, xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, 10, 0x243185BE )
R_(11)
P( xmm5, xmm6, xmm7, xmm0, xmm1, xmm2, xmm3, xmm4, 11, 0x550C7DC3 )
R_(12)
P( xmm4, xmm5, xmm6, xmm7, xmm0, xmm1, xmm2, xmm3, 12, 0x72BE5D74 )
R_(13)
P( xmm3, xmm4, xmm5, xmm6, xmm7, xmm0, xmm1, xmm2, 13, 0x80DEB1FE )
R_(14)
P( xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm0, xmm1, 14, 0x9BDC06A7 )
R_(15)
P( xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm0, 15, 0xC19BF174 )
R(16)
P( xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, 16, 0xE49B69C1 )
R(17)
P( xmm7, xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, 17, 0xEFBE4786 )
R(18)
P( xmm6, xmm7, xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, 18, 0x0FC19DC6 )
R(19)
P( xmm5, xmm6, xmm7, xmm0, xmm1, xmm2, xmm3, xmm4, 19, 0x240CA1CC )
R(20)
P( xmm4, xmm5, xmm6, xmm7, xmm0, xmm1, xmm2, xmm3, 20, 0x2DE92C6F )
R(21)
P( xmm3, xmm4, xmm5, xmm6, xmm7, xmm0, xmm1, xmm2, 21, 0x4A7484AA )
R(22)
P( xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm0, xmm1, 22, 0x5CB0A9DC )
R(23)
P( xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm0, 23, 0x76F988DA )
R(24)
P( xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, 24, 0x983E5152 )
R(25)
P( xmm7, xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, 25, 0xA831C66D )
R(26)
P( xmm6, xmm7, xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, 26, 0xB00327C8 )
R(27)
P( xmm5, xmm6, xmm7, xmm0, xmm1, xmm2, xmm3, xmm4, 27, 0xBF597FC7 )
R(28)
P( xmm4, xmm5, xmm6, xmm7, xmm0, xmm1, xmm2, xmm3, 28, 0xC6E00BF3 )
R(29)
P( xmm3, xmm4, xmm5, xmm6, xmm7, xmm0, xmm1, xmm2, 29, 0xD5A79147 )
R(30)
P( xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm0, xmm1, 30, 0x06CA6351 )
R(31)
P( xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm0, 31, 0x14292967 )
R(32)
P( xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, 32, 0x27B70A85 )
R(33)
P( xmm7, xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, 33, 0x2E1B2138 )
R(34)
P( xmm6, xmm7, xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, 34, 0x4D2C6DFC )
R(35)
P( xmm5, xmm6, xmm7, xmm0, xmm1, xmm2, xmm3, xmm4, 35, 0x53380D13 )
R(36)
P( xmm4, xmm5, xmm6, xmm7, xmm0, xmm1, xmm2, xmm3, 36, 0x650A7354 )
R(37)
P( xmm3, xmm4, xmm5, xmm6, xmm7, xmm0, xmm1, xmm2, 37, 0x766A0ABB )
R(38)
P( xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm0, xmm1, 38, 0x81C2C92E )
R(39)
P( xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm0, 39, 0x92722C85 )
R(40)
P( xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, 40, 0xA2BFE8A1 )
R(41)
P( xmm7, xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, 41, 0xA81A664B )
R(42)
P( xmm6, xmm7, xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, 42, 0xC24B8B70 )
R(43)
P( xmm5, xmm6, xmm7, xmm0, xmm1, xmm2, xmm3, xmm4, 43, 0xC76C51A3 )
R(44)
P( xmm4, xmm5, xmm6, xmm7, xmm0, xmm1, xmm2, xmm3, 44, 0xD192E819 )
R(45)
P( xmm3, xmm4, xmm5, xmm6, xmm7, xmm0, xmm1, xmm2, 45, 0xD6990624 )
R(46)
P( xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm0, xmm1, 46, 0xF40E3585 )
R(47)
P( xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm0, 47, 0x106AA070 )
R(48)
P( xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, 48, 0x19A4C116 )
R(49)
P( xmm7, xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, 49, 0x1E376C08 )
R(50)
P( xmm6, xmm7, xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, 50, 0x2748774C )
R(51)
P( xmm5, xmm6, xmm7, xmm0, xmm1, xmm2, xmm3, xmm4, 51, 0x34B0BCB5 )
R(52)
P( xmm4, xmm5, xmm6, xmm7, xmm0, xmm1, xmm2, xmm3, 52, 0x391C0CB3 )
R(53)
P( xmm3, xmm4, xmm5, xmm6, xmm7, xmm0, xmm1, xmm2, 53, 0x4ED8AA4A )
R(54)
P( xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm0, xmm1, 54, 0x5B9CCA4F )
R(55)
P( xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm0, 55, 0x682E6FF3 )
R(56)
P( xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, 56, 0x748F82EE )
R(57)
P( xmm7, xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, 57, 0x78A5636F )
R(58)
P( xmm6, xmm7, xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, 58, 0x84C87814 )
R(59)
P( xmm5, xmm6, xmm7, xmm0, xmm1, xmm2, xmm3, xmm4, 59, 0x8CC70208 )
R(60)
P( xmm4, xmm5, xmm6, xmm7, xmm0, xmm1, xmm2, xmm3, 60, 0x90BEFFFA )
R(61)
P( xmm3, xmm4, xmm5, xmm6, xmm7, xmm0, xmm1, xmm2, 61, 0xA4506CEB )
R(62)
P( xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm0, xmm1, 62, 0xBEF9A3F7 )
R(63)
P( xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm0, 63, 0xC67178F2 )
!movd edx, xmm0
!add [esi + 0], edx
!movd edx, xmm1
!add [esi + 4], edx
!movd edx, xmm2
!add [esi + 8], edx
!movd edx, xmm3
!add [esi + 12], edx
!movd edx, xmm4
!add [esi + 16], edx
!movd edx, xmm5
!add [esi + 20], edx
!movd edx, xmm6
!add [esi + 24], edx
!movd edx, xmm7
!add [esi + 28], edx
!add esp, 272
!pop esi
!pop edi
!pop ebx
!pop ebp
!ret
EndProcedure
PrototypeC sha256_process_proto(*ctx.sha256_context, *bytes)
Global sha256_process.sha256_process_proto = sha256_process_addr__()
Procedure sha256_update( *ctx.sha256_context, *input, length, jobsize.q, *callback )
Define.l left, fill
If length=0 : ProcedureReturn : EndIf
left = *ctx\total & $3F
fill = 64-left
*ctx\total + length
If left And (length >= fill)
CopyMemory( *input, @*ctx\buffer[0]+left, fill )
sha256_process( *ctx, @*ctx\buffer[0] )
length - fill
*input + fill
left = 0
EndIf
While length >= 64
sha256_process( *ctx, *input )
length - 64
*input + 64
*ctx\totalprocessed+64
If *callback
If *ctx\totalprocessed & $ffff = 0
progress = 100 * *ctx\totalprocessed / jobsize
CallFunctionFast(*callback, progress )
EndIf
EndIf
Wend
If length
CopyMemory( *input, @*ctx\buffer[0]+left, length )
EndIf
EndProcedure
Procedure sha256_finish( *ctx.sha256_context, *digest, jobsize.q, full, *callback )
Define.l last, padn
msglen.q
sha256_padding.UINT8_BUFFER
sha256_padding\b[0]=$80
jobsize<<3
!mov eax, [p.v_jobsize+4]
!mov edx, [p.v_jobsize]
!bswap eax
!bswap edx
!mov [p.v_msglen],eax
!mov [p.v_msglen+4],edx
last = *ctx\total & $3F
If last<56
padn = 56-last
Else
padn = 120-last
EndIf
sha256_update( *ctx, @sha256_padding, padn, padn, *callback )
sha256_update( *ctx, @msglen, 8, 8, *callback )
!push edi
!push esi
!mov esi, [p.p_ctx+8]
!mov edi, [p.p_digest+8]
!xor ecx, ecx
!loopstart:
!mov eax, [esi]
!bswap eax
!mov [edi + ecx], eax
!add ecx, 4
!add esi, 4
!cmp ecx, 32
!jnz loopstart
!pop esi
!pop edi
*ctx\totalprocessed = 0
If *callback
CallFunctionFast(*callback, 100 )
EndIf
EndProcedure
Procedure MoveSumToDigestAsHex(*sum, *digest, full)
!push edi
!push esi
!cmp dword [esp + 20], 0x0
!jnz fullsize
!mov ecx, 0x1c
!jmp endsize
!fullsize:
!mov ecx, 0x20
!endsize:
!mov esi, [esp + 12]
!mov edi, [esp + 16]
!jecxz exit
!startloop:
!lodsb
!mov ah, al
!shr al, 4
!and ax, 0x0f0f
!or ax, 0x3030
!cmp al, 0x3a
!jb no_offset_lo
!add al, 39
!no_offset_lo:
!cmp ah, 0x3a
!jb no_offset_hi
!add ah, 39
!no_offset_hi:
!stosw
!loop startloop
!exit:
!pop esi
!pop edi
EndProcedure
Procedure.s SHA256LongFingerprint(*datapointer, Length, full, *callback=0) ; Data address, data size, [ ,<procaddress> ]
*ctx.sha256_context = AllocateMemory(SizeOf(sha256_context))
*sha256sum = AllocateMemory(32)
Protected digest.s
If full
sha256_starts( *ctx )
Else
sha224_starts( *ctx )
EndIf
sha256_update( *ctx, *datapointer, Length, Length, *callback )
sha256_finish( *ctx, *sha256sum, Length, full, *callback )
*output = AllocateMemory(65)
MoveSumToDigestAsHex(*sha256sum, *output, full)
digest = PeekS(*output)
FreeMemory(*output)
FreeMemory(*sha256sum)
FreeMemory(*ctx)
ProcedureReturn digest
EndProcedure
Procedure.s SHA256LongFileFingerprint(filename.s, full, *callback=0) ; filename$, [ ,<procaddress> ]
Protected digest.s
Protected *datapointer, *output, *ctx.sha256_context
Protected bytesread, fresult
Protected jobsize.q
*ctx = AllocateMemory(SizeOf(sha256_context))
*sha256sum = AllocateMemory(32)
*output = AllocateMemory(65)
*datapointer = AllocateMemory($10000)
fresult = OpenFile(#PB_Any, filename)
If fresult
FileBuffersSize(fresult, $10000)
jobsize = Lof(fresult)
If full
sha256_starts( *ctx )
Else
sha224_starts( *ctx )
EndIf
While Not Eof(fresult)
bytesread = ReadData(fresult, *datapointer, $10000)
sha256_update( *ctx, *datapointer, bytesread, jobsize, *callback )
Wend
sha256_finish( *ctx, *sha256sum, jobsize, full, *callback )
MoveSumToDigestAsHex(*sha256sum, *output, full)
digest = PeekS(*output)
CloseFile(fresult)
EndIf
FreeMemory(*datapointer)
FreeMemory(*output)
FreeMemory(*sha256sum)
FreeMemory(*ctx)
ProcedureReturn digest
EndProcedure
;================================================================
; EXPORTED FUNCTIONS
;================================================================
ProcedureDLL.s SHA256FileFingerprint(filename.s, *callback=0) ; filename$, [ ,<procaddress> ]
ProcedureReturn SHA256LongFileFingerprint(filename.s, 1, *callback)
EndProcedure
ProcedureDLL.s SHA224FileFingerprint(filename.s, *callback=0) ; filename$, [ ,<procaddress> ]
ProcedureReturn SHA256LongFileFingerprint(filename.s, 0, *callback)
EndProcedure
ProcedureDLL.s SHA256Fingerprint(*datapointer, Length, *callback=0) ; Data address, data size, [ ,<procaddress> ]
ProcedureReturn SHA256LongFingerprint(*datapointer, Length, 1, *callback)
EndProcedure
ProcedureDLL.s SHA224Fingerprint(*datapointer, Length, *callback=0) ; Data address, data size, [ ,<procaddress> ]
ProcedureReturn SHA256LongFingerprint(*datapointer, Length, 0, *callback)
EndProcedure
Code: Select all
; Test program for SHA256Fingerprint()
; Here are some common tests with known outputs:
IncludeFile "sha256.pbi"
ProcedureDLL.l TicksHQ() ; By Rescator
Static maxfreq.q
Protected t.q
If maxfreq=0
QueryPerformanceFrequency_(@maxfreq)
maxfreq=maxfreq/1000
EndIf
QueryPerformanceCounter_(@t)
ProcedureReturn t/maxfreq
EndProcedure
Global Dim msg.s(5)
msg(0) = "abc"
msg(1) = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
msg(2) = Space(1000000) : FillMemory(@msg(2), 1000000, 'a', #PB_Byte) ; A string of one million "a"'s
msg(3) = "" ; Null string
msg(4) = "Test vector from febooti.com"
msg(5) = "The quick brown fox jumps over the lazy dog"
; These are the known digests for each:
Global Dim value.s(5)
value(0) = "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
value(1) = "248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1"
value(2) = "cdc76e5c9914fb9281a1c7e284d73e67f1809a48a497200e046d39ccc7112cd0"
value(3) = "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
value(4) = "077b18fe29036ada4890bdec192186e10678597a67880290521df70df4bac9ab"
value(5) = "d7a8fbb307d7809469ca9abcb0082e4f8d5651e46d3cdb762d02d0bf37c9e592"
Procedure progress(value)
Static lastvalue
If value<>lastvalue
; StatusBarProgress(0,0,value)
lastvalue=value
EndIf
EndProcedure
Procedure TestSha256(void)
t=TicksHQ()
For i = 0 To 5
AddGadgetItem( 0, -1, " Test " + Str(i+1) + ":")
digest.s = SHA256Fingerprint(@msg(i), Len(msg(i) ))
If digest <> value(i)
AddGadgetItem( 0, -1, " failed!" )
Else
AddGadgetItem( 0, -1, " passed." )
EndIf
Next
v=TicksHQ()
StatusBarProgress(0,0,0)
AddGadgetItem(0, -1, Str(v-t))
EndProcedure
OpenWindow(0,0,0,640,480,"SHA-256 Validation Tests:", #PB_Window_ScreenCentered|#PB_Window_SystemMenu)
ListViewGadget(0,40,20,560,360)
ButtonGadget(1, 300,400,80,20,"Do the tests")
CreateStatusBar(0, WindowID(0))
AddStatusBarField(640)
Repeat
EventID = WaitWindowEvent()
Select EventID
Case #PB_Event_Gadget
If EventGadget()=1
If Not IsThread(tid)
StatusBarProgress(0,0,0)
tid = CreateThread(@TestSha256(),0)
EndIf
EndIf
EndSelect
Until EventID = #PB_Event_CloseWindow