SHA-2 (SHA-224/256/384/512) für PB 64-Bit
Verfasst: 04.07.2011 20:45
Da mich diese Algos doch mal interessiert haben, hier ein 64-Bit-Prog für Text/Strings und Files. 64-Bit, weil eine 384/512-Realisierung mit 32-Bit sau-langsam ist. Dieser Code ist dafür ca. 5-mal schneller als 32-Bit-Programme, die ich zu Testzwecken verwendete (es gab auch Faktor 30). Um die Realisierung der Prozeduren in Assembler führt kein Weg vorbei (also bitte Nachsicht!
).
In diesem Zusammenhang würde es mich auch mal interessieren, wie weit der Verbreitungsgrad von PB 64-Bit z.Z. ist.
Viel Spaß
!
Helle

Code: Alles auswählen
;- SHA-2, Grundlage (Pseudo-Code) siehe engl. Wikipedia
;- "Helle" Klaus Helbing, 04.07.2011, PB 4.51 (x64)
;- 64-Bit-Windows-Version mit Nutzung von SSE2
;- Optimierungen für die "Krücken" SHA-224 und SHA-384 habe ich mir verkniffen
Global ChunksSum.d ;für Fortschrittsbalken größere Dateien
Global ChunksAll.d
Global p_a_h_A.q
Global pAllBlocksA.q
Global pHashA.q
Global pWA.q
Procedure Padding_224_256()
;Size wird auf Vielfaches von 512 Bit (64 Byte) gebracht (Blocklänge ist 512 Bit)
!mov r8,[v_pAllBlocksA]
!mov rax,[v_MemAv]
!mov r9,rax
!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[r8+rax],80h ;1 gesetztes Bit anhängen
!or rdx,rdx ;RDX=0?
;1.Fall: RDX=0. Letzter 512-Bit-Block ist Vielfaches von 512 (64 Byte). Es wird ein kompletter 512-Bit-Block angehängt
!jz @f
!sub r9,rdx
;2.Fall: RDX<56. Letzter 512-Bit-Block ist kleiner als 448 Bit (56 Byte), aber größer Null
!cmp rdx,56 ;448 Bit
!jb @f
;3.Fall: RDX>=56. 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
!add r8,64
!add [v_Chunks],1 ;es wurde ja ein Block drangehängt
!@@:
!mov rax,[v_Size]
!shl rax,3 ;reicht so für Filelänge ca. 2.3EB (ExaBytes, 10^18)
!bswap rax
!mov [r8+r9+56],rax ;Original-Länge als 64-Bit-Big-Endian-Wert anhängen
EndProcedure
Procedure Padding_384_512()
;Size wird auf Vielfaches von 1024 Bit (128 Byte) gebracht (Blocklänge ist 1024 Bit)
!mov r8,[v_pAllBlocksA]
!mov rax,[v_MemAv]
!mov r9,rax
!mov rcx,128 ;1024 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[r8+rax],80h ;1 gesetztes Bit anhängen
!or rdx,rdx ;RDX=0?
;1.Fall: RDX=0. Letzter 1024-Bit-Block ist Vielfaches von 1024 Bit (128 Byte). Es wird ein kompletter 1024-Bit-Block angehängt
!jz @f
!sub r9,rdx
;2.Fall: RDX<112. Letzter 1024-Bit-Block ist kleiner als 896 Bit (112 Byte), aber größer Null
!cmp rdx,112 ;896 Bit
!jb @f
;3.Fall: RDX>=112. Letzter 1024-Bit-Block ist größer/gleich als 896 Bit (112 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 128-Bit-Big-Endian-Wert
!add r8,128
!add [v_Chunks],1 ;es wurde ja ein Block drangehängt
!@@:
!mov rax,[v_Size]
!shl rax,3 ;reicht so für Filelänge ca. 2.3EB (ExaBytes, 10^18)
!bswap rax
!mov [r8+r9+120],rax ;Original-Länge als 128-Bit-Big-Endian-Wert anhängen, hier nur der Low-Wert als Quad
EndProcedure
Procedure Main_224_256()
;W[0] bis W[15]
!mov r11,[v_pAllBlocksA]
!mov r10,[v_pWA]
!mov rcx,16
!@@:
!mov eax,[r11]
!bswap eax
!mov [r10],eax
!add r10,4
!add r11,4
!sub rcx,1
!jnz @b
;W[16] bis W[63]
!mov rcx,48
!mov r11,[v_pWA]
!add r11,64
!@@:
;s0
!mov eax,[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,[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,[r11-64]
!add edx,r10d ;R10d=s0
!add edx,[r11-28]
!add edx,eax ;EAX=s1
!mov [r11],edx
!add r11,4
!sub rcx,1
!jnz @b
;Initialisierung
!mov r9,[v_p_a_h_A] ;wegen der PB-Einschübe hierhin (Neu-Initialisierung)
!mov r11,[v_pHashA]
!movdqa xmm0,[r11]
!movdqa xmm1,[r11+16]
!movdqa [r9],xmm0
!movdqa [r9+16],xmm1
;Main Loop
!xor rcx,rcx ;hier mal so
!lea r11,[k_224_256] ;siehe Data
!@@:
;s0
!mov eax,[r9] ;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) maj = (a and b) + (c and (a xor b)) NEU!
!mov eax,[r9] ;a
!mov edx,eax
!mov r8d,[r9+4] ;b
!xor eax,r8d ;(a xor b)
!and r8d,edx ;(a and b)
!and eax,[r9+8] ;c
!add r8d,eax ;R8d=maj
;t2
!add r8d,r10d ;R8d=t2, R10d=s0
;s1
!mov eax,[r9+16] ;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 ch = g xor (e and (f xor g)) NEU!
!mov eax,[r9+24] ;g
!mov edx,eax
!xor edx,[r9+20] ;f
!and edx,[r9+16] ;e
!xor edx,eax
;t1
!mov eax,[r9+28] ;h
!add eax,r10d ;s1
!add eax,edx ;ch
!add eax,[r11+rcx] ;k[i]
!mov r10,[v_pWA]
!add eax,[r10+rcx] ;EAX=t1, R10+rcx=W[i]
;Vertauschungen
!mov edx,[r9+12] ;"altes" d
!add edx,eax ;EAX=t1
!movdqa xmm0,[r9]
!movdqa xmm1,[r9+16]
!movdqu [r9+4],xmm0 ;mit Versatz von 4 Bytes zurückkopieren
!movdqu [r9+20],xmm1
!add eax,r8d ;EAX=t1, R8d=t2
!mov [r9],eax ;"neues" a
!mov [r9+16],edx ;"neues" e
!add rcx,4
!cmp rcx,256
!jb @b
;am Ende jedes Chunks Hashs zu vorhandenen Werten aufaddieren (Überträge werden ignoriert!)
!mov r10,[v_pHashA]
!movdqa xmm0,[r10]
!paddd xmm0,[r9]
!movdqa [r10],xmm0
!movdqa xmm0,[r10+16]
!paddd xmm0,[r9+16]
!movdqa [r10+16],xmm0
!add [v_pAllBlocksA],64 ;512 Bit (64 Byte) weiter, nächster Chunk
EndProcedure
Procedure Main_384_512()
;W[0] bis W[15]
!mov r11,[v_pAllBlocksA]
!mov r10,[v_pWA]
!mov rcx,16
!@@:
!mov rax,[r11]
!bswap rax
!mov [r10],rax
!add r10,8
!add r11,8
!sub rcx,1
!jnz @b
;W[16] bis W[79]
!mov rcx,64
!mov r11,[v_pWA]
!add r11,128
!@@:
;s0
!mov rax,[r11-120]
!mov rdx,rax
!mov r10,rax
!ror rax,1
!ror rdx,8
!shr r10,7
!xor rax,rdx
!xor r10,rax
;s1
!mov rax,[r11-16]
!mov rdx,rax
!mov r8,rax
!ror rax,19
!ror rdx,61
!xor rax,rdx
!shr r8,6
!xor rax,r8
;W[i]
!mov rdx,[r11-128]
!add rdx,r10 ;R10=s0
!add rdx,[r11-56]
!add rdx,rax ;RAX=s1
!mov [r11],rdx
!add r11,8
!sub rcx,1
!jnz @b
;Initialisierung
!mov r9,[v_p_a_h_A] ;wegen der PB-Einschübe hierhin (Neu-Initialisierung)
!mov r11,[v_pHashA]
!movdqa xmm0,[r11]
!movdqa xmm1,[r11+16]
!movdqa xmm2,[r11+32]
!movdqa xmm3,[r11+48]
!movdqa [r9],xmm0
!movdqa [r9+16],xmm1
!movdqa [r9+32],xmm2
!movdqa [r9+48],xmm3
;Main Loop
!xor rcx,rcx ;hier mal so
!lea r11,[k_384_512] ;siehe Data
!@@:
;s0
!mov rax,[r9] ;a
!mov rdx,rax
!mov r10,rax
!ror rax,28
!ror rdx,34
!xor rax,rdx
!ror r10,39
!xor r10,rax ;R10=s0
;maj (major) maj = (a and b) + (c and (a xor b)) NEU!
!mov rax,[r9] ;a
!mov rdx,rax
!mov r8,[r9+8] ;b
!xor rax,r8 ;(a xor b)
!and r8,rdx ;(a and b)
!and rax,[r9+16] ;c
!add r8,rax ;R8=maj
;t2
!add r8,r10 ;R8=t2, R10=s0
;s1
!mov rax,[r9+32] ;e
!mov rdx,rax
!mov r10,rax
!ror rax,14
!ror rdx,18
!xor rax,rdx
!ror r10,41
!xor r10,rax ;R10=s1
;ch ch = g xor (e and (f xor g)) NEU!
!mov rax,[r9+48] ;g
!mov rdx,rax
!xor rdx,[r9+40] ;f
!and rdx,[r9+32] ;e
!xor rdx,rax
;t1
!mov rax,[r9+56] ;h
!add rax,r10 ;s1
!add rax,rdx ;ch
!add rax,[r11+rcx] ;k[i]
!mov r10,[v_pWA]
!add rax,[r10+rcx] ;RAX=t1, R10+RCX=W[i]
;Vertauschungen
!mov rdx,[r9+24] ;"altes" d
!add rdx,rax ;RAX=t1
!movdqa xmm0,[r9]
!movdqa xmm1,[r9+16]
!movdqa xmm2,[r9+32]
!movdqa xmm3,[r9+48]
!movdqu [r9+8],xmm0 ;mit Versatz von 8 Bytes zurückkopieren
!movdqu [r9+24],xmm1
!movdqu [r9+40],xmm2
!movdqu [r9+56],xmm3
!add rax,r8 ;RAX=t1, R8=t2
!mov [r9],rax ;"neues" a
!mov [r9+32],rdx ;"neues" e
!add rcx,8
!cmp rcx,640
!jb @b
;am Ende jedes Chunks Hashs zu vorhandenen Werten aufaddieren (Überträge werden ignoriert!)
!mov r10,[v_pHashA]
!movdqa xmm0,[r10]
!paddq xmm0,[r9]
!movdqa [r10],xmm0
!movdqa xmm0,[r10+16]
!paddq xmm0,[r9+16]
!movdqa [r10+16],xmm0
!movdqa xmm0,[r10+32]
!paddq xmm0,[r9+32]
!movdqa [r10+32],xmm0
!movdqa xmm0,[r10+48]
!paddq xmm0,[r9+48]
!movdqa [r10+48],xmm0
!add [v_pAllBlocksA],128 ;1024 Bit (128 Byte) weiter, nächster Chunk
EndProcedure
If OpenWindow(0, 0, 0, 1000, 450, "Helles SHA-2, 64-Bit-Windows", #PB_Window_MinimizeGadget | #PB_Window_ScreenCentered)
Repeat ;hier rigoros für neue Abfrage
OptionGadget(0, 10, 10, 80, 20, "SHA-224")
OptionGadget(1, 10, 35, 80, 20, "SHA-256")
OptionGadget(2, 10, 60, 80, 20, "SHA-384")
OptionGadget(3, 10, 85, 80, 20, "SHA-512")
SetGadgetState(1, 1)
PanelGadget(4, 110, 10, 880, 300)
AddGadgetItem (4, -1, "Text eingeben ")
EditorGadget(5, 10, 10, 855, 250)
AddGadgetItem (4, -1, "Zwischenablage einfügen ")
EditorGadget(6, 10, 10, 855, 250)
AddGadgetItem (4, -1,"File auswählen ")
TextGadget(7, 10, 10, 230, 15, "Select a File :")
ExplorerTreeGadget(8, 10, 30, 855, 230, "", #PB_Explorer_NoDriveRequester)
CloseGadgetList()
SetActiveGadget(5)
ButtonGadget(9, 450, 350, 100, 20, "Los !", #PB_Button_Toggle)
Repeat
Event = WaitWindowEvent()
If GetGadgetState(4) = 2 And GetGadgetState(8) <> #PB_Explorer_File
DisableGadget(9, 1)
If Toggle
Toggle ! 1
EndIf
Else
DisableGadget(9, 0)
EndIf
If GetGadgetState(4) = 1 And Toggle = 0
SetGadgetText(6, GetClipboardText())
Toggle ! 1
ElseIf GetGadgetState(4) = 0
If Toggle
Toggle ! 1
EndIf
EndIf
If Event = #PB_Event_CloseWindow
End
EndIf
Until GetGadgetState(9) Or (EventType() = #PB_EventType_LeftDoubleClick And GetGadgetState(8) = #PB_Explorer_File)
FreeGadget(9)
Select GetGadgetState(4)
Case 0
Input$ = GetGadgetText(5)
Case 1
Input$ = GetGadgetText(6)
Case 2
File = 1
EndSelect
For SubMode = 0 To 3
If GetGadgetState(SubMode)
Break
EndIf
Next
Select SubMode
Case 0
Mode = 1
SHA$ = "SHA-224-Hash : "
pHashBase = ?HashBase_224
Case 1
Mode = 1
SHA$ = "SHA-256-Hash : "
pHashBase = ?HashBase_256
Case 2
Mode = 2
SHA$ = "SHA-384-Hash : "
pHashBase = ?HashBase_384
Case 3
Mode = 2
SHA$ = "SHA-512-Hash : "
pHashBase = ?HashBase_512
EndSelect
TA = ElapsedMilliseconds()
TF1 = TA ;nur für Fortschritts-Balken
TF2 = TA ;für Durchsatz
If File
File$ = GetGadgetText(8)
ReadFile(0, File$)
Size = Lof(0)
Else
Size = Len(Input$)
File$ = "String"
pInput = @Input$
EndIf
SizeAv = Size
ChunksAll = (Size / (64 * Mode)) + 1 ;nur für Fortschritts-Balken
If Size > $40000
MemAv = $40000
Chunks = $1000 / Mode
ChunksOld = Chunks
Else
MemAv = Size
ChunksOld = ChunksAll
EndIf
SizeP$ = Str(Size) ;für Anzeige File-Länge < 1000 Bytes
TextGadget(9, 10, 320, 960, 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(10, 10, 340, 560, 20, "File-Länge : " + SizeP$ + " Bytes")
TextGadget(11, 10, 360, 100, 20, "Durchsatz (MB/s) : ")
TextGadget(12, 110,360, 100, 20, "")
TextGadget(13, 425,380, 200, 20, "Berechnungs-Fortschritt :")
ProgressBarGadget(14, 25,405, 950, 25, 0, 100, #PB_ProgressBar_Smooth)
TextGadget(15, 550, 380, 50, 20, "")
If Size <= MemAv
MemAv = Size
EndIf
pW = AllocateMemory(640 + 16)
i = pW % 16
pWA = pW - i + 16
p_a_h = AllocateMemory(72 + 16) ;für a-h, 72 wegen verschobenes Rückkopieren beim Vertauschen
i = p_a_h % 16
p_a_h_A = p_a_h - i + 16 ;jetzt 16-Byte-Alignment
pHash = AllocateMemory(64 + 16) ;damit Hash-Startwerte erhalten bleiben
i = pHash % 16
pHashA = pHash - i + 16
CopyMemory(pHashBase, pHashA, 32 * Mode)
pAllBlocks = AllocateMemory(MemAv + 256 + 16) ;(großzügig bemessener) Speicher für die 512/1024-Bit-Blöcke
i = pAllBlocks % 16
pAllBlocksA = pAllBlocks - i + 16
pAllBlocksOld = pAllBlocksA
If Size = 0 ;damit auch Länge=0 berücksichtigt wird
If File
CloseFile(0)
EndIf
If Mode = 1 ;224/256
Padding_224_256()
Main_224_256()
Else ;384/512
Padding_384_512()
Main_384_512()
EndIf
EndIf
While SizeAv
If File
If Size = -1
MessageRequester("Fehler!", "Zugriff auf File fehlgeschlagen (System-File?)")
Break
EndIf
BytesRead = ReadData(0, pAllBlocksA, MemAv) ;Datei in Speicher einlesen
Seek + BytesRead
FileSeek(0, Seek)
SizeAv - BytesRead
Else
CopyMemory(pInput, pAllBlocksA, MemAv) ;lässt sich sicher noch verfeinern (kein umkopieren der "Vollblöcke")
SizeAv - MemAv
pInput + MemAv
EndIf
If SizeAv <= 0
If File
CloseFile(0)
EndIf
If Mode = 1 ;224/256
Padding_224_256()
Else ;384/512
Padding_384_512()
EndIf
EndIf
While Chunks ;1024 Bit (128 Byte) oder 512 Bit (64 Byte)
If Mode = 1 ;224/256
Main_224_256()
Else ;384/512
Main_384_512()
EndIf
ChunksSum + 1 ;nur für Fortschritts-Balken
TF = ElapsedMilliseconds()
If TF - TF1 > 100
If TF - TF2 > 500
SetGadgetText(12, StrF((ChunksSum - ChunksSum1) * 0.064 * Mode / (TF - TF2), 3))
SetGadgetText(15, StrD((ChunksSum / ChunksAll) * 100, 1) + "%")
TF2 = TF
ChunksSum1 = ChunksSum
EndIf
TF1 = TF
SetGadgetState(14, (ChunksSum / ChunksAll) * 100)
EndIf
Chunks - 1
Wend
pAllBlocksA = pAllBlocksOld
If SizeAv <= MemAv
MemAv = SizeAv
FreeMemory(pAllBlocks)
pAllBlocks = AllocateMemory(MemAv + 256 + 16)
i = pAllBlocks % 16
pAllBlocksA = pAllBlocks - i + 16
Else
Chunks = ChunksOld
EndIf
Wend
FreeGadget(13) : FreeGadget(14) : FreeGadget(15)
If Mode = 1 ;224/256
If SubMode = 0
j = 24
Else
j = 28
EndIf
For i = 0 To j Step 4
Hash$ + RSet(Hex(PeekL(pHashA + i) & $FFFFFFFF), 8, "0")
Next
Else ;384/512
If SubMode = 2
j = 40
Else
j = 56
EndIf
For i = 0 To j Step 8
Hash$ + RSet(Hex(PeekQ(pHashA + i)), 16, "0")
Next
EndIf
TE = ElapsedMilliseconds() - TA
TextGadget(13, 10, 380, 960, 20, SHA$ + 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
SetGadgetText(12, StrF(Size / ((TE + 1) * 1000), 3))
TextGadget(14, 10, 400, 560, 20, "Benötigte Zeit : " + TE$ + " ms")
For i = 0 To 8
DisableGadget(i, 1)
Next
ButtonGadget(16, 125, 420, 250, 20, "Ergebnis in Zwischenablage kopieren", #PB_Button_Toggle)
ButtonGadget(17, 425, 415, 150, 30, "E N D E", #PB_Button_Toggle)
ButtonGadget(18, 625, 420, 250, 20, "Neue Auswahl", #PB_Button_Toggle)
Repeat
Event = WaitWindowEvent()
If GetGadgetState(16)
SetClipboardText(Hash$)
SetGadgetState(16, 0)
EndIf
If GetGadgetState(17)
Quit = 1
Break
EndIf
If GetGadgetState(18)
FreeMemory(pW)
FreeMemory(p_a_h)
FreeMemory(pHash)
FreeMemory(pAllBlocks)
File$ = ""
Hash$ = ""
ChunksSum = 0
ChunksSum1 = 0
File = 0
Seek = 0
TF1 = 0
TF2 = 0
For i = 0 To 18
FreeGadget(i)
Next
Break
EndIf
If Event = #PB_Event_CloseWindow
Quit = 1
Break
EndIf
ForEver
Until Quit
EndIf
End
DataSection
HashBase_224: ;The second 32 bits of the fractional parts of the square roots of the 9th through 16th primes 23...53, Big-Endian!
Data.l $c1059ed8, $367cd507, $3070dd17, $f70e5939, $ffc00b31, $68581511, $64f98fa7, $befa4fa4
HashBase_256: ;The first 32 bits of the fractional parts of the square roots of the first 8 primes 2...19, Big-Endian!
Data.l $6a09e667, $bb67ae85, $3c6ef372, $a54ff53a, $510e527f, $9b05688c, $1f83d9ab, $5be0cd19
HashBase_384: ;The first 64 bits of the fractional parts of the square roots of the 9th through 16th primes 23...53, Big-Endian!
Data.q $cbbb9d5dc1059ed8, $629a292a367cd507, $9159015a3070dd17, $152fecd8f70e5939
Data.q $67332667ffc00b31, $8eb44a8768581511, $db0c2e0d64f98fa7, $47b5481dbefa4fa4
HashBase_512: ;The first 64 bits of the fractional parts of the square roots of the first 8 primes 2...19, Big-Endian!
Data.q $6a09e667f3bcc908, $bb67ae8584caa73b, $3c6ef372fe94f82b, $a54ff53a5f1d36f1
Data.q $510e527fade682d1, $9b05688c2b3e6c1f, $1f83d9abfb41bd6b, $5be0cd19137e2179
!k_224_256: ;The first 32 bits of the fractional parts of the cube roots of the first 64 primes 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
!k_384_512: ;The first 64 bits of the fractional parts of the cube roots of the first 80 primes 2...409, Big-Endian!
Data.q $428a2f98d728ae22, $7137449123ef65cd, $b5c0fbcfec4d3b2f, $e9b5dba58189dbbc
Data.q $3956c25bf348b538, $59f111f1b605d019, $923f82a4af194f9b, $ab1c5ed5da6d8118
Data.q $d807aa98a3030242, $12835b0145706fbe, $243185be4ee4b28c, $550c7dc3d5ffb4e2
Data.q $72be5d74f27b896f, $80deb1fe3b1696b1, $9bdc06a725c71235, $c19bf174cf692694
Data.q $e49b69c19ef14ad2, $efbe4786384f25e3, $0fc19dc68b8cd5b5, $240ca1cc77ac9c65
Data.q $2de92c6f592b0275, $4a7484aa6ea6e483, $5cb0a9dcbd41fbd4, $76f988da831153b5
Data.q $983e5152ee66dfab, $a831c66d2db43210, $b00327c898fb213f, $bf597fc7beef0ee4
Data.q $c6e00bf33da88fc2, $d5a79147930aa725, $06ca6351e003826f, $142929670a0e6e70
Data.q $27b70a8546d22ffc, $2e1b21385c26c926, $4d2c6dfc5ac42aed, $53380d139d95b3df
Data.q $650a73548baf63de, $766a0abb3c77b2a8, $81c2c92e47edaee6, $92722c851482353b
Data.q $a2bfe8a14cf10364, $a81a664bbc423001, $c24b8b70d0f89791, $c76c51a30654be30
Data.q $d192e819d6ef5218, $d69906245565a910, $f40e35855771202a, $106aa07032bbd1b8
Data.q $19a4c116b8d2d0c8, $1e376c085141ab53, $2748774cdf8eeb99, $34b0bcb5e19b48a8
Data.q $391c0cb3c5c95a63, $4ed8aa4ae3418acb, $5b9cca4f7763e373, $682e6ff3d6b2b8a3
Data.q $748f82ee5defb2fc, $78a5636f43172f60, $84c87814a1f0ab72, $8cc702081a6439ec
Data.q $90befffa23631e28, $a4506cebde82bde9, $bef9a3f7b2c67915, $c67178f2e372532b
Data.q $ca273eceea26619c, $d186b8c721c0c207, $eada7dd6cde0eb1e, $f57d4f7fee6ed178
Data.q $06f067aa72176fba, $0a637dc5a2c898a6, $113f9804bef90dae, $1b710b35131c471b
Data.q $28db77f523047d84, $32caab7b40c72493, $3c9ebe0a15c9bebc, $431d67c49c100d4c
Data.q $4cc5d4becb3e42b6, $597f299cfc657e2a, $5fcb6fab3ad6faec, $6c44198c4a475817
EndDataSection
Viel Spaß

Helle