Den Pseudo-Code von der englischen Wikipedia habe ich mal für PB umgesetzt; natürlich die Routinen in ASM (also FAsm). Es ist ganz allgemein gehalten; jeder kann daraus Prozeduren oder sonstwas machen. Bei div.Tests konnte ich keine Fehler feststellen (bei halbwegs normalen Stringlängen, Test mit max. 1.000.000 Bytes). Optimierungen sind sicher noch möglich (SSE).
Code: Alles auswählen
;- SHA-256, Test für PB. Grundlage (Pseudo-Code) siehe engl. Wikipedia
;- "Helle" Klaus Helbing, 12.06.2011, PB4.51 (x86)
;- 32-Bit-Windows, kein Unicode
Global Size.l
Global pSource.l
Global pAllBlocks.l
Global Chunks.l
Global pW.l
Global a.l
Global b.l
Global c.l
Global d.l
Global e.l
Global f.l
Global g.l
Global h.l
Source$ = "Franz jagt im komplett verwahrlosten Taxi quer durch Bayern"
;Source$ = ""
;Source$ = "abc"
pSource = @Source$ ;Pointer auf den Teststring
Size = Len(Source$) ;Länge des Teststrings
pAllBlocks = AllocateMemory(Size + 128) ;(großzügig bemessener) Speicher für die 512-Blöcke
pW = AllocateMemory(256)
;der Einfachheit halber wird der Teststring in den 512-Bit-Block-Speicher umkopiert
CopyMemory(pSource, pAllBlocks, Size)
!pushad
;Preprocessing, Size wird auf Vielfaches von 512 Bit (64 Byte) gebracht (Blocklänge ist 512 Bit)
!mov edi,[v_pAllBlocks]
!mov eax,[v_Size]
!mov ebx,eax
!mov esi,eax
!shl esi,3 ;Länge in Bits!
!bswap esi ;Size auf Big-Endian bringen
!mov ecx,64 ;512 Bit
!cdq
!div ecx ;Modulo steht in edx
!inc eax ;eine Runde wollen wir ja wenigstens!
!mov [v_Chunks],eax
!mov eax,[v_Size]
!mov byte[edi+eax],80h ;Bit mit Wert 1 anhängen (wird 1 durch bswap)
!or edx,edx ;edx=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 [edi+ebx+60],esi ;Original-Länge als 64-Bit-Big-Endian-Wert anhängen
!jmp End_Preprocessing
!@@:
!cmp edx,56 ;448 Bit
!jae @f
;2.Fall: Letzter 512-Bit-Block ist kleiner als 448 Bit (56 Byte), aber größer Null
!sub ebx,edx
!mov [edi+ebx+60],esi ;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 ebx,edx
!mov [edi+ebx+124],esi ;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 ecx,16
!mov esi,[v_pAllBlocks]
!mov edi,[v_pW]
!@@:
!mov eax,[esi] ;(erweiterten) Source einlesen
!bswap eax ;auf Big-Endian bringen
!mov [edi],eax
!add edi,4
!add esi,4
!dec ecx
!jnz @b
;W[16] bis W[63]
!mov ecx,48
!mov esi,[v_pW]
!add esi,64
!@@:
;s0
!mov eax,[esi-60]
!mov edx,eax
!mov edi,eax
!ror eax,7
!ror edx,18
!shr edi,3
!xor eax,edx
!xor edi,eax
;s1
!mov eax,[esi-8]
!mov edx,eax
!mov ebx,eax
!ror eax,17
!ror edx,19
!xor eax,edx
!shr ebx,10
!xor eax,ebx
;W[i]
!mov edx,[esi-64]
!add edx,edi ;edi=s0
!add edx,[esi-28]
!add edx,eax ;eax=s1
!mov [esi],edx
!add esi,4
!dec ecx
!jnz @b
;Initialisierung
!lea esi,[h0] ;siehe Data
!mov eax,[esi]
!mov [v_a],eax
!mov eax,[esi+4]
!mov [v_b],eax
!mov eax,[esi+8]
!mov [v_c],eax
!mov eax,[esi+12]
!mov [v_d],eax
!mov eax,[esi+16]
!mov [v_e],eax
!mov eax,[esi+20]
!mov [v_f],eax
!mov eax,[esi+24]
!mov [v_g],eax
!mov eax,[esi+28]
!mov [v_h],eax
;Main Loop
!xor ecx,ecx ;hier mal so
!lea esi,[k] ;siehe Data
!@@:
;s0
!mov eax,[v_a]
!mov edx,eax
!mov edi,eax
!ror eax,2
!ror edx,13
!xor eax,edx
!ror edi,22
!xor edi,eax ;edi=s0
;maj (major)
!mov eax,[v_a]
!mov edx,[v_b]
!mov ebx,eax
!and ebx,edx
!and eax,[v_c] ;Verwendung von ebp habe ich mir verkniffen
!xor ebx,eax
!and edx,[v_c]
!xor ebx,edx ;ebx=maj
;t2
!add ebx,edi ;ebx=t2, edi=s0
;s1
!mov eax,[v_e]
!mov edx,eax
!mov edi,eax
!ror eax,6
!ror edx,11
!xor eax,edx
!ror edi,25
!xor edi,eax ;edi=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,edi ;s1
!add eax,edx ;ch
!add eax,[esi+ecx] ;k[i]
!mov edi,[v_pW]
!add eax,[edi+ecx] ;eax=t1, edi+ecx=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,ebx ;ebx=t2
!mov [v_a],eax
!add ecx,4
!cmp ecx,256
!jb @b
;am Ende jedes Chunks Hashs zu vorhandenen Werten aufaddieren
!lea edi,[h0]
!mov eax,[v_a]
!add eax,[edi]
!mov [edi],eax
!mov eax,[v_b]
!add eax,[edi+4]
!mov [edi+4],eax
!mov eax,[v_c]
!add eax,[edi+8]
!mov [edi+8],eax
!mov eax,[v_d]
!add eax,[edi+12]
!mov [edi+12],eax
!mov eax,[v_e]
!add eax,[edi+16]
!mov [edi+16],eax
!mov eax,[v_f]
!add eax,[edi+20]
!mov [edi+20],eax
!mov eax,[v_g]
!add eax,[edi+24]
!mov [edi+24],eax
!mov eax,[v_h]
!add eax,[edi+28]
!mov [edi+28],eax
!add [v_pAllBlocks],64 ;512 Bit (64 Byte) weiter, nächster Chunk
!dec [v_Chunks]
!jnz Next_Chunk
!popad
For i = 0 To 31 Step 4
Hash$ + Hex(PeekL(?Hash + i) & $FFFFFFFF)
Next
MessageRequester("Helles SHA-256-Test", Source$ + #LFCR$ + Hash$)
End
;Vergleichswerte:
;"" = e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
;"abc" = BA7816BF8F01CFEA414140DE5DAE2223B00361A396177A9CB410FF61F20015AD
;"abcd" = 88d4266fd4e6338d13b845fcf289579d209c897823b9217da3e161936f031589
;"Franz jagt im komplett verwahrlosten Taxi quer durch Bayern"
; = d32b568cd1b96d459e7291ebf4b25d007f275c9f13149beeb782fac0716613f8
;"Frank jagt im komplett verwahrlosten Taxi quer durch Bayern"
; = 78206a866dbb2bf017d8e34274aed01a8ce405b69d45db30bafa00f5eeed7d5e
DataSection
Hash:
!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