Code: Alles auswählen
;- SHA-256, Test für PB. Grundlage (Pseudo-Code) siehe engl. Wikipedia
;- "Helle" Klaus Helbing, 14.06.2011, PB 4.51 (x64)
;- 64-Bit-Windows-Version, hier für Dateien
Global Size.q
Global SizeAv.q
Global pSource.q
Global pAllBlocks.q
Global Chunks.q
Global ChunksSum.q
Global ChunksAll.q
Global pW.q
Global pHash.q
Global FreeMem.q
Global MemAv.q
Global a.l
Global b.l
Global c.l
Global d.l
Global e.l
Global f.l
Global g.l
Global h.l
If OpenWindow(0, 0, 0, 600, 400, "Helles SHA-256, 64-Bit-OS", #PB_Window_MinimizeGadget | #PB_Window_ScreenCentered)
;- freies RAM ermitteln
SysInfo.SYSTEM_INFO
Mem.MEMORYSTATUSEX
;- Größe der Struktur ermitteln und in ihr selbst speichern
Mem\dwLength = SizeOf(MEMORYSTATUSEX)
;- vom System Speicherinfo holen
GlobalMemoryStatusEx_(@Mem)
FreeMem = Mem\ullAvailPhys >> 1 ;halbieren
If FreeMem >= $40000000 ;1GB
MemAv = $40000000
Chunks = $1000000 ;für 1GB
ElseIf FreeMem >= $20000000 ;512MB
MemAv = $20000000
Chunks = $800000 ;für 512MB
Else
MessageRequester("Abbruch !", "Ist mir zuwenig RAM !")
EndIf
ChunksOld = Chunks
TextGadget(0, 10, 10, 230, 15, "Select a File :")
ExplorerTreeGadget(1, 10, 30, 580, 360, "", #PB_Explorer_NoDriveRequester)
Repeat
Event = WaitWindowEvent()
If Event = #PB_Event_CloseWindow
End
EndIf
Until EventType() = #PB_EventType_LeftDoubleClick And GetGadgetState(1) = #PB_Explorer_File
File$ = GetGadgetText(1)
FreeGadget(0) : FreeGadget(1)
TA = ElapsedMilliseconds()
TF = TA ;nur für Fortschritts-Balken
ReadFile(0, File$)
Size = Lof(0)
SizeAv = Size
ChunksAll = (Size / 64) + 1 ;nur für Fortschritts-Balken
TextGadget(0, 10, 10, 560, 20, "File : " + File$)
Size$ = Str(Size) ;für 1000-er Trennpunkte
LS = Len(Size$)
LSMod = LS % 3
If LSMod = 0
LSMod = 3
EndIf
i = 3
j = 1
While LS - i > 0
SizeP$ = InsertString(Size$, ".", LSMod + j)
i + 3
Size$ = SizeP$
j + 4
Wend
TextGadget(1, 10, 30, 560, 20, "File-Länge : " + SizeP$ + " Bytes")
TextGadget(2, 25, 50, 550, 20, "Berechnungs-Fortschritt :", #PB_Text_Center)
ProgressBarGadget(3, 25, 75, 550, 25, 0, 100, #PB_ProgressBar_Smooth)
If Size <= MemAv
MemAv = Size
EndIf
pW = AllocateMemory(256)
pHash = AllocateMemory(32) ;damit Hash-Startwerte erhalten bleiben
CopyMemory(?HashBase, pHash, 32)
pAllBlocks = AllocateMemory(MemAv + 128) ;(großzügig bemessener) Speicher für die 512-Bit-Blöcke
pAllBlocksOld = pAllBlocks
!File_Weiter:
BytesRead = ReadData(0, pAllBlocks, MemAv) ;Datei in Speicher einlesen
Seek + BytesRead
SizeAv - BytesRead
If SizeAv = 0
CloseFile(0)
EndIf
;Preprocessing, Size wird auf Vielfaches von 512 Bit (64 Byte) gebracht (Blocklänge ist 512 Bit)
!cmp [v_SizeAv],0
!jne End_Preprocessing
!mov r10,[v_pAllBlocks]
!mov rax,[v_MemAv]
!mov r8,rax
!mov r11,[v_Size]
!shl r11,3 ;Länge in Bits!
!bswap r11 ;Size auf Big-Endian bringen
!mov rcx,64 ;512 Bit
!xor rdx,rdx ;hier mal so (ist ja unsigned)
!div rcx ;Modulo steht in rdx
!inc rax ;eine Runde wollen wir ja wenigstens!
!mov [v_Chunks],rax
!mov rax,[v_MemAv]
!mov byte[r10+rax],80h ;Bit mit Wert 1 anhängen (wird 1 durch bswap)
!or rdx,rdx ;rdx=0?
!jnz @f ;nein
;1.Fall: Letzter 512-Bit-Block ist Vielfaches von 512 Bit (64 Byte). Es wird ein kompletter 512-Bit-Block angehängt
!mov [r10+r8+56],r11 ;Original-Länge als 64-Bit-Big-Endian-Wert anhängen
!jmp End_Preprocessing
!@@:
!cmp rdx,56 ;448 Bit
!jae @f
;2.Fall: Letzter 512-Bit-Block ist kleiner als 448 Bit (56 Byte), aber größer Null
!sub r8,rdx
!mov [r10+r8+56],r11 ;Original-Länge als 64-Bit-Big-Endian-Wert in den vorhandenen Block kopieren (Bytes 56-63)
!jmp End_Preprocessing
!@@:
;3.Fall: Letzter 512-Bit-Block ist größer/gleich als 448 Bit (56 Byte). Dieser Block wird aufgefüllt (Bitwert 1 drangehängt,
; Rest Null) und ein weiterer Block drangehängt mit Nullen und am Ende Original-Länge als 64-Bit-Big-Endian-Wert
!sub r8,rdx
!mov [r10+r8+120],r11 ;Original-Länge als 64-Bit-Big-Endian-Wert in den zusätzlichen Block kopieren (Bytes 56-63)
!inc [v_Chunks] ;es wurde ja ein Block drangehängt
!End_Preprocessing:
!Next_Chunk: ;512 Bit (64 Byte)
;W[0] bis W[15]
!mov rcx,16
!mov r11,[v_pAllBlocks]
!mov r10,[v_pW]
!@@:
!mov eax,dword[r11] ;(erweiterten) Source einlesen
!bswap eax ;auf Big-Endian bringen
!mov dword[r10],eax
!add r10,4
!add r11,4
!dec rcx
!jnz @b
;W[16] bis W[63]
!mov rcx,48
!mov r11,[v_pW]
!add r11,64
!@@:
;s0
!mov eax,dword[r11-60]
!mov edx,eax
!mov r10d,eax
!ror eax,7
!ror edx,18
!shr r10d,3
!xor eax,edx
!xor r10d,eax
;s1
!mov eax,dword[r11-8]
!mov edx,eax
!mov r8d,eax
!ror eax,17
!ror edx,19
!xor eax,edx
!shr r8d,10
!xor eax,r8d
;W[i]
!mov edx,dword[r11-64]
!add edx,r10d ;r10d=s0
!add edx,dword[r11-28]
!add edx,eax ;eax=s1
!mov dword[r11],edx
!add r11,4
!dec rcx
!jnz @b
;Initialisierung
!mov r11,[v_pHash] ;siehe Data
!mov eax,dword[r11]
!mov [v_a],eax
!mov eax,dword[r11+4]
!mov [v_b],eax
!mov eax,dword[r11+8]
!mov [v_c],eax
!mov eax,dword[r11+12]
!mov [v_d],eax
!mov eax,dword[r11+16]
!mov [v_e],eax
!mov eax,dword[r11+20]
!mov [v_f],eax
!mov eax,dword[r11+24]
!mov [v_g],eax
!mov eax,dword[r11+28]
!mov [v_h],eax
;Main Loop
!xor rcx,rcx ;hier mal so
!lea r11,[k] ;siehe Data
!@@:
;s0
!mov eax,[v_a]
!mov edx,eax
!mov r10d,eax
!ror eax,2
!ror edx,13
!xor eax,edx
!ror r10d,22
!xor r10d,eax ;r10d=s0
;maj (major)
!mov eax,[v_a]
!mov edx,[v_b]
!mov r9d,[v_c]
!mov r8d,eax
!and r8d,edx
!and eax,r9d
!xor r8d,eax
!and edx,r9d
!xor r8d,edx ;r8d=maj
;t2
!add r8d,r10d ;r8d=t2, r10d=s0
;s1
!mov eax,[v_e]
!mov edx,eax
!mov r10d,eax
!ror eax,6
!ror edx,11
!xor eax,edx
!ror r10d,25
!xor r10d,eax ;r10d=s1
;ch
!mov eax,[v_e]
!mov edx,eax
!and edx,[v_f]
!not eax
!and eax,[v_g]
!xor edx,eax ;edx=ch
;t1
!mov eax,[v_h]
!add eax,r10d ;s1
!add eax,edx ;ch
!add eax,dword[r11+rcx] ;k[i]
!mov r10d,dword[v_pW]
!add eax,dword[r10+rcx] ;eax=t1, r10+rcx=W[i]
;Vertauschungen
!mov edx,[v_g]
!mov [v_h],edx
!mov edx,[v_f]
!mov [v_g],edx
!mov edx,[v_e]
!mov [v_f],edx
!mov edx,[v_d]
!add edx,eax ;eax=t1
!mov [v_e],edx
!mov edx,[v_c]
!mov [v_d],edx
!mov edx,[v_b]
!mov [v_c],edx
!mov edx,[v_a]
!mov [v_b],edx
!add eax,r8d ;r8d=t2
!mov [v_a],eax
!add rcx,4
!cmp rcx,256
!jb @b
;am Ende jedes Chunks Hashs zu vorhandenen Werten aufaddieren
!mov r10,[v_pHash]
!mov eax,[v_a]
!add eax,dword[r10]
!mov [r10],eax
!mov eax,[v_b]
!add eax,dword[r10+4]
!mov [r10+4],eax
!mov eax,[v_c]
!add eax,dword[r10+8]
!mov [r10+8],eax
!mov eax,[v_d]
!add eax,dword[r10+12]
!mov [r10+12],eax
!mov eax,[v_e]
!add eax,dword[r10+16]
!mov [r10+16],eax
!mov eax,[v_f]
!add eax,dword[r10+20]
!mov [r10+20],eax
!mov eax,[v_g]
!add eax,dword[r10+24]
!mov [r10+24],eax
!mov eax,[v_h]
!add eax,dword[r10+28]
!mov dword[r10+28],eax
!add [v_pAllBlocks],64 ;512 Bit (64 Byte) weiter, nächster Chunk
!inc [v_ChunksSum] ;nur für Fortschritts-Balken
If ElapsedMilliseconds() - TF > 100
TF = ElapsedMilliseconds()
SetGadgetState(3, (ChunksSum * 100) / ChunksAll)
EndIf
!dec [v_Chunks]
!jnz Next_Chunk
!cmp [v_SizeAv],0
!je @f
FileSeek(0, Seek)
pAllBlocks = pAllBlocksOld
If SizeAv <= MemAv
MemAv = SizeAv
FreeMemory(pAllBlocks)
pAllBlocks = AllocateMemory(MemAv + 128)
Else
Chunks = ChunksOld
EndIf
!jmp File_Weiter
!@@:
FreeGadget(2) : FreeGadget(3)
For i = 0 To 31 Step 4
Hash$ + Hex(PeekL(pHash + i) & $FFFFFFFF) ;bei Bedarf in Zwischenablage kopieren
Next
TE = ElapsedMilliseconds() - TA
TextGadget(2, 10, 50, 560, 20, "SHA-256-Hash : " + Hash$)
TE$ = Str(TE) ;für 1000-er Trennpunkte
LT = Len(TE$)
LTMod = LT % 3
If LTMod = 0
LTMod = 3
EndIf
i = 3
j = 1
While LT - i > 0
TEP$ = InsertString(TE$, ".", LTMod + j)
i + 3
TE$ = TEP$
j + 4
Wend
TextGadget(3, 10, 70, 560, 20, "Benötigte Zeit : " + TE$ + " ms")
Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
EndIf
End
DataSection
HashBase:
;!h0: ;Fractional_Parts_Square_2_19, Big-Endian!
Data.l $6a09e667, $bb67ae85, $3c6ef372, $a54ff53a, $510e527f, $9b05688c, $1f83d9ab, $5be0cd19
!k: ;Fractional_Parts_Cube_2_311, Big-Endian!
Data.l $428a2f98, $71374491, $b5c0fbcf, $e9b5dba5, $3956c25b, $59f111f1, $923f82a4, $ab1c5ed5
Data.l $d807aa98, $12835b01, $243185be, $550c7dc3, $72be5d74, $80deb1fe, $9bdc06a7, $c19bf174
Data.l $e49b69c1, $efbe4786, $0fc19dc6, $240ca1cc, $2de92c6f, $4a7484aa, $5cb0a9dc, $76f988da
Data.l $983e5152, $a831c66d, $b00327c8, $bf597fc7, $c6e00bf3, $d5a79147, $06ca6351, $14292967
Data.l $27b70a85, $2e1b2138, $4d2c6dfc, $53380d13, $650a7354, $766a0abb, $81c2c92e, $92722c85
Data.l $a2bfe8a1, $a81a664b, $c24b8b70, $c76c51a3, $d192e819, $d6990624, $f40e3585, $106aa070
Data.l $19a4c116, $1e376c08, $2748774c, $34b0bcb5, $391c0cb3, $4ed8aa4a, $5b9cca4f, $682e6ff3
Data.l $748f82ee, $78a5636f, $84c87814, $8cc70208, $90befffa, $a4506ceb, $bef9a3f7, $c67178f2
EndDataSection
Viel Spaß!
Helle
Edit: 14.6.2011, nur Kosmetik