Assembly Language Programming

FASM – x86 Secure Hash Algorithm

In this post I implement the Secure Hash Algorithm in x86 assembly language, using the Flat Assembler (FASM). This code is based on the latest version of the Secure Hash Standard (SHS) as specified in FIPS PUB 180-4:

Specifications

 ```SHA-1, SHA-224, SHA-256: - Message is processed in blocks of 512 bits (64 bytes) - Each block is further divided into 32 bit words (4 bytes) - Size of the message can be up to 264 bits Output hash sizes: - SHA-1 = 160 bits (20 bytes or 5 words) - SHA-224 = 224 bits (28 bytes or 7 words) - SHA-256 = 256 bits (32 bytes or 8 words) SHA-384, SHA-512: - Message is processed in blocks of 1024 bits (128 bytes) - Each block is further divided into 64 bit double words (8 bytes) - Size of the message can be up to 2128 bits Output hash sizes: - SHA-384 = 384 bits (48 bytes or 6 double words) - SHA-512 = 512 bits (64 bytes or 8 double words) ```

Hash Calculation: SHA-1, SHA-224, SHA-256

 ```(1) Pre-process the input message : Pad the input data such that the length of the input message in bits is a multiple of 512. Divide up the input message into a sequence of 512 bit blocks. (2) Calculate the hash : Set an initial hash value. Iterate the hash value by passing the blocks to the hash function one at a time. (3) For each block : Use the block to generate an 80 word (SHA-1) or 64 word (SHA-224, SHA-256) message schedule array from the block. Use the message schedule array and the current hash value to compute the next intermediate hash value. (4) Get the next block and repeat (3). ```

Hash Calculation: SHA-384, SHA-512

 ```(1) Pre-process the input message : Pad the input data such that the length of the input message in bits is a multiple of 1024. Divide up the input message into a sequence of 1024 bit blocks. (2) Calculate the hash : Set an initial hash value. Iterate the hash value by passing the blocks to the hash function one at a time. (3) For each block : Use the block to generate an 80 double word message schedule array from the block. Use the message schedule array and the current hash value to compute the next intermediate hash value. (4) Get the next block and repeat (3). ```

A message must be padded such that its size is a multiple of 512 bits (SHA-1, SHA-224, SHA-256) or 1024 bits (SHA-384, SHA-512):

 ```(1) The special case of an empty message (bit length = 0): - A padding block of 512/1024 bits is created. - All bits are initialised to zero. - The first bit is then set to 1. - The message length is zero, so the final 64/128 bits in the block already give the bit length. (2) The bit length of the message is already a multiple of 512/1024 bits: - An additional padding block of 512/1024 bits is still needed. - All bits in this padding block are initialised to zero. - The first bit is then set to 1. - The final 64/128 bits in the block are set to the bit length of the message. (3) The bit length of the last block is less than 448 bits (for SHA-1/224/256) or 896 bits (SHA-364/512): - Add padding bits to this last block such that its length becomes 512/1024 bits. - Initialise these bits to zero. - Set the bit immediately after the last message bit to 1. - Set the final 64/128 bits to the bit length of the message. (4) The bit length of the last block is greater than or equal to 448 bits or 896 bits: - The padding requires a minimum of 65/129 bits to accommodate the '1' bit and the 64/128 bit message length. - Padding bits are added to this last block such that its length becomes 512/1024 bits. - These bits are initialised to zero. - The bit immediately after the last message bit is set to 1. - Then another padding block of 512/1024 bits is created. - All bits in this padding block are initialised to zero. - The final 64/128 bits in this padding block are set to the bit length of the message. ```

Message Byte Ordering

The input message for the secure hash algorithm is in Big Endian byte order. That is, the most significant byte in the message (the first byte) is stored in the lowest memory address. However, for processing purposes the message blocks are divided up into 32 bit or 64 bit words. Since x86 uses the Little Endian byte order, the byte order within each word will need to be reversed. In the code below, this byte reversal process occurs when the 512/1024 bit blocks from the original message are copied into the message schedule.

The Program

To use the program enter the message as either a hexadecimal number or a text string. Then press either the [SHA(HEX)] or [SHA(TXT)] buttons. If the message is entered as a hex number, it is OK for it to contain whitespace and CRLF characters for formatting purposes. These will be stripped out when the hex number is read into memory.

To grab this code, select it with the mouse and copy it. It can then be pasted directly into the FASM IDE.

 ```; ------------------------------------------------------------------------------------- format PE GUI 4.0 entry start include 'win32a.inc' ; ------------------------------------------------------------------------------------- IDD_THE_DIALOG = 102 IDC_INPUT = 1000 IDC_OUTPUT = 1001 IDC_BTN_SHA_HEX = 1002 IDC_BTN_SHA_TXT = 1003 IDC_BTN_RESET = 1004 ; ------------------------------------------------------------------------------------- IN_STR_MAX_LENGTH = 14000 MESSAGE_LENGTH = 5120 ; ------------------------------------------------------------------------------------- section '.code' code readable executable start: invoke GetModuleHandle,0 invoke DialogBoxParam,eax,IDD_THE_DIALOG,0,DialogProc,0 exit: invoke ExitProcess,0 ; ------------------------------------------------------------------------------------- proc DialogProc uses esi edi ebx,hwnddlg,msg,wparam,lparam cmp [msg],WM_INITDIALOG je .wminitdialog cmp [msg],WM_COMMAND je .wmcommand cmp [msg],WM_CLOSE je .wmclose xor eax,eax jmp .quit .wminitdialog: invoke SetDlgItemText,[hwnddlg],IDC_INPUT,szInitText invoke SetDlgItemText,[hwnddlg],IDC_OUTPUT,"" jmp .done .wmcommand: cmp [wparam], BN_CLICKED shl 16 + IDC_BTN_SHA_HEX je .SHA_HEX cmp [wparam], BN_CLICKED shl 16 + IDC_BTN_SHA_TXT je .SHA_TXT cmp [wparam], BN_CLICKED shl 16 + IDC_BTN_RESET je .RESET jmp .done .SHA_HEX: invoke GetDlgItemText,[hwnddlg],IDC_INPUT,bfDisplay,IN_STR_MAX_LENGTH stdcall StrToMessageBuffer stdcall Compute_Hash stdcall Print_Hash invoke SetDlgItemText,[hwnddlg],IDC_OUTPUT,bfDisplay jmp .done .SHA_TXT: invoke GetDlgItemText,[hwnddlg],IDC_INPUT,bfDisplay,IN_STR_MAX_LENGTH stdcall TextToMessageBuffer stdcall Compute_Hash stdcall Print_Hash invoke SetDlgItemText,[hwnddlg],IDC_OUTPUT,bfDisplay jmp .done .RESET: invoke SetDlgItemText,[hwnddlg],IDC_INPUT,szInitText invoke SetDlgItemText,[hwnddlg],IDC_OUTPUT,"" jmp .done .wmclose: invoke EndDialog,[hwnddlg],0 .done: mov eax,1 .quit: ret endp ; ------------------------------------------------------------------------------------- proc ResetMessageBuffer uses edi ecx ; clear the message buffer lea edi,[MESSAGE] mov cx,0 .CLEAR: mov [edi],byte 0 inc edi inc cx cmp cx,MESSAGE_LENGTH jl .CLEAR ret endp ; ------------------------------------------------------------------------------------- proc TextToMessageBuffer ; input is a text string ; copy the bytes to the message buffer lea esi,[bfDisplay] lea edi,[MESSAGE] mov ecx,0 .COPY: mov al,[esi] cmp al,0 je .DONE mov [edi],al inc esi inc edi inc ecx cmp ecx,MESSAGE_LENGTH jl .COPY .DONE: ; ECX gives the number of chars (bytes) that were read shl ecx,3 mov [BitLength],ecx ret endp ; ------------------------------------------------------------------------------------- proc StrToHexStr uses esi edi ; filter out any non hex digit characters from the bfDisplay string lea esi,[bfDisplay] lea edi,[bfDisplay] .FILTER: mov al,[esi] cmp al,0 je .DONE cmp al,48 jl .NOT_HEX cmp al,57 jle .COPY cmp al,65 jl .NOT_HEX cmp al,70 jle .COPY cmp al,97 jl .NOT_HEX cmp al,102 jg .NOT_HEX .COPY: mov [edi],al inc edi .NOT_HEX: inc esi jmp .FILTER .DONE: ; null terminate the new string mov [edi],byte 0 ret endp ; ------------------------------------------------------------------------------------- proc HexDigitToValue ; convert a hex digit to a 4 bit value ; input in AL - output in AL ; is AL in the range: 48 - 57 (0 - 9) ? cmp al,48 jl .NOT_HEX cmp al,57 jg .A_Z sub al,48 jmp .DONE .A_Z: ; is AL in the range: 65 - 70 (A - B) ? cmp al,65 jl .NOT_HEX cmp al,70 jg .a_z sub al,55 jmp .DONE .a_z: ; is AL in the range: 97 - 102 (a - b) ? cmp al,97 jl .NOT_HEX cmp al,102 jg .NOT_HEX sub al,87 jmp .DONE .NOT_HEX: ; set EAX to 0xffff if input is not a valid hex digit mov eax,0xffff .DONE: ret endp ; ------------------------------------------------------------------------------------- proc ByteToDigits ; convert 1 byte to 2 hex digits ; input in AL - output in AX ; copy AL to AH mov ah,al ; AH: get the upper 4 bits of the byte shr ah,4 ; nibble to hex digit add ah,48 cmp ah,57 jle .NEXT add ah,7 .NEXT: ; AL: get the lower 4 bits of the byte and al,0xf ; nibble to hex digit add al,48 cmp al,57 jle .DONE add al,7 .DONE: ; output is in AX ret endp ; ------------------------------------------------------------------------------------- macro PRINT_CRLF { mov [edi],byte 13 inc edi mov [edi],byte 10 inc edi mov [edi],byte 13 inc edi mov [edi],byte 10 inc edi } ; ------------------------------------------------------------------------------------- proc Print_Hash uses esi edi lea edi,[bfDisplay] ; print the bit length and number of message blocks mov [edi],dword "Bit " add edi,4 mov [edi],dword "Leng" add edi,4 mov [edi],dword "th: " add edi,4 mov eax,[BitLength] stdcall DWordToStr mov [edi],byte 9 inc edi mov [edi],dword "nBlo" add edi,4 mov [edi],dword "cks5" add edi,4 mov [edi],dword "12: " add edi,4 mov eax,[nBlocks512] stdcall DWordToStr mov [edi],byte 9 inc edi mov [edi],dword "nBlo" add edi,4 mov [edi],dword "cks1" add edi,4 mov [edi],dword "024:" add edi,4 mov [edi],byte 32 inc edi mov eax,[nBlocks1024] stdcall DWordToStr PRINT_CRLF ; print the SHA-1 result mov [edi],dword "SHA-" add edi,4 mov [edi],word "1:" add edi,2 PRINT_CRLF lea esi,[H_0_1] mov eax,[esi] stdcall DWordToStr mov eax,[esi+4] stdcall DWordToStr mov eax,[esi+8] stdcall DWordToStr mov eax,[esi+12] stdcall DWordToStr mov eax,[esi+16] stdcall DWordToStr PRINT_CRLF ; print the SHA-224 result mov [edi],dword "SHA-" add edi,4 mov [edi],dword "224:" add edi,4 PRINT_CRLF lea esi,[H_0_224] mov eax,[esi] stdcall DWordToStr mov eax,[esi+4] stdcall DWordToStr mov eax,[esi+8] stdcall DWordToStr mov eax,[esi+12] stdcall DWordToStr mov eax,[esi+16] stdcall DWordToStr mov eax,[esi+20] stdcall DWordToStr mov eax,[esi+24] stdcall DWordToStr PRINT_CRLF ; print the SHA-256 result mov [edi],dword "SHA-" add edi,4 mov [edi],dword "256:" add edi,4 PRINT_CRLF lea esi,[H_0_256] mov eax,[esi] stdcall DWordToStr mov eax,[esi+4] stdcall DWordToStr mov eax,[esi+8] stdcall DWordToStr mov eax,[esi+12] stdcall DWordToStr mov eax,[esi+16] stdcall DWordToStr mov eax,[esi+20] stdcall DWordToStr mov eax,[esi+24] stdcall DWordToStr mov eax,[esi+28] stdcall DWordToStr PRINT_CRLF ; print the SHA-384 result mov [edi],dword "SHA-" add edi,4 mov [edi],dword "384:" add edi,4 PRINT_CRLF lea esi,[H_0_384] mov eax,[esi] stdcall DWordToStr mov eax,[esi+4] stdcall DWordToStr mov eax,[esi+8] stdcall DWordToStr mov eax,[esi+12] stdcall DWordToStr mov eax,[esi+16] stdcall DWordToStr mov eax,[esi+20] stdcall DWordToStr mov eax,[esi+24] stdcall DWordToStr mov eax,[esi+28] stdcall DWordToStr mov [edi],byte 13 inc edi mov [edi],byte 10 inc edi mov eax,[esi+32] stdcall DWordToStr mov eax,[esi+36] stdcall DWordToStr mov eax,[esi+40] stdcall DWordToStr mov eax,[esi+44] stdcall DWordToStr PRINT_CRLF ; print the SHA-512 result mov [edi],dword "SHA-" add edi,4 mov [edi],dword "512:" add edi,4 PRINT_CRLF lea esi,[H_0_512] mov eax,[esi] stdcall DWordToStr mov eax,[esi+4] stdcall DWordToStr mov eax,[esi+8] stdcall DWordToStr mov eax,[esi+12] stdcall DWordToStr mov eax,[esi+16] stdcall DWordToStr mov eax,[esi+20] stdcall DWordToStr mov eax,[esi+24] stdcall DWordToStr mov eax,[esi+28] stdcall DWordToStr mov [edi],byte 13 inc edi mov [edi],byte 10 inc edi mov eax,[esi+32] stdcall DWordToStr mov eax,[esi+36] stdcall DWordToStr mov eax,[esi+40] stdcall DWordToStr mov eax,[esi+44] stdcall DWordToStr mov eax,[esi+48] stdcall DWordToStr mov eax,[esi+52] stdcall DWordToStr mov eax,[esi+56] stdcall DWordToStr mov eax,[esi+60] stdcall DWordToStr ; zero terminate the string mov [edi],byte 0 ret endp ; ------------------------------------------------------------------------------------- proc WordToStr uses edx ; print a word (2 bytes) to a string ; word passed in AX ; EDI set outside of this function mov dx,ax mov al,ah stdcall ByteToDigits mov [edi],ah inc edi mov [edi],al inc edi mov al,dl stdcall ByteToDigits mov [edi],ah inc edi mov [edi],al inc edi ret endp ; ------------------------------------------------------------------------------------- proc DWordToStr ; print a dword (4 bytes) to a string ; word passed in EAX ; EDI set outside of this function locals tmp dw 0 endl mov word [tmp],ax shr eax,16 stdcall WordToStr mov ax,word [tmp] stdcall WordToStr ; add a space mov [edi],byte 32 inc edi ret endp ; ------------------------------------------------------------------------------------- proc StrToBuffer ; load the buffer in memory from the string bfDisplay ; address of input buffer is passed in EAX ; max number of hex digits to read passed in EDX locals count dw 0 endl lea esi,[bfDisplay] mov edi,eax mov ecx,0 .GET_CHARS: mov al,byte [esi] cmp al,0 je .DONE stdcall HexDigitToValue ; just skip and get the next char if not a hex digit cmp eax,0xffff je .NEXT ; AL contains a nibble, determine where to place it in the dest byte ; if count is even, the nibble is mapped to the lower 4 bits in dest ; if count is odd, the nibble is mapped to the upper 4 bits in dest inc word [count] ; even if count AND 1 == 0 test [count],1 jz .EVEN .ODD: inc cx shl al,4 mov [edi],al jmp .NEXT .EVEN: inc cx or [edi],al inc edi .NEXT: inc esi cmp cx,dx jge .DONE jmp .GET_CHARS .DONE: ; CX contains the number of hex digits that were read, return in EDX mov edx,ecx ret endp ; ------------------------------------------------------------------------------------- proc StrToMessageBuffer ; load the message buffer from the input string ; input string is a hex value ; reset the input buffer stdcall ResetMessageBuffer stdcall StrToHexStr lea eax,[MESSAGE] mov edx,2*MESSAGE_LENGTH stdcall StrToBuffer ; EDX contains number of hex digits in message ; set bit length shl edx,2 mov [BitLength],edx ret endp ; ------------------------------------------------------------------------------------- proc Init_H_0_SHA_1 uses edi lea edi,[H_0_1] mov [edi],dword 0x67452301 mov [edi+4],dword 0xefcdab89 mov [edi+8],dword 0x98badcfe mov [edi+12],dword 0x10325476 mov [edi+16],dword 0xc3d2e1f0 ret endp ; ------------------------------------------------------------------------------------- proc Init_H_0_SHA_224 uses edi lea edi,[H_0_256] mov [edi],dword 0xc1059ed8 mov [edi+4],dword 0x367cd507 mov [edi+8],dword 0x3070dd17 mov [edi+12],dword 0xf70e5939 mov [edi+16],dword 0xffc00b31 mov [edi+20],dword 0x68581511 mov [edi+24],dword 0x64f98fa7 mov [edi+28],dword 0xbefa4fa4 ret endp ; ------------------------------------------------------------------------------------- proc Init_H_0_SHA_256 uses edi lea edi,[H_0_256] mov [edi],dword 0x6a09e667 mov [edi+4],dword 0xbb67ae85 mov [edi+8],dword 0x3c6ef372 mov [edi+12],dword 0xa54ff53a mov [edi+16],dword 0x510e527f mov [edi+20],dword 0x9b05688c mov [edi+24],dword 0x1f83d9ab mov [edi+28],dword 0x5be0cd19 ret endp ; ------------------------------------------------------------------------------------- proc Init_H_0_SHA_384 uses edi lea edi,[H_0_512] mov [edi],dword 0xcbbb9d5d mov [edi+4],dword 0xc1059ed8 mov [edi+8],dword 0x629a292a mov [edi+12],dword 0x367cd507 mov [edi+16],dword 0x9159015a mov [edi+20],dword 0x3070dd17 mov [edi+24],dword 0x152fecd8 mov [edi+28],dword 0xf70e5939 mov [edi+32],dword 0x67332667 mov [edi+36],dword 0xffc00b31 mov [edi+40],dword 0x8eb44a87 mov [edi+44],dword 0x68581511 mov [edi+48],dword 0xdb0c2e0d mov [edi+52],dword 0x64f98fa7 mov [edi+56],dword 0x47b5481d mov [edi+60],dword 0xbefa4fa4 ret endp ; ------------------------------------------------------------------------------------- proc Init_H_0_SHA_512 uses edi lea edi,[H_0_512] mov [edi],dword 0x6a09e667 mov [edi+4],dword 0xf3bcc908 mov [edi+8],dword 0xbb67ae85 mov [edi+12],dword 0x84caa73b mov [edi+16],dword 0x3c6ef372 mov [edi+20],dword 0xfe94f82b mov [edi+24],dword 0xa54ff53a mov [edi+28],dword 0x5f1d36f1 mov [edi+32],dword 0x510e527f mov [edi+36],dword 0xade682d1 mov [edi+40],dword 0x9b05688c mov [edi+44],dword 0x2b3e6c1f mov [edi+48],dword 0x1f83d9ab mov [edi+52],dword 0xfb41bd6b mov [edi+56],dword 0x5be0cd19 mov [edi+60],dword 0x137e2179 ret endp ; ------------------------------------------------------------------------------------- proc SetPaddingBits uses edi ecx ; clear all of the bytes from the end of the message to the ; end of the message buffer and then append the 1 bit lea edi,[MESSAGE] ; start from the last byte in the message buffer add edi,MESSAGE_LENGTH+127 ; put the message length in bytes into EDX mov edx,[BitLength] shr edx,3 mov ecx,MESSAGE_LENGTH+128 .CLEAR: mov [edi],byte 0 dec edi dec ecx cmp ecx,edx jg .CLEAR ; now append the 1 bit to the end of the message ; first test (BitLength mod 8) mov edx,[BitLength] test edx,7 jz .APPEND ; BitLength is a multiple of 4 ; set the high bit of the nibble following the last message nibble and [edi],byte 0xf0 or [edi],byte 0x8 jmp .DONE .APPEND: ; BitLength is a multiple of 8 ; set the high bit of the byte following the last message byte inc edi mov [edi],byte 0x80 .DONE: ret endp ; ------------------------------------------------------------------------------------- proc Preprocess_512 uses edi stdcall SetPaddingBits ; compute the number of 512 bit blocks in the message mov edx,[BitLength] shr edx,9 inc edx mov [nBlocks512],edx ; get length of last block ; if greater than or equal to 448 bits, an extra padding block is needed mov edx,[BitLength] and edx,0x1ff cmp edx,448 jl .SET_LAST inc dword [nBlocks512] .SET_LAST: ; set the last 64 bits in the padded message to the bit length of the message lea edi,[MESSAGE] mov edx,[nBlocks512] shl edx,6 add edi,edx ; BitLength is a dword (32 bits) ; copy to the last 32 bits of the padded message sub edi,4 mov eax,[BitLength] bswap eax mov [edi],eax ret endp ; ------------------------------------------------------------------------------------- proc Preprocess_1024 uses edi stdcall SetPaddingBits ; compute the number of 1024 bit blocks in the message mov edx,[BitLength] shr edx,10 inc edx mov [nBlocks1024],edx ; get length of last block ; if greater than or equal to 896 bits, an extra padding block is needed mov edx,[BitLength] and edx,0x3ff cmp edx,896 jl .SET_LAST inc dword [nBlocks1024] .SET_LAST: ; set the last 128 bits in the padded message to the bit length of the message lea edi,[MESSAGE] mov edx,[nBlocks1024] shl edx,7 add edi,edx ; BitLength is a dword (32 bits) ; copy to the last 32 bits of the padded message sub edi,4 mov eax,[BitLength] bswap eax mov [edi],eax ret endp ; ------------------------------------------------------------------------------------- proc Compute_Hash uses esi edi stdcall Preprocess_512 stdcall Compute_SHA_1 stdcall Compute_SHA_224 lea esi,[H_0_256] lea edi,[H_0_224] mov eax,[esi] mov [edi],eax mov eax,[esi+4] mov [edi+4],eax mov eax,[esi+8] mov [edi+8],eax mov eax,[esi+12] mov [edi+12],eax mov eax,[esi+16] mov [edi+16],eax mov eax,[esi+20] mov [edi+20],eax mov eax,[esi+24] mov [edi+24],eax stdcall Compute_SHA_256 stdcall Preprocess_1024 stdcall Compute_SHA_384 lea esi,[H_0_512] lea edi,[H_0_384] mov eax,[esi] mov [edi],eax mov eax,[esi+4] mov [edi+4],eax mov eax,[esi+8] mov [edi+8],eax mov eax,[esi+12] mov [edi+12],eax mov eax,[esi+16] mov [edi+16],eax mov eax,[esi+20] mov [edi+20],eax mov eax,[esi+24] mov [edi+24],eax mov eax,[esi+28] mov [edi+28],eax mov eax,[esi+32] mov [edi+32],eax mov eax,[esi+36] mov [edi+36],eax mov eax,[esi+40] mov [edi+40],eax mov eax,[esi+44] mov [edi+44],eax stdcall Compute_SHA_512 ret endp ; ------------------------------------------------------------------------------------- proc Compute_SHA_1 stdcall Init_H_0_SHA_1 mov ecx,[nBlocks512] lea esi,[MESSAGE] .HASH_BLOCK: lea edi,[Message_Schedule] mov edx,64 .INIT_SCHED: ; copy the 512 bit block to the first 512 bits of the message schedule mov eax,[esi] ; big endian to little endian bswap eax mov [edi],eax add esi,4 add edi,4 sub dx,4 cmp dx,0 jg .INIT_SCHED ; iterate the hash value stdcall SHA_1_Iterate dec cx jcxz .DONE jmp .HASH_BLOCK .DONE: ret endp ; ------------------------------------------------------------------------------------- proc Compute_SHA_224 stdcall Init_H_0_SHA_224 mov ecx,[nBlocks512] lea esi,[MESSAGE] .HASH_BLOCK: lea edi,[Message_Schedule] mov dx,64 .INIT_SCHED: ; copy the 512 bit block to the first 512 bits of the message schedule mov eax,[esi] ; big endian to little endian bswap eax mov [edi],eax add esi,4 add edi,4 sub dx,4 cmp dx,0 jg .INIT_SCHED ; iterate the hash value stdcall SHA_224_256_Iterate dec cx jcxz .DONE jmp .HASH_BLOCK .DONE: ret endp ; ------------------------------------------------------------------------------------- proc Compute_SHA_256 stdcall Init_H_0_SHA_256 mov ecx,[nBlocks512] lea esi,[MESSAGE] .HASH_BLOCK: lea edi,[Message_Schedule] mov dx,64 .INIT_SCHED: ; copy the 512 bit block to the first 512 bits of the message schedule mov eax,[esi] ; big endian to little endian bswap eax mov [edi],eax add esi,4 add edi,4 sub dx,4 cmp dx,0 jg .INIT_SCHED ; iterate the hash value stdcall SHA_224_256_Iterate dec cx jcxz .DONE jmp .HASH_BLOCK .DONE: ret endp ; ------------------------------------------------------------------------------------- proc Compute_SHA_384 stdcall Init_H_0_SHA_384 mov ecx,[nBlocks1024] lea esi,[MESSAGE] .HASH_BLOCK: lea edi,[Message_Schedule] mov dx,128 .INIT_SCHED: ; copy the 1024 bit block to the first 1024 bits of the message schedule mov eax,[esi] ; big endian to little endian bswap eax mov [edi],eax add esi,4 add edi,4 sub dx,4 cmp dx,0 jg .INIT_SCHED ; iterate the hash value stdcall SHA_384_512_Iterate dec cx jcxz .DONE jmp .HASH_BLOCK .DONE: ret endp ; ------------------------------------------------------------------------------------- proc Compute_SHA_512 stdcall Init_H_0_SHA_512 mov ecx,[nBlocks1024] lea esi,[MESSAGE] .HASH_BLOCK: lea edi,[Message_Schedule] mov dx,128 .INIT_SCHED: ; copy the 1024 bit block to the first 1024 bits of the message schedule mov eax,[esi] ; big endian to little endian bswap eax mov [edi],eax add esi,4 add edi,4 sub dx,4 cmp dx,0 jg .INIT_SCHED ; iterate the hash value stdcall SHA_384_512_Iterate dec cx jcxz .DONE jmp .HASH_BLOCK .DONE: ret endp ; ------------------------------------------------------------------------------------- proc SHA_1_Iterate uses esi edi ebx ecx ; prepare the message schedule ; the first 16 words of the message schedule ; already contain the 512 bit message block lea esi,[Message_Schedule] lea edi,[Message_Schedule] add esi,64 add edi,64 mov cx,16 .PREPARE: ; W[t] = ROTL(W[t-3] xor W[t-8] xor W[t-14] xor W[t-16]) mov eax,[esi-12] xor eax,[esi-32] xor eax,[esi-56] xor eax,[esi-64] rol eax,1 mov [edi],eax add esi,4 add edi,4 inc cx cmp cx,80 jl .PREPARE ; initialise a,b,c,d,e lea esi,[H_0_1] lea edi,[Temp_H] mov eax,[esi] mov [edi],eax mov eax,[esi+4] mov [edi+4],eax mov eax,[esi+8] mov [edi+8],eax mov eax,[esi+12] mov [edi+12],eax mov eax,[esi+16] mov [edi+16],eax ; compute the hash xor ecx,ecx mov cx,0 lea esi,[Temp_H] lea edi,[Message_Schedule] .HASH: ; T = ROTL(a,5) mov eax,[esi] rol eax,5 ; T += e add eax,[esi+16] mov edx,ecx shl edx,2 ; T += W[t] add eax,[edi+edx] .0_19: cmp cx,19 jg .20_39 ; add Kt add eax,0x5a827999 ; f(t) = Ch(b,c,d) = (b and c) xor (not(b) and d) ; calc f(t)(b,c,d) mov ebx,[esi+4] and ebx,[esi+8] mov edx,[esi+4] not edx and edx,[esi+12] xor edx,ebx ; add f(t) to T add eax,edx jmp .NEXT .20_39: cmp cx,39 jg .40_59 ; add Kt add eax,0x6ed9eba1 ; f(t) = Parity(b,c,d) = b xor c xor d ; calc f(t)(b,c,d) mov edx,[esi+4] xor edx,[esi+8] xor edx,[esi+12] ; add f(t) to T add eax,edx jmp .NEXT .40_59: cmp cx,59 jg .60_79 ; add Kt add eax,0x8f1bbcdc ; f(t) = Maj(b,c,d) = (b and c) xor (b and d) xor (c and d) ; calc f(t)(b,c,d) mov ebx,[esi+4] and ebx,[esi+8] mov edx,[esi+4] and edx,[esi+12] xor edx,ebx mov ebx,[esi+8] and ebx,[esi+12] xor edx,ebx ; add f(t) to T add eax,edx jmp .NEXT .60_79: ; add Kt add eax,0xca62c1d6 ; f(t) = Parity(b,c,d) = b xor c xor d ; calc f(t)(b,c,d) mov edx,[esi+4] xor edx,[esi+8] xor edx,[esi+12] ; add f(t) to T add eax,edx .NEXT: ; e = d mov edx,[esi+12] mov [esi+16],edx ; d = c mov edx,[esi+8] mov [esi+12],edx ; c = ROTL(30,b) mov edx,[esi+4] rol edx,30 mov [esi+8],edx ; b = a mov edx,[esi] mov [esi+4],edx ; a = T mov [esi],eax inc cx cmp cx,80 jl .HASH .UPDATE: ; add a,b,c,d,e to the hash lea esi,[Temp_H] lea edi,[H_0_1] mov eax,[edi] add eax,[esi] mov [edi],eax mov eax,[edi+4] add eax,[esi+4] mov [edi+4],eax mov eax,[edi+8] add eax,[esi+8] mov [edi+8],eax mov eax,[edi+12] add eax,[esi+12] mov [edi+12],eax mov eax,[edi+16] add eax,[esi+16] mov [edi+16],eax ret endp ; ------------------------------------------------------------------------------------- proc SHA_224_256_Iterate uses esi edi ebx ecx locals T1 dd 0 T2 dd 0 endl ; prepare the message schedule ; the first 16 words of the message schedule ; already contain the 512 bit message block lea esi,[Message_Schedule] lea edi,[Message_Schedule] add esi,64 add edi,64 mov cx,16 .PREPARE: ; W[t] = W[t-7] + W[t-16] + sigma_256_1(W[t-2]) + sigma_256_0(W[t-15]) ; W[t-7] mov eax,[esi-28] ; W[t-16] add eax,[esi-64] mov [edi],eax ; SHR(W(t-2),10) mov edx,[esi-8] shr edx,10 mov eax,edx ; ROTR(W(t-2),17) mov edx,[esi-8] ror edx,17 xor eax,edx ; ROTR(W(t-2),17) mov edx,[esi-8] ror edx,19 xor eax,edx add [edi],eax ; SHR(W(t-15),3) mov edx,[esi-60] shr edx,3 mov eax,edx ; ROTR(W(t-15),7) mov edx,[esi-60] ror edx,7 xor eax,edx ; ROTR(W(t-15),18) mov edx,[esi-60] ror edx,18 xor eax,edx add [edi],eax add esi,4 add edi,4 inc cx cmp cx,64 jl .PREPARE ; initialise a,b,c,d,e,f,g,h lea esi,[H_0_256] lea edi,[Temp_H] mov eax,[esi] mov [edi],eax mov eax,[esi+4] mov [edi+4],eax mov eax,[esi+8] mov [edi+8],eax mov eax,[esi+12] mov [edi+12],eax mov eax,[esi+16] mov [edi+16],eax mov eax,[esi+20] mov [edi+20],eax mov eax,[esi+24] mov [edi+24],eax mov eax,[esi+28] mov [edi+28],eax ; compute the hash xor ecx,ecx mov cx,0 lea esi,[Temp_H] lea edi,[Message_Schedule] lea ebx,[SHA_224_256_Kt] .HASH: ; T1 = h mov eax,[esi+28] ; T1 += W[t] mov edx,ecx shl edx,2 add eax,[edi+edx] ; T1 += Kt add eax,[ebx+edx] mov [T1],eax ; T1 += Ch(e,f,g) = (e and f) xor (not(e) and g) mov eax,[esi+16] and eax,[esi+20] mov edx,[esi+16] not edx and edx,[esi+24] xor eax,edx add [T1],eax ; T1 += SIGMA_256_1(e) = ROTR(e,6) xor ROTR(e,11) xor ROTR(e,25) mov eax,[esi+16] ror eax,6 mov edx,[esi+16] ror edx,11 xor eax,edx mov edx,[esi+16] ror edx,25 xor eax,edx add [T1],eax ; T2 = SIGMA_256_0(a) = ROTR(a,2) xor ROTR(a,13) xor ROTR(a,22) mov eax,[esi] ror eax,2 mov edx,[esi] ror edx,13 xor eax,edx mov edx,[esi] ror edx,22 xor eax,edx mov [T2],eax ; T2 += Maj(a,b,c) = (a and b) xor (a and c) xor (b and c) mov eax,[esi] and eax,[esi+4] mov edx,[esi] and edx,[esi+8] xor eax,edx mov edx,[esi+4] and edx,[esi+8] xor eax,edx add [T2],eax ; h = g mov edx,[esi+24] mov [esi+28],edx ; g = f mov edx,[esi+20] mov [esi+24],edx ; f = e mov edx,[esi+16] mov [esi+20],edx ; e = d + T1 mov edx,[T1] add edx,[esi+12] mov [esi+16],edx ; d = c mov edx,[esi+8] mov [esi+12],edx ; c = b mov edx,[esi+4] mov [esi+8],edx ; b = a mov edx,[esi] mov [esi+4],edx ; a = T1 + T2 mov edx,[T1] add edx,[T2] mov [esi],edx inc cx cmp cx,64 jl .HASH .UPDATE: ; add a,b,c,d,e,f,g,h to the hash lea esi,[Temp_H] lea edi,[H_0_256] mov eax,[edi] add eax,[esi] mov [edi],eax mov eax,[edi+4] add eax,[esi+4] mov [edi+4],eax mov eax,[edi+8] add eax,[esi+8] mov [edi+8],eax mov eax,[edi+12] add eax,[esi+12] mov [edi+12],eax mov eax,[edi+16] add eax,[esi+16] mov [edi+16],eax mov eax,[edi+20] add eax,[esi+20] mov [edi+20],eax mov eax,[edi+24] add eax,[esi+24] mov [edi+24],eax mov eax,[edi+28] add eax,[esi+28] mov [edi+28],eax ret endp ; ------------------------------------------------------------------------------------- proc SHA_384_512_Iterate uses esi edi ebx ecx locals T1_U dd 0 T1_L dd 0 T2_U dd 0 T2_L dd 0 endl ; prepare the message schedule ; the first 32 words of the message schedule ; already contain the 1024 bit message block lea esi,[Message_Schedule] lea edi,[Message_Schedule] add esi,128 add edi,128 xor ecx,ecx mov cx,16 .PREPARE: ; W[t] = W[t-7] + W[t-16] + sigma_512_1(W[t-2]) + sigma_512_0(W[t-15]) ; 64 bit words: ; lower 32 bits in EAX ; upper 32 bits in EDX ; W[t-7] mov eax,[esi-52] mov edx,[esi-56] ; W[t-16] add eax,[esi-124] adc edx,[esi-128] mov [edi+4],eax mov [edi],edx ; sigma_512_1(x) = ROTR(x,19) xor ROTR(x,61) xor SHR(x,6) stdcall sigma_512_1_Wt ; add to W[t] add [edi+4],eax adc [edi],edx ; sigma_512_0(x) = ROTR(x,1) xor ROTR(x,8) xor SHR(x,7) stdcall sigma_512_0_Wt ; add to W[t] add [edi+4],eax adc [edi],edx add esi,8 add edi,8 inc cx cmp cx,80 jl .PREPARE ; initialise a,b,c,d,e,f,g,h stdcall Init_512 ; compute the hash xor ecx,ecx mov cx,0 lea esi,[Temp_H] lea edi,[Message_Schedule] .HASH: ; 64 bit words: ; lower 32 bits in EAX ; upper 32 bits in EDX ; a = esi + 0 ; b = esi + 8 ; c = esi + 16 ; d = esi + 24 ; e = esi + 32 ; f = esi + 40 ; g = esi + 48 ; h = esi + 56 ; T1 = h + SIGMA_512_1(e) + Ch(e,f,g) + K[t] + W[t] ; T1 = h mov eax,[esi+60] mov edx,[esi+56] mov [T1_L],eax mov [T1_U],edx ; T1 += W[t] mov ebx,ecx shl ebx,3 mov eax,[edi+ebx+4] mov edx,[edi+ebx] add [T1_L],eax adc [T1_U],edx ; T1 += Ch(e,f,g) ; Ch(e,f,g) = (e and f) xor (not(e) and g) stdcall Ch_512 add [T1_L],eax adc [T1_U],edx ; T1 += K[t] stdcall Kt_512 add [T1_L],eax adc [T1_U],edx ; T1 += SIGMA_512_1(e) ; SIGMA_512_1(e) = ROTR(e,14) xor ROTR(e,18) xor ROTR(e,41) stdcall SIGMA_512_E add [T1_L],eax adc [T1_U],edx ; T2 = SIGMA_512_0(a) + Maj(a,b,c) ; T2 = Maj(a,b,c) ; Maj(a,b,c) = (a and b) xor (a and c) xor (b and c) stdcall Maj_512 mov [T2_L],eax mov [T2_U],edx ; T2 += SIGMA_512_0(a) ; SIGMA_512_0(a) = ROTR(a,28) xor ROTR(a,34) xor ROTR(a,39) stdcall SIGMA_512_A add [T2_L],eax adc [T2_U],edx ; h = g mov eax,[esi+52] mov edx,[esi+48] mov [esi+60],eax mov [esi+56],edx ; g = f mov eax,[esi+44] mov edx,[esi+40] mov [esi+52],eax mov [esi+48],edx ; f = e mov eax,[esi+36] mov edx,[esi+32] mov [esi+44],eax mov [esi+40],edx ; e = d + T1 mov eax,[esi+28] mov edx,[esi+24] add eax,[T1_L] adc edx,[T1_U] mov [esi+36],eax mov [esi+32],edx ; d = c mov eax,[esi+20] mov edx,[esi+16] mov [esi+28],eax mov [esi+24],edx ; c = b mov eax,[esi+12] mov edx,[esi+8] mov [esi+20],eax mov [esi+16],edx ; b = a mov eax,[esi+4] mov edx,[esi] mov [esi+12],eax mov [esi+8],edx ; a = T1 + T2 mov eax,[T1_L] mov edx,[T1_U] add eax,[T2_L] adc edx,[T2_U] mov [esi+4],eax mov [esi],edx inc cx cmp cx,80 jl .HASH .UPDATE: ; add a,b,c,d,e,f,g,h to the hash stdcall Update_512 ret endp ; ------------------------------------------------------------------------------------- macro ROT_RIGHT nbits { ; Rotate right the double word EDX,EAX mov ebx,eax shrd eax,edx,nbits shr edx,nbits shl ebx,32-nbits or edx,ebx } ; ------------------------------------------------------------------------------------- macro ROT_RIGHT_32 { ; Rotate right the double word EDX,EAX by 32 bits ; equivalent to swapping EAX and EDX mov ebx,eax mov eax,edx mov edx,ebx } ; ------------------------------------------------------------------------------------- proc sigma_512_0_Wt uses esi ; sigma_512_0(x) = ROTR(x,1) xor ROTR(x,8) xor SHR(x,7) ; x = W[t-15] ; t in ECX ; result returned in EAX and EDX locals Temp_L dd 0 Temp_U dd 0 endl lea esi,[Message_Schedule] ; get ESI for the current t mov ebx,ecx shl ebx,3 add esi,ebx mov eax,[esi-116] mov edx,[esi-120] ; SHR(x,7) shrd eax,edx,7 shr edx,7 mov [Temp_L],eax mov [Temp_U],edx ; ROTR(x,1) mov eax,[esi-116] mov edx,[esi-120] ROT_RIGHT 1 ; xor xor [Temp_L],eax xor [Temp_U],edx ; ROTR(x,8) mov eax,[esi-116] mov edx,[esi-120] ROT_RIGHT 8 ; xor xor eax,[Temp_L] xor edx,[Temp_U] ret endp ; ------------------------------------------------------------------------------------- proc sigma_512_1_Wt uses esi ; sigma_512_1(x) = ROTR(x,19) xor ROTR(x,61) xor SHR(x,6) ; x = W[t-2] ; t in ECX ; result returned in EAX and EDX locals Temp_L dd 0 Temp_U dd 0 endl lea esi,[Message_Schedule] ; get ESI for the current t mov ebx,ecx shl ebx,3 add esi,ebx mov eax,[esi-12] mov edx,[esi-16] ; SHR(x,6) shrd eax,edx,6 shr edx,6 mov [Temp_L],eax mov [Temp_U],edx ; ROTR(x,19) mov eax,[esi-12] mov edx,[esi-16] ROT_RIGHT 19 ; xor xor [Temp_L],eax xor [Temp_U],edx ; ROTR(x,61) = ROTR(ROTR(x,32),29) mov eax,[esi-12] mov edx,[esi-16] ROT_RIGHT_32 ROT_RIGHT 29 ; xor xor eax,[Temp_L] xor edx,[Temp_U] ret endp ; ------------------------------------------------------------------------------------- proc SIGMA_512_A uses esi ; SIGMA_512_0(a) = ROTR(a,28) xor ROTR(a,34) xor ROTR(a,39) ; result returned in EAX and EDX locals Temp_L dd 0 Temp_U dd 0 endl lea esi,[Temp_H] ; a = esi + 0 mov eax,[esi+4] mov edx,[esi] ; ROTR(a,28) ROT_RIGHT 28 mov [Temp_L],eax mov [Temp_U],edx mov eax,[esi+4] mov edx,[esi] ; ROTR(a,34) = ROTR(ROTR(a,32),2) ROT_RIGHT_32 ROT_RIGHT 2 ; xor xor [Temp_L],eax xor [Temp_U],edx mov eax,[esi+4] mov edx,[esi] ; ROTR(a,39) = ROTR(ROTR(a,32),7) ROT_RIGHT_32 ROT_RIGHT 7 ; xor xor eax,[Temp_L] xor edx,[Temp_U] ret endp ; ------------------------------------------------------------------------------------- proc SIGMA_512_E uses esi ; SIGMA_512_1(e) = ROTR(e,14) xor ROTR(e,18) xor ROTR(e,41) ; result returned in EAX and EDX locals Temp_L dd 0 Temp_U dd 0 endl lea esi,[Temp_H] ; e = esi + 32 mov eax,[esi+36] mov edx,[esi+32] ; ROTR(e,14) ROT_RIGHT 14 mov [Temp_L],eax mov [Temp_U],edx mov eax,[esi+36] mov edx,[esi+32] ; ROTR(e,18) ROT_RIGHT 18 ; xor xor [Temp_L],eax xor [Temp_U],edx mov eax,[esi+36] mov edx,[esi+32] ; ROTR(e,41) = ROTR(ROTR(e,32),9) ROT_RIGHT_32 ROT_RIGHT 9 ; xor xor eax,[Temp_L] xor edx,[Temp_U] ret endp ; ------------------------------------------------------------------------------------- proc Ch_512 uses esi ; Ch(e,f,g) = (e and f) xor (not(e) and g) ; return the result in EAX and EDX locals Temp_L dd 0 Temp_U dd 0 endl ; e = esi + 32 ; f = esi + 40 ; g = esi + 48 ; e and f lea esi,[Temp_H] mov eax,[esi+36] mov edx,[esi+32] and eax,[esi+44] and edx,[esi+40] mov [Temp_L],eax mov [Temp_U],edx ; not(e) mov eax,[esi+36] mov edx,[esi+32] not eax not edx ; not(e) and g and eax,[esi+52] and edx,[esi+48] ; xor xor eax,[Temp_L] xor edx,[Temp_U] ret endp ; ------------------------------------------------------------------------------------- proc Maj_512 uses esi ; Maj(a,b,c) = (a and b) xor (a and c) xor (b and c) ; return the result in EAX and EDX locals Temp_L dd 0 Temp_U dd 0 endl ; a = esi + 0 ; b = esi + 8 ; c = esi + 16 ; a and b lea esi,[Temp_H] mov eax,[esi+4] mov edx,[esi] and eax,[esi+12] and edx,[esi+8] mov [Temp_L],eax mov [Temp_U],edx ; a and c mov eax,[esi+4] mov edx,[esi] and eax,[esi+20] and edx,[esi+16] ; xor xor [Temp_L],eax xor [Temp_U],edx ; b and c mov eax,[esi+12] mov edx,[esi+8] and eax,[esi+20] and edx,[esi+16] ; xor xor eax,[Temp_L] xor edx,[Temp_U] ret endp ; ------------------------------------------------------------------------------------- proc Kt_512 uses esi ; t is in ECX ; return K[t] in EAX and EDX lea esi,[SHA_384_512_Kt] mov edx,ecx shl edx,3 mov eax,[esi+edx+4] mov edx,[esi+edx] ret endp ; ------------------------------------------------------------------------------------- proc Init_512 ; initialise a,b,c,d,e,f,g,h for SHA-384 and SHA-512 lea esi,[H_0_512] lea edi,[Temp_H] mov cx,16 .COPY: mov eax,[esi] mov [edi],eax add esi,4 add edi,4 dec cx jcxz .DONE jmp .COPY .DONE: ret endp ; ------------------------------------------------------------------------------------- proc Update_512 ; add a,b,c,d,e,f,g,h to the hash for SHA-384 and SHA-512 lea esi,[Temp_H] lea edi,[H_0_512] mov cx,8 .ADD: mov eax,[esi+4] mov edx,[esi] add [edi+4],eax adc [edi],edx add esi,8 add edi,8 dec cx jcxz .DONE jmp .ADD .DONE: ret endp ; ------------------------------------------------------------------------------------- section '.idata' import data readable writeable library kernel,'KERNEL32.DLL',\ user,'USER32.DLL' import kernel,\ GetModuleHandle,'GetModuleHandleA',\ ExitProcess,'ExitProcess' import user,\ DialogBoxParam,'DialogBoxParamA',\ SetDlgItemText,'SetDlgItemTextA',\ GetDlgItemText,'GetDlgItemTextA',\ EndDialog,'EndDialog' ; ------------------------------------------------------------------------------------- section '.data' readable writeable bfDisplay rb IN_STR_MAX_LENGTH MESSAGE rb MESSAGE_LENGTH+128 BitLength dd 0 nBlocks512 dd 0 nBlocks1024 dd 0 szInitText db "Enter the message as a hex number or text string (up to 5120 bytes):",0 ; ------------------------------------------------------------------------------------- section '.hash' readable writeable H_0_1 rd 5 H_0_224 rd 8 H_0_256 rd 8 H_0_384 rd 16 H_0_512 rd 16 Message_Schedule rd 160 Temp_H rd 16 SHA_224_256_Kt dd 0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5,\ 0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5,\ 0xd807aa98,0x12835b01,0x243185be,0x550c7dc3,\ 0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174,\ 0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc,\ 0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da,\ 0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7,\ 0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967,\ 0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13,\ 0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85,\ 0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3,\ 0xd192e819,0xd6990624,0xf40e3585,0x106aa070,\ 0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5,\ 0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3,\ 0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208,\ 0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2 SHA_384_512_Kt dd 0x428a2f98,0xd728ae22,0x71374491,0x23ef65cd,\ 0xb5c0fbcf,0xec4d3b2f,0xe9b5dba5,0x8189dbbc,\ 0x3956c25b,0xf348b538,0x59f111f1,0xb605d019,\ 0x923f82a4,0xaf194f9b,0xab1c5ed5,0xda6d8118,\ 0xd807aa98,0xa3030242,0x12835b01,0x45706fbe,\ 0x243185be,0x4ee4b28c,0x550c7dc3,0xd5ffb4e2,\ 0x72be5d74,0xf27b896f,0x80deb1fe,0x3b1696b1,\ 0x9bdc06a7,0x25c71235,0xc19bf174,0xcf692694,\ 0xe49b69c1,0x9ef14ad2,0xefbe4786,0x384f25e3,\ 0x0fc19dc6,0x8b8cd5b5,0x240ca1cc,0x77ac9c65,\ 0x2de92c6f,0x592b0275,0x4a7484aa,0x6ea6e483,\ 0x5cb0a9dc,0xbd41fbd4,0x76f988da,0x831153b5,\ 0x983e5152,0xee66dfab,0xa831c66d,0x2db43210,\ 0xb00327c8,0x98fb213f,0xbf597fc7,0xbeef0ee4,\ 0xc6e00bf3,0x3da88fc2,0xd5a79147,0x930aa725,\ 0x06ca6351,0xe003826f,0x14292967,0x0a0e6e70,\ 0x27b70a85,0x46d22ffc,0x2e1b2138,0x5c26c926,\ 0x4d2c6dfc,0x5ac42aed,0x53380d13,0x9d95b3df,\ 0x650a7354,0x8baf63de,0x766a0abb,0x3c77b2a8,\ 0x81c2c92e,0x47edaee6,0x92722c85,0x1482353b,\ 0xa2bfe8a1,0x4cf10364,0xa81a664b,0xbc423001,\ 0xc24b8b70,0xd0f89791,0xc76c51a3,0x0654be30,\ 0xd192e819,0xd6ef5218,0xd6990624,0x5565a910,\ 0xf40e3585,0x5771202a,0x106aa070,0x32bbd1b8,\ 0x19a4c116,0xb8d2d0c8,0x1e376c08,0x5141ab53,\ 0x2748774c,0xdf8eeb99,0x34b0bcb5,0xe19b48a8,\ 0x391c0cb3,0xc5c95a63,0x4ed8aa4a,0xe3418acb,\ 0x5b9cca4f,0x7763e373,0x682e6ff3,0xd6b2b8a3,\ 0x748f82ee,0x5defb2fc,0x78a5636f,0x43172f60,\ 0x84c87814,0xa1f0ab72,0x8cc70208,0x1a6439ec,\ 0x90befffa,0x23631e28,0xa4506ceb,0xde82bde9,\ 0xbef9a3f7,0xb2c67915,0xc67178f2,0xe372532b,\ 0xca273ece,0xea26619c,0xd186b8c7,0x21c0c207,\ 0xeada7dd6,0xcde0eb1e,0xf57d4f7f,0xee6ed178,\ 0x06f067aa,0x72176fba,0x0a637dc5,0xa2c898a6,\ 0x113f9804,0xbef90dae,0x1b710b35,0x131c471b,\ 0x28db77f5,0x23047d84,0x32caab7b,0x40c72493,\ 0x3c9ebe0a,0x15c9bebc,0x431d67c4,0x9c100d4c,\ 0x4cc5d4be,0xcb3e42b6,0x597f299c,0xfc657e2a,\ 0x5fcb6fab,0x3ad6faec,0x6c44198c,0x4a475817 ; ------------------------------------------------------------------------------------- section '.rc' resource data readable directory RT_DIALOG,dialogs resource dialogs,IDD_THE_DIALOG,LANG_ENGLISH+SUBLANG_DEFAULT,the_dialog dialog the_dialog,\ 'FASM - Secure Hash Algorithm',50,50,360,440,\ DS_MODALFRAME+WS_MINIMIZEBOX+WS_POPUP+WS_VISIBLE+WS_CAPTION+WS_SYSMENU,\ 0,0,"Lucida Console",11 dialogitem 'BUTTON',"Input",-1,7,5,346,180,BS_GROUPBOX+WS_VISIBLE,0 dialogitem 'BUTTON',"Output",-1,7,190,346,220,BS_GROUPBOX+WS_VISIBLE,0 dialogitem 'EDIT',0,IDC_INPUT,13,18,335,160,ES_MULTILINE+ES_AUTOVSCROLL+ES_WANTRETURN+WS_VSCROLL+WS_BORDER+WS_VISIBLE,0 dialogitem 'EDIT',0,IDC_OUTPUT,13,203,335,200,ES_MULTILINE+ES_AUTOVSCROLL+ES_WANTRETURN+WS_VSCROLL+WS_BORDER+WS_VISIBLE,0 dialogitem 'BUTTON',"SHA(HEX)",IDC_BTN_SHA_HEX,7,415,60,14,BS_PUSHBUTTON+WS_VISIBLE,0 dialogitem 'BUTTON',"SHA(TXT)",IDC_BTN_SHA_TXT,69,415,60,14,BS_PUSHBUTTON+WS_VISIBLE,0 dialogitem 'BUTTON',"RESET",IDC_BTN_RESET,131,415,60,14,BS_PUSHBUTTON+WS_VISIBLE,0 enddialog ; ------------------------------------------------------------------------------------- ```