# Assembly Language Programming

## May 6, 2012

### FASM – x86 Blowfish Encryption

In this post I implement the Blowfish Encryption Algorithm in x86 assembly language using FASM (the flat assembler).

The Blowfish Algorithm was created by Bruce Schneier. The website for Blowfish can be found at:

## The Key

The size of the key is variable and can be anything from 1 bit up to 448 bits (56 bytes). Before any encryption is done, the key is expanded to 72 bytes in length so that the subkeys and S-Boxes can be computed. The key is expanded by duplicating (copying up) the input key bits. For example if the input key A is 18 bytes in length, then the expanded 72 byte key will be AAAA.

## The SubKeys

The subkeys are the P array (of size 72 bytes or 18 32-bit words) and 4 S-Boxes (1024 bytes each or 256 32-Bit words). These subkeys are pre-computed before any encryption is done. The blowfish encryption function is used to generate these subkeys:

 ```Generate the SubKeys: (1) First xor the expanded 72 bit key into the P array. for(i=0;i<18;i++) { P[i] = key[i] xor P[i] } (2) Assuming that the P array and 4 S-Boxes are ordered in the 1042 word array: SK = P,S[1],S[2],S[3],S[4]. xL = xR = 0 for(i=0;i<1042;i+=2) { xL,xR = Encrypt(xL,xR) SK[i] = xL SK[i+1] = xR } - xL and xR go through the encryption process again and again, but with constantly changing subkeys. ```

Prior to the key being read in and the subkeys being generated, the P array and S-Boxes are initialised to the first 4168 hex digits of PI (starting from after the decimal point).

## Encryption

The encryption process is straightforward:

 ```The input is a 64 bit (8 byte) data block (xL,xR). xL and xR are each 4 bytes in size. for(i=0;i<16;i++) { xL = xL xor P[i] xR = F(xL) xor xR if(i==15) break swap(xL,xR) } xR = xR xor P[16] xL = xL xor P[17] ```

## The F(xL) Function

The F(xL) function is defined as:

F(xL) = ((S1[A] + S2[B]) xor S3[C]) + S4[D]

Where S1 … S4 are the S-boxes and A,B,C,D are the bytes within xL. This calculation is done mod 232, which happens automatically when 32 bit registers are used.

## Input Byte Ordering

When an input message is read into memory, it is stored in Big Endian byte order. That is, the most significant byte in the message (the first byte) will be stored in the lowest memory address.

 ```For example, the message WXYZ is stored as: message[0] = W message[1] = X message[2] = Y message[3] = Z ```

Since x86 uses the little endian byte ordering and since Blowfish processes the message in blocks of 32 bit words, this means that once the message has been read into memory the byte order within each 4 byte word will need to be reversed.

In the Javascript version (in the other post), the byte swap happens automatically just by breaking up the input string into 4 byte blocks and calling the parseInt() function for each block to load it into the array of 32 bit words that stores the input message.

## The FASM x86 Code

The program accepts input as a hexadecimal number. To encrypt or decrypt, first enter the key and then press the [Refresh Key] button. Then press the [Encrypt] or [Decrypt] button. Note that each new key only needs to be entered once.

To encrypt a text message, first press the [Input To Hex] button to convert it to a hex number. Then press [Encrypt].

To convert a recently decrypted message back to text, press the [Output To Text] button. Non-printing characters will be replaced with the # character.

To view the sub keys (the P and S-Box arrays) press the [Sub Keys] button.

 ```; ------------------------------------------------------------------------------------- format PE GUI 4.0 entry start include 'win32a.inc' ; ------------------------------------------------------------------------------------- IDD_THE_DIALOG = 102 IDC_INPUT = 1000 IDC_OUTPUT = 1001 IDC_KEY = 1002 IDC_BTN_ENCRYPT = 1005 IDC_BTN_DECRYPT = 1006 IDC_BTN_KEY = 1007 IDC_BTN_TO_HEX = 1008 IDC_BTN_TO_TXT = 1009 IDC_BTN_RESET = 1010 IDC_BTN_SUB_KEYS = 1011 ; ------------------------------------------------------------------------------------- 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,szInputInfoText invoke SetDlgItemText,[hwnddlg],IDC_OUTPUT,szOutputInfoText invoke SetDlgItemText,[hwnddlg],IDC_KEY,szKeyInfoText stdcall onInitDialog jmp .done .wmcommand: cmp [wparam], BN_CLICKED shl 16 + IDC_BTN_SUB_KEYS je .SHOW_SUB_KEYS cmp [wparam], BN_CLICKED shl 16 + IDC_BTN_ENCRYPT je .ENCRYPT cmp [wparam], BN_CLICKED shl 16 + IDC_BTN_DECRYPT je .DECRYPT cmp [wparam], BN_CLICKED shl 16 + IDC_BTN_KEY je .GET_KEY cmp [wparam], BN_CLICKED shl 16 + IDC_BTN_TO_HEX je .INPUT_TO_HEX cmp [wparam], BN_CLICKED shl 16 + IDC_BTN_TO_TXT je .OUTPUT_TO_TXT cmp [wparam], BN_CLICKED shl 16 + IDC_BTN_RESET je .CLEARDATA jmp .done .SHOW_SUB_KEYS: stdcall onShowSubKeys invoke SetDlgItemText,[hwnddlg],IDC_INPUT,bfShowSubKeys jmp .done .ENCRYPT: invoke GetDlgItemText,[hwnddlg],IDC_INPUT,bfDisplay,2400 stdcall onNullInput stdcall StrToInputBuffer stdcall PrintInputBuffer invoke SetDlgItemText,[hwnddlg],IDC_INPUT,bfDisplay stdcall BswapInputBuffer stdcall EncryptInputBuffer stdcall BswapOutputBuffer stdcall PrintOutputBuffer invoke SetDlgItemText,[hwnddlg],IDC_OUTPUT,bfDisplay jmp .done .DECRYPT: invoke GetDlgItemText,[hwnddlg],IDC_INPUT,bfDisplay,2400 stdcall onNullInput stdcall StrToInputBuffer stdcall PrintInputBuffer invoke SetDlgItemText,[hwnddlg],IDC_INPUT,bfDisplay stdcall BswapInputBuffer stdcall DecryptInputBuffer stdcall BswapOutputBuffer stdcall PrintOutputBuffer invoke SetDlgItemText,[hwnddlg],IDC_OUTPUT,bfDisplay jmp .done .GET_KEY: invoke GetDlgItemText,[hwnddlg],IDC_KEY,bfDisplay,200 stdcall StrToKeyBits stdcall PrintKeyBits stdcall BswapKeyBitsBuffer stdcall Init_SubKey_Arrays stdcall GenerateSubKeys invoke SetDlgItemText,[hwnddlg],IDC_OUTPUT,bfDisplay jmp .done .INPUT_TO_HEX: invoke GetDlgItemText,[hwnddlg],IDC_INPUT,bfDisplay,2400 stdcall onNullInput stdcall InputToHex stdcall PrintInputBuffer invoke SetDlgItemText,[hwnddlg],IDC_INPUT,bfDisplay jmp .done .OUTPUT_TO_TXT: invoke GetDlgItemText,[hwnddlg],IDC_OUTPUT,bfDisplay,2400 stdcall onNullInput stdcall StrToInputBuffer stdcall OutputToText invoke SetDlgItemText,[hwnddlg],IDC_OUTPUT,bfDisplay jmp .done .CLEARDATA: invoke SetDlgItemText,[hwnddlg],IDC_INPUT,szInputInfoText invoke SetDlgItemText,[hwnddlg],IDC_OUTPUT,szOutputInfoText invoke SetDlgItemText,[hwnddlg],IDC_KEY,szKeyInfoText jmp .done .wmclose: invoke EndDialog,[hwnddlg],0 .done: mov eax,1 .quit: ret endp ; ------------------------------------------------------------------------------------- proc onInitDialog ; init with the zero key stdcall ResetKeyBits stdcall Init_SubKey_Arrays stdcall GenerateSubKeys ret endp ; ------------------------------------------------------------------------------------- proc onShowSubKeys ; print the P array and S-boxes to the bfShowSubKeys string lea esi,[P_ARR] lea edi,[bfShowSubKeys] mov cx,18 mov dx,0 .PRINT: mov eax,dword [esi] stdcall DWordToStr mov [edi],byte 32 inc edi ; update ESI add esi,4 ; DX counts the number of dwords inc dx ; add a CRLF after every 8 dwords test dx,7 jnz .NEXT mov [edi],byte 13 inc edi mov [edi],byte 10 inc edi .NEXT: dec cx cmp cx,0 jg .PRINT ; move on to the next S-Box cmp dx,1024 jge .DONE ; CRLF mov [edi],byte 13 inc edi mov [edi],byte 10 inc edi cmp dx,18 jg .CONT ; CRLF mov [edi],byte 13 inc edi mov [edi],byte 10 inc edi mov dx,0 lea esi,[S_BOXES] .CONT: mov cx,256 jmp .PRINT .DONE: ; 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 ret endp ; ------------------------------------------------------------------------------------- proc InputToHex uses edi esi ; convert an ascii text string to a hex number in memory lea esi,[bfDisplay] lea edi,[InputBuffer] ; just copy bfDisplay to InputBuffer stdcall ResetInputBuffer mov cx,0 .COPY: mov al,[esi] cmp al,0 je .DONE mov [edi],al inc esi inc edi inc cx cmp cx,1024 jne .COPY .DONE: ; adjust CX so it is a multiple of 8 bytes test cx,0x7 jz .QUIT shr cx,3 inc cx shl cx,3 .QUIT: ; save the number of bytes that were read: mov word [nInputBytes],cx ret endp ; ------------------------------------------------------------------------------------- proc OutputToText uses esi edi ; convert a hex number to a text string lea esi,[InputBuffer] lea edi,[bfDisplay] ; just copy InputBuffer to bfDisplay mov cx,word [nInputBytes] .COPY: mov al,[esi] cmp al,32 jl .HASH cmp al,126 jg .HASH mov [edi],al jmp .NEXT .HASH: ; non-printing character - substitute the # character mov [edi],byte 35 .NEXT: inc esi inc edi dec cx jcxz .DONE jmp .COPY .DONE: mov [edi],byte 0 ret endp ; ------------------------------------------------------------------------------------- proc ResetInputBuffer uses edi ecx ; clear the input buffer lea edi,[InputBuffer] mov cx,0 .CLEAR: mov [edi],byte 0 inc edi inc cx cmp cx,1024 jl .CLEAR ret endp ; ------------------------------------------------------------------------------------- proc ResetOutputBuffer uses edi ecx ; clear the output buffer lea edi,[OutputBuffer] mov cx,0 .CLEAR: mov [edi],byte 0 inc edi inc cx cmp cx,1024 jl .CLEAR ret endp ; ------------------------------------------------------------------------------------- proc ResetKeyBits uses edi ecx ; clear the key bits buffer lea edi,[KeyBits] mov cx,0 .CLEAR: mov [edi],byte 0 inc edi inc cx cmp cx,72 jl .CLEAR ret endp ; ------------------------------------------------------------------------------------- proc BswapInputBuffer ; for each 32 bit dword in the input buffer, reverse the bytes mov cx,word [nInputBytes] ; divide by 4 shr cx,2 lea eax,[InputBuffer] stdcall ReverseBytes ret endp ; ------------------------------------------------------------------------------------- proc BswapOutputBuffer ; for each 32 bit dword in the output buffer, reverse the bytes mov cx,word [nInputBytes] ; divide by 4 shr cx,2 lea eax,[OutputBuffer] stdcall ReverseBytes ret endp ; ------------------------------------------------------------------------------------- proc BswapKeyBitsBuffer ; for each 32 bit dword in the key bits buffer, reverse the bytes mov cx,18 lea eax,[KeyBits] stdcall ReverseBytes ret endp ; ------------------------------------------------------------------------------------- proc ReverseBytes uses esi ; for each 32 bit dword in a buffer, reverse the bytes ; address of buffer passed in EAX ; size of buffer in dwords passed in CX mov esi,eax .REVERSE: mov eax,[esi] bswap eax mov [esi],eax add esi,4 dec cx cmp cx,0 jg .REVERSE ret endp ; ------------------------------------------------------------------------------------- proc onNullInput ; if the bfDisplay string is empty, set it to "0" lea edi,[bfDisplay] cmp [edi],byte 0 jne .DONE mov [edi],byte 48 mov [edi+1],byte 0 .DONE: 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 PrintBuffer uses esi edi ; print the hex value in the buffer to the bfDisplay string ; address of buffer passed in EAX ; number of bytes in buffer passed in EDX locals count db 0 endl mov esi,eax lea edi,[bfDisplay] mov ecx,edx .PRINT: ; byte to digits mov al,[esi] stdcall ByteToDigits ; add the 2 digits to the string mov [edi],ah inc edi mov [edi],al inc edi dec cx jcxz .DONE ; update ESI inc esi ; add spaces and CRLF to the output string ; a space after every 8 chars ; a CRLF after every 64 chars add [count],2 test [count],7 jne .PRINT test [count],63 je .ADD_CRLF mov [edi],byte 32 inc edi jmp .PRINT .ADD_CRLF: mov [edi],byte 13 inc edi mov [edi],byte 10 inc edi jmp .PRINT .DONE: ; zero terminate the string mov [edi],byte 0 ret endp ; ------------------------------------------------------------------------------------- proc PrintKeyBits ; print the 72 byte key bits buffer to the display string lea eax,[KeyBits] mov edx,72 stdcall PrintBuffer ret endp ; ------------------------------------------------------------------------------------- proc PrintInputBuffer ; print the input buffer to the display string lea eax,[InputBuffer] xor edx,edx mov dx,word [nInputBytes] stdcall PrintBuffer ret endp ; ------------------------------------------------------------------------------------- proc PrintOutputBuffer ; print the output buffer to the display string lea eax,[OutputBuffer] xor edx,edx mov dx,word [nInputBytes] stdcall PrintBuffer 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 GetKeyStr uses esi edi ; the input key is in bfDisplay - process this string ; if bfDisplay is longer than 56 bytes - truncate it to 56 bytes ; fill the key bits out to 72 bytes lea esi,[bfDisplay] mov ecx,0 .GET_LEN: cmp [esi],byte 0 je .FILL inc esi inc cx cmp cx,112 jl .GET_LEN .FILL: cmp cx,0 je .NULL_KEY mov dx,cx lea esi,[bfDisplay] lea edi,[bfDisplay] add edi,ecx mov cx,0 .COPY_DIGITS: ; copy up the hex digits in the input string mov al,[esi] mov [edi],al inc esi inc edi inc cx cmp cx,dx jl .COPY_DIGITS add cx,dx cmp cx,144 jl .FILL jmp .DONE .NULL_KEY: lea edi,[bfDisplay] mov cx,0 .FILL_0: mov [edi],byte 48 inc edi inc cx cmp cx,144 jl .FILL_0 .DONE: ; terminate the string at 72 bytes (144 hex chars) lea edi,[bfDisplay] add edi,144 mov [edi],byte 0 ret endp ; ------------------------------------------------------------------------------------- proc StrToKeyBits ; get the key from the input string ; input string is a hex value stdcall ResetKeyBits ; pre-process the bfDisplay string to fill the key out to 144 hex digits stdcall StrToHexStr stdcall GetKeyStr ; load the hex value of the key into the [KeyBits] buffer lea eax,[KeyBits] mov edx,144 stdcall StrToBuffer ret endp ; ------------------------------------------------------------------------------------- proc StrToInputBuffer ; load the input buffer from the input string ; input string is a hex value ; reset the input buffer stdcall ResetInputBuffer lea eax,[InputBuffer] mov edx,2048 stdcall StrToBuffer ; the number of hex digits that were read are now in EDX ; the size of the input buffer should be a multiple of 8 bytes ; adjust InputLength if necessary ; input buffer is already padded with zeros ; test if EDX is a multiple of 16 (hex digits) test edx,0xf jz .QUIT ; adjust EDX so it is a multiple of 16 hex digits (8 bytes) shr edx,4 inc edx shl edx,4 .QUIT: ; divide EDX by 2 and save to InputLength shr edx,1 mov word [nInputBytes],dx 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 ; ------------------------------------------------------------------------------------- proc EncryptInputBuffer uses esi edi ; input length should be a multiple of 8 bytes ; divide by 8 to give the number of 64 bit blocks to process mov cx,word [nInputBytes] shr cx,3 ; quit if greater than 128 (1024 bytes) cmp cx,128 jg .DONE ; clear the output buffer stdcall ResetOutputBuffer ; do the encryption lea esi,[InputBuffer] lea edi,[OutputBuffer] .PROCESS: mov eax,[esi] mov edx,[esi+4] stdcall Encrypt mov [edi],eax mov [edi+4],edx add esi,8 add edi,8 dec cx jcxz .DONE jmp .PROCESS .DONE: ret endp ; ------------------------------------------------------------------------------------- proc DecryptInputBuffer uses esi edi ; input length should be a multiple of 8 bytes ; divide by 8 to give the number of 64 bit blocks to process mov cx,word [nInputBytes] shr cx,3 ; quit if greater than 128 (1024 bytes) cmp cx,128 jg .DONE ; clear the output buffer stdcall ResetOutputBuffer ; do the encryption lea esi,[InputBuffer] lea edi,[OutputBuffer] .PROCESS: mov eax,[esi] mov edx,[esi+4] stdcall Decrypt mov [edi],eax mov [edi+4],edx add esi,8 add edi,8 dec cx jcxz .DONE jmp .PROCESS .DONE: ret endp ; ------------------------------------------------------------------------------------- proc Encrypt uses esi ecx ebx ; xL is passed in EAX ; xR is passed in EDX lea esi,[P_ARR] mov cx,16 .ROUNDS: mov ebx,edx ; xL = xL xor P[i] xor eax,[esi] ; calc F(xL) stdcall F_xL ; xR = F(xL) xor xR xor edx,ebx ; xL is in EAX and xR in EDX add esi,4 dec cx ; don't want to swap xL,xR in the last round jcxz .FINISH ; swap xL and xR (xR is in EDX) mov ebx,edx mov edx,eax mov eax,ebx ; xL has been moved to EDX and xR to EAX jmp .ROUNDS .FINISH: ; xR = xR xor P[17] xor edx,dword [esi] ; xL = xL xor P[18] add esi,4 xor eax,dword [esi] ; xL is now in EAX ; xR is now in EDX ; RETURN ret endp ; ------------------------------------------------------------------------------------- proc Decrypt uses esi ecx ebx ; xL is passed in EAX ; xR is passed in EDX lea esi,[P_ARR] ; use P in the reverse order (start from P[18]) add esi,68 mov cx,16 .ROUNDS: mov ebx,edx ; xL = xL xor P[i] xor eax,dword [esi] ; calc F(xL) stdcall F_xL ; xR = F(xL) xor xR xor edx,ebx ; xL is in EAX and xR in EDX sub esi,4 dec cx ; don't want to swap xL,xR in the last round jcxz .FINISH ; swap xL and xR (xR is in EDX) mov ebx,edx mov edx,eax mov eax,ebx ; xL has been moved to EDX and xR to EAX jmp .ROUNDS .FINISH: ; xR = xR xor P[2] xor edx,dword [esi] ; xL = xL xor P[1] sub esi,4 xor eax,dword [esi] ; xL is now in EAX ; xR is now in EDX ; RETURN ret endp ; ------------------------------------------------------------------------------------- macro GET_A reg { shr reg,24 and reg,0xff shl reg,2 } ; ------------------------------------------------------------------------------------- macro GET_B reg { shr reg,16 and reg,0xff shl reg,2 } ; ------------------------------------------------------------------------------------- macro GET_C reg { shr reg,8 and reg,0xff shl reg,2 } ; ------------------------------------------------------------------------------------- macro GET_D reg { and reg,0xff shl reg,2 } ; ------------------------------------------------------------------------------------- proc F_xL uses esi ; F(xL) = ((S1[a] + S2[b]) xor S3[c]) + S4[d] ; xL is passed in EAX locals temp dd 0 endl mov dword [temp],eax ; xL = a,b,c,d ; F = S1[a] lea esi,[S_BOXES] GET_A eax mov edx,[esi+eax] ; F += S2[b] lea esi,[S_BOXES] add esi,1024 mov eax,dword [temp] GET_B eax add edx,[esi+eax] ; F = F xor S3[c] lea esi,[S_BOXES] add esi,2048 mov eax,dword [temp] GET_C eax xor edx,[esi+eax] ; F += S4[d] lea esi,[S_BOXES] add esi,3072 mov eax,dword [temp] GET_D eax add edx,[esi+eax] ; restore EAX mov eax,dword [temp] ; return xR in EDX ret endp ; ------------------------------------------------------------------------------------- proc GenerateSubKeys uses ebx esi edi ; xor the key bits into the P array: lea esi,[KeyBits] lea edi,[P_ARR] mov cx,0 .XOR_P: mov eax,dword [esi] xor dword [edi],eax add esi,4 add edi,4 inc cx cmp cx,18 jl .XOR_P ; encrypt and replace the P and S-Box arrays ; start with the all-zero string (in EAX and EDX) xor eax,eax xor edx,edx ; the P array lea edi,[P_ARR] mov cx,9 stdcall Replace ; the S Boxes lea edi,[S_BOXES] mov cx,512 stdcall Replace ret endp ; ------------------------------------------------------------------------------------- proc Replace ; called by GenerateSubKeys .REPLACE: stdcall Encrypt mov dword [edi],eax mov dword [edi+4],edx add edi,8 dec cx jcxz .DONE jmp .REPLACE .DONE: ret endp ; ------------------------------------------------------------------------------------- macro LOAD_8 w1,w2,w3,w4,w5,w6,w7,w8,offset { mov [edi+offset],dword w1 mov [edi+offset+4],dword w2 mov [edi+offset+8],dword w3 mov [edi+offset+12],dword w4 mov [edi+offset+16],dword w5 mov [edi+offset+20],dword w6 mov [edi+offset+24],dword w7 mov [edi+offset+28],dword w8 } ; ------------------------------------------------------------------------------------- macro LOAD_6 w1,w2,w3,w4,w5,w6,offset { mov [edi+offset],dword w1 mov [edi+offset+4],dword w2 mov [edi+offset+8],dword w3 mov [edi+offset+12],dword w4 mov [edi+offset+16],dword w5 mov [edi+offset+20],dword w6 } ; ------------------------------------------------------------------------------------- proc Init_SubKey_Arrays uses edi ; subkey arrays = 4168 bytes ; initialise the P Array (72 bytes) lea edi,[P_ARR] LOAD_6 0x243f6a88,0x85a308d3,0x13198a2e,0x03707344,0xa4093822,0x299f31d0,0 LOAD_6 0x082efa98,0xec4e6c89,0x452821e6,0x38d01377,0xbe5466cf,0x34e90c6c,24 LOAD_6 0xc0ac29b7,0xc97c50dd,0x3f84d5b5,0xb5470917,0x9216d5d9,0x8979fb1b,48 ; initialise S-box 1 (1024 bytes) lea edi,[S_BOXES] LOAD_8 0xd1310ba6,0x98dfb5ac,0x2ffd72db,0xd01adfb7,0xb8e1afed,0x6a267e96,0xba7c9045,0xf12c7f99,0 LOAD_8 0x24a19947,0xb3916cf7,0x0801f2e2,0x858efc16,0x636920d8,0x71574e69,0xa458fea3,0xf4933d7e,32 LOAD_8 0x0d95748f,0x728eb658,0x718bcd58,0x82154aee,0x7b54a41d,0xc25a59b5,0x9c30d539,0x2af26013,64 LOAD_8 0xc5d1b023,0x286085f0,0xca417918,0xb8db38ef,0x8e79dcb0,0x603a180e,0x6c9e0e8b,0xb01e8a3e,96 LOAD_8 0xd71577c1,0xbd314b27,0x78af2fda,0x55605c60,0xe65525f3,0xaa55ab94,0x57489862,0x63e81440,128 LOAD_8 0x55ca396a,0x2aab10b6,0xb4cc5c34,0x1141e8ce,0xa15486af,0x7c72e993,0xb3ee1411,0x636fbc2a,160 LOAD_8 0x2ba9c55d,0x741831f6,0xce5c3e16,0x9b87931e,0xafd6ba33,0x6c24cf5c,0x7a325381,0x28958677,192 LOAD_8 0x3b8f4898,0x6b4bb9af,0xc4bfe81b,0x66282193,0x61d809cc,0xfb21a991,0x487cac60,0x5dec8032,224 LOAD_8 0xef845d5d,0xe98575b1,0xdc262302,0xeb651b88,0x23893e81,0xd396acc5,0x0f6d6ff3,0x83f44239,256 LOAD_8 0x2e0b4482,0xa4842004,0x69c8f04a,0x9e1f9b5e,0x21c66842,0xf6e96c9a,0x670c9c61,0xabd388f0,288 LOAD_8 0x6a51a0d2,0xd8542f68,0x960fa728,0xab5133a3,0x6eef0b6c,0x137a3be4,0xba3bf050,0x7efb2a98,320 LOAD_8 0xa1f1651d,0x39af0176,0x66ca593e,0x82430e88,0x8cee8619,0x456f9fb4,0x7d84a5c3,0x3b8b5ebe,352 LOAD_8 0xe06f75d8,0x85c12073,0x401a449f,0x56c16aa6,0x4ed3aa62,0x363f7706,0x1bfedf72,0x429b023d,384 LOAD_8 0x37d0d724,0xd00a1248,0xdb0fead3,0x49f1c09b,0x075372c9,0x80991b7b,0x25d479d8,0xf6e8def7,416 LOAD_8 0xe3fe501a,0xb6794c3b,0x976ce0bd,0x04c006ba,0xc1a94fb6,0x409f60c4,0x5e5c9ec2,0x196a2463,448 LOAD_8 0x68fb6faf,0x3e6c53b5,0x1339b2eb,0x3b52ec6f,0x6dfc511f,0x9b30952c,0xcc814544,0xaf5ebd09,480 LOAD_8 0xbee3d004,0xde334afd,0x660f2807,0x192e4bb3,0xc0cba857,0x45c8740f,0xd20b5f39,0xb9d3fbdb,512 LOAD_8 0x5579c0bd,0x1a60320a,0xd6a100c6,0x402c7279,0x679f25fe,0xfb1fa3cc,0x8ea5e9f8,0xdb3222f8,544 LOAD_8 0x3c7516df,0xfd616b15,0x2f501ec8,0xad0552ab,0x323db5fa,0xfd238760,0x53317b48,0x3e00df82,576 LOAD_8 0x9e5c57bb,0xca6f8ca0,0x1a87562e,0xdf1769db,0xd542a8f6,0x287effc3,0xac6732c6,0x8c4f5573,608 LOAD_8 0x695b27b0,0xbbca58c8,0xe1ffa35d,0xb8f011a0,0x10fa3d98,0xfd2183b8,0x4afcb56c,0x2dd1d35b,640 LOAD_8 0x9a53e479,0xb6f84565,0xd28e49bc,0x4bfb9790,0xe1ddf2da,0xa4cb7e33,0x62fb1341,0xcee4c6e8,672 LOAD_8 0xef20cada,0x36774c01,0xd07e9efe,0x2bf11fb4,0x95dbda4d,0xae909198,0xeaad8e71,0x6b93d5a0,704 LOAD_8 0xd08ed1d0,0xafc725e0,0x8e3c5b2f,0x8e7594b7,0x8ff6e2fb,0xf2122b64,0x8888b812,0x900df01c,736 LOAD_8 0x4fad5ea0,0x688fc31c,0xd1cff191,0xb3a8c1ad,0x2f2f2218,0xbe0e1777,0xea752dfe,0x8b021fa1,768 LOAD_8 0xe5a0cc0f,0xb56f74e8,0x18acf3d6,0xce89e299,0xb4a84fe0,0xfd13e0b7,0x7cc43b81,0xd2ada8d9,800 LOAD_8 0x165fa266,0x80957705,0x93cc7314,0x211a1477,0xe6ad2065,0x77b5fa86,0xc75442f5,0xfb9d35cf,832 LOAD_8 0xebcdaf0c,0x7b3e89a0,0xd6411bd3,0xae1e7e49,0x00250e2d,0x2071b35e,0x226800bb,0x57b8e0af,864 LOAD_8 0x2464369b,0xf009b91e,0x5563911d,0x59dfa6aa,0x78c14389,0xd95a537f,0x207d5ba2,0x02e5b9c5,896 LOAD_8 0x83260376,0x6295cfa9,0x11c81968,0x4e734a41,0xb3472dca,0x7b14a94a,0x1b510052,0x9a532915,928 LOAD_8 0xd60f573f,0xbc9bc6e4,0x2b60a476,0x81e67400,0x08ba6fb5,0x571be91f,0xf296ec6b,0x2a0dd915,960 LOAD_8 0xb6636521,0xe7b9f9b6,0xff34052e,0xc5855664,0x53b02d5d,0xa99f8fa1,0x08ba4799,0x6e85076a,992 ; initialise S-box 2 (1024 bytes) add edi,1024 LOAD_8 0x4b7a70e9,0xb5b32944,0xdb75092e,0xc4192623,0xad6ea6b0,0x49a7df7d,0x9cee60b8,0x8fedb266,0 LOAD_8 0xecaa8c71,0x699a17ff,0x5664526c,0xc2b19ee1,0x193602a5,0x75094c29,0xa0591340,0xe4183a3e,32 LOAD_8 0x3f54989a,0x5b429d65,0x6b8fe4d6,0x99f73fd6,0xa1d29c07,0xefe830f5,0x4d2d38e6,0xf0255dc1,64 LOAD_8 0x4cdd2086,0x8470eb26,0x6382e9c6,0x021ecc5e,0x09686b3f,0x3ebaefc9,0x3c971814,0x6b6a70a1,96 LOAD_8 0x687f3584,0x52a0e286,0xb79c5305,0xaa500737,0x3e07841c,0x7fdeae5c,0x8e7d44ec,0x5716f2b8,128 LOAD_8 0xb03ada37,0xf0500c0d,0xf01c1f04,0x0200b3ff,0xae0cf51a,0x3cb574b2,0x25837a58,0xdc0921bd,160 LOAD_8 0xd19113f9,0x7ca92ff6,0x94324773,0x22f54701,0x3ae5e581,0x37c2dadc,0xc8b57634,0x9af3dda7,192 LOAD_8 0xa9446146,0x0fd0030e,0xecc8c73e,0xa4751e41,0xe238cd99,0x3bea0e2f,0x3280bba1,0x183eb331,224 LOAD_8 0x4e548b38,0x4f6db908,0x6f420d03,0xf60a04bf,0x2cb81290,0x24977c79,0x5679b072,0xbcaf89af,256 LOAD_8 0xde9a771f,0xd9930810,0xb38bae12,0xdccf3f2e,0x5512721f,0x2e6b7124,0x501adde6,0x9f84cd87,288 LOAD_8 0x7a584718,0x7408da17,0xbc9f9abc,0xe94b7d8c,0xec7aec3a,0xdb851dfa,0x63094366,0xc464c3d2,320 LOAD_8 0xef1c1847,0x3215d908,0xdd433b37,0x24c2ba16,0x12a14d43,0x2a65c451,0x50940002,0x133ae4dd,352 LOAD_8 0x71dff89e,0x10314e55,0x81ac77d6,0x5f11199b,0x043556f1,0xd7a3c76b,0x3c11183b,0x5924a509,384 LOAD_8 0xf28fe6ed,0x97f1fbfa,0x9ebabf2c,0x1e153c6e,0x86e34570,0xeae96fb1,0x860e5e0a,0x5a3e2ab3,416 LOAD_8 0x771fe71c,0x4e3d06fa,0x2965dcb9,0x99e71d0f,0x803e89d6,0x5266c825,0x2e4cc978,0x9c10b36a,448 LOAD_8 0xc6150eba,0x94e2ea78,0xa5fc3c53,0x1e0a2df4,0xf2f74ea7,0x361d2b3d,0x1939260f,0x19c27960,480 LOAD_8 0x5223a708,0xf71312b6,0xebadfe6e,0xeac31f66,0xe3bc4595,0xa67bc883,0xb17f37d1,0x018cff28,512 LOAD_8 0xc332ddef,0xbe6c5aa5,0x65582185,0x68ab9802,0xeecea50f,0xdb2f953b,0x2aef7dad,0x5b6e2f84,544 LOAD_8 0x1521b628,0x29076170,0xecdd4775,0x619f1510,0x13cca830,0xeb61bd96,0x0334fe1e,0xaa0363cf,576 LOAD_8 0xb5735c90,0x4c70a239,0xd59e9e0b,0xcbaade14,0xeecc86bc,0x60622ca7,0x9cab5cab,0xb2f3846e,608 LOAD_8 0x648b1eaf,0x19bdf0ca,0xa02369b9,0x655abb50,0x40685a32,0x3c2ab4b3,0x319ee9d5,0xc021b8f7,640 LOAD_8 0x9b540b19,0x875fa099,0x95f7997e,0x623d7da8,0xf837889a,0x97e32d77,0x11ed935f,0x16681281,672 LOAD_8 0x0e358829,0xc7e61fd6,0x96dedfa1,0x7858ba99,0x57f584a5,0x1b227263,0x9b83c3ff,0x1ac24696,704 LOAD_8 0xcdb30aeb,0x532e3054,0x8fd948e4,0x6dbc3128,0x58ebf2ef,0x34c6ffea,0xfe28ed61,0xee7c3c73,736 LOAD_8 0x5d4a14d9,0xe864b7e3,0x42105d14,0x203e13e0,0x45eee2b6,0xa3aaabea,0xdb6c4f15,0xfacb4fd0,768 LOAD_8 0xc742f442,0xef6abbb5,0x654f3b1d,0x41cd2105,0xd81e799e,0x86854dc7,0xe44b476a,0x3d816250,800 LOAD_8 0xcf62a1f2,0x5b8d2646,0xfc8883a0,0xc1c7b6a3,0x7f1524c3,0x69cb7492,0x47848a0b,0x5692b285,832 LOAD_8 0x095bbf00,0xad19489d,0x1462b174,0x23820e00,0x58428d2a,0x0c55f5ea,0x1dadf43e,0x233f7061,864 LOAD_8 0x3372f092,0x8d937e41,0xd65fecf1,0x6c223bdb,0x7cde3759,0xcbee7460,0x4085f2a7,0xce77326e,896 LOAD_8 0xa6078084,0x19f8509e,0xe8efd855,0x61d99735,0xa969a7aa,0xc50c06c2,0x5a04abfc,0x800bcadc,928 LOAD_8 0x9e447a2e,0xc3453484,0xfdd56705,0x0e1e9ec9,0xdb73dbd3,0x105588cd,0x675fda79,0xe3674340,960 LOAD_8 0xc5c43465,0x713e38d8,0x3d28f89e,0xf16dff20,0x153e21e7,0x8fb03d4a,0xe6e39f2b,0xdb83adf7,992 ; initialise S-box 3 (1024 bytes) add edi,1024 LOAD_8 0xe93d5a68,0x948140f7,0xf64c261c,0x94692934,0x411520f7,0x7602d4f7,0xbcf46b2e,0xd4a20068,0 LOAD_8 0xd4082471,0x3320f46a,0x43b7d4b7,0x500061af,0x1e39f62e,0x97244546,0x14214f74,0xbf8b8840,32 LOAD_8 0x4d95fc1d,0x96b591af,0x70f4ddd3,0x66a02f45,0xbfbc09ec,0x03bd9785,0x7fac6dd0,0x31cb8504,64 LOAD_8 0x96eb27b3,0x55fd3941,0xda2547e6,0xabca0a9a,0x28507825,0x530429f4,0x0a2c86da,0xe9b66dfb,96 LOAD_8 0x68dc1462,0xd7486900,0x680ec0a4,0x27a18dee,0x4f3ffea2,0xe887ad8c,0xb58ce006,0x7af4d6b6,128 LOAD_8 0xaace1e7c,0xd3375fec,0xce78a399,0x406b2a42,0x20fe9e35,0xd9f385b9,0xee39d7ab,0x3b124e8b,160 LOAD_8 0x1dc9faf7,0x4b6d1856,0x26a36631,0xeae397b2,0x3a6efa74,0xdd5b4332,0x6841e7f7,0xca7820fb,192 LOAD_8 0xfb0af54e,0xd8feb397,0x454056ac,0xba489527,0x55533a3a,0x20838d87,0xfe6ba9b7,0xd096954b,224 LOAD_8 0x55a867bc,0xa1159a58,0xcca92963,0x99e1db33,0xa62a4a56,0x3f3125f9,0x5ef47e1c,0x9029317c,256 LOAD_8 0xfdf8e802,0x04272f70,0x80bb155c,0x05282ce3,0x95c11548,0xe4c66d22,0x48c1133f,0xc70f86dc,288 LOAD_8 0x07f9c9ee,0x41041f0f,0x404779a4,0x5d886e17,0x325f51eb,0xd59bc0d1,0xf2bcc18f,0x41113564,320 LOAD_8 0x257b7834,0x602a9c60,0xdff8e8a3,0x1f636c1b,0x0e12b4c2,0x02e1329e,0xaf664fd1,0xcad18115,352 LOAD_8 0x6b2395e0,0x333e92e1,0x3b240b62,0xeebeb922,0x85b2a20e,0xe6ba0d99,0xde720c8c,0x2da2f728,384 LOAD_8 0xd0127845,0x95b794fd,0x647d0862,0xe7ccf5f0,0x5449a36f,0x877d48fa,0xc39dfd27,0xf33e8d1e,416 LOAD_8 0x0a476341,0x992eff74,0x3a6f6eab,0xf4f8fd37,0xa812dc60,0xa1ebddf8,0x991be14c,0xdb6e6b0d,448 LOAD_8 0xc67b5510,0x6d672c37,0x2765d43b,0xdcd0e804,0xf1290dc7,0xcc00ffa3,0xb5390f92,0x690fed0b,480 LOAD_8 0x667b9ffb,0xcedb7d9c,0xa091cf0b,0xd9155ea3,0xbb132f88,0x515bad24,0x7b9479bf,0x763bd6eb,512 LOAD_8 0x37392eb3,0xcc115979,0x8026e297,0xf42e312d,0x6842ada7,0xc66a2b3b,0x12754ccc,0x782ef11c,544 LOAD_8 0x6a124237,0xb79251e7,0x06a1bbe6,0x4bfb6350,0x1a6b1018,0x11caedfa,0x3d25bdd8,0xe2e1c3c9,576 LOAD_8 0x44421659,0x0a121386,0xd90cec6e,0xd5abea2a,0x64af674e,0xda86a85f,0xbebfe988,0x64e4c3fe,608 LOAD_8 0x9dbc8057,0xf0f7c086,0x60787bf8,0x6003604d,0xd1fd8346,0xf6381fb0,0x7745ae04,0xd736fccc,640 LOAD_8 0x83426b33,0xf01eab71,0xb0804187,0x3c005e5f,0x77a057be,0xbde8ae24,0x55464299,0xbf582e61,672 LOAD_8 0x4e58f48f,0xf2ddfda2,0xf474ef38,0x8789bdc2,0x5366f9c3,0xc8b38e74,0xb475f255,0x46fcd9b9,704 LOAD_8 0x7aeb2661,0x8b1ddf84,0x846a0e79,0x915f95e2,0x466e598e,0x20b45770,0x8cd55591,0xc902de4c,736 LOAD_8 0xb90bace1,0xbb8205d0,0x11a86248,0x7574a99e,0xb77f19b6,0xe0a9dc09,0x662d09a1,0xc4324633,768 LOAD_8 0xe85a1f02,0x09f0be8c,0x4a99a025,0x1d6efe10,0x1ab93d1d,0x0ba5a4df,0xa186f20f,0x2868f169,800 LOAD_8 0xdcb7da83,0x573906fe,0xa1e2ce9b,0x4fcd7f52,0x50115e01,0xa70683fa,0xa002b5c4,0x0de6d027,832 LOAD_8 0x9af88c27,0x773f8641,0xc3604c06,0x61a806b5,0xf0177a28,0xc0f586e0,0x006058aa,0x30dc7d62,864 LOAD_8 0x11e69ed7,0x2338ea63,0x53c2dd94,0xc2c21634,0xbbcbee56,0x90bcb6de,0xebfc7da1,0xce591d76,896 LOAD_8 0x6f05e409,0x4b7c0188,0x39720a3d,0x7c927c24,0x86e3725f,0x724d9db9,0x1ac15bb4,0xd39eb8fc,928 LOAD_8 0xed545578,0x08fca5b5,0xd83d7cd3,0x4dad0fc4,0x1e50ef5e,0xb161e6f8,0xa28514d9,0x6c51133c,960 LOAD_8 0x6fd5c7e7,0x56e14ec4,0x362abfce,0xddc6c837,0xd79a3234,0x92638212,0x670efa8e,0x406000e0,992 ; initialise S-box 4 (1024 bytes) add edi,1024 LOAD_8 0x3a39ce37,0xd3faf5cf,0xabc27737,0x5ac52d1b,0x5cb0679e,0x4fa33742,0xd3822740,0x99bc9bbe,0 LOAD_8 0xd5118e9d,0xbf0f7315,0xd62d1c7e,0xc700c47b,0xb78c1b6b,0x21a19045,0xb26eb1be,0x6a366eb4,32 LOAD_8 0x5748ab2f,0xbc946e79,0xc6a376d2,0x6549c2c8,0x530ff8ee,0x468dde7d,0xd5730a1d,0x4cd04dc6,64 LOAD_8 0x2939bbdb,0xa9ba4650,0xac9526e8,0xbe5ee304,0xa1fad5f0,0x6a2d519a,0x63ef8ce2,0x9a86ee22,96 LOAD_8 0xc089c2b8,0x43242ef6,0xa51e03aa,0x9cf2d0a4,0x83c061ba,0x9be96a4d,0x8fe51550,0xba645bd6,128 LOAD_8 0x2826a2f9,0xa73a3ae1,0x4ba99586,0xef5562e9,0xc72fefd3,0xf752f7da,0x3f046f69,0x77fa0a59,160 LOAD_8 0x80e4a915,0x87b08601,0x9b09e6ad,0x3b3ee593,0xe990fd5a,0x9e34d797,0x2cf0b7d9,0x022b8b51,192 LOAD_8 0x96d5ac3a,0x017da67d,0xd1cf3ed6,0x7c7d2d28,0x1f9f25cf,0xadf2b89b,0x5ad6b472,0x5a88f54c,224 LOAD_8 0xe029ac71,0xe019a5e6,0x47b0acfd,0xed93fa9b,0xe8d3c48d,0x283b57cc,0xf8d56629,0x79132e28,256 LOAD_8 0x785f0191,0xed756055,0xf7960e44,0xe3d35e8c,0x15056dd4,0x88f46dba,0x03a16125,0x0564f0bd,288 LOAD_8 0xc3eb9e15,0x3c9057a2,0x97271aec,0xa93a072a,0x1b3f6d9b,0x1e6321f5,0xf59c66fb,0x26dcf319,320 LOAD_8 0x7533d928,0xb155fdf5,0x03563482,0x8aba3cbb,0x28517711,0xc20ad9f8,0xabcc5167,0xccad925f,352 LOAD_8 0x4de81751,0x3830dc8e,0x379d5862,0x9320f991,0xea7a90c2,0xfb3e7bce,0x5121ce64,0x774fbe32,384 LOAD_8 0xa8b6e37e,0xc3293d46,0x48de5369,0x6413e680,0xa2ae0810,0xdd6db224,0x69852dfd,0x09072166,416 LOAD_8 0xb39a460a,0x6445c0dd,0x586cdecf,0x1c20c8ae,0x5bbef7dd,0x1b588d40,0xccd2017f,0x6bb4e3bb,448 LOAD_8 0xdda26a7e,0x3a59ff45,0x3e350a44,0xbcb4cdd5,0x72eacea8,0xfa6484bb,0x8d6612ae,0xbf3c6f47,480 LOAD_8 0xd29be463,0x542f5d9e,0xaec2771b,0xf64e6370,0x740e0d8d,0xe75b1357,0xf8721671,0xaf537d5d,512 LOAD_8 0x4040cb08,0x4eb4e2cc,0x34d2466a,0x0115af84,0xe1b00428,0x95983a1d,0x06b89fb4,0xce6ea048,544 LOAD_8 0x6f3f3b82,0x3520ab82,0x011a1d4b,0x277227f8,0x611560b1,0xe7933fdc,0xbb3a792b,0x344525bd,576 LOAD_8 0xa08839e1,0x51ce794b,0x2f32c9b7,0xa01fbac9,0xe01cc87e,0xbcc7d1f6,0xcf0111c3,0xa1e8aac7,608 LOAD_8 0x1a908749,0xd44fbd9a,0xd0dadecb,0xd50ada38,0x0339c32a,0xc6913667,0x8df9317c,0xe0b12b4f,640 LOAD_8 0xf79e59b7,0x43f5bb3a,0xf2d519ff,0x27d9459c,0xbf97222c,0x15e6fc2a,0x0f91fc71,0x9b941525,672 LOAD_8 0xfae59361,0xceb69ceb,0xc2a86459,0x12baa8d1,0xb6c1075e,0xe3056a0c,0x10d25065,0xcb03a442,704 LOAD_8 0xe0ec6e0e,0x1698db3b,0x4c98a0be,0x3278e964,0x9f1f9532,0xe0d392df,0xd3a0342b,0x8971f21e,736 LOAD_8 0x1b0a7441,0x4ba3348c,0xc5be7120,0xc37632d8,0xdf359f8d,0x9b992f2e,0xe60b6f47,0x0fe3f11d,768 LOAD_8 0xe54cda54,0x1edad891,0xce6279cf,0xcd3e7e6f,0x1618b166,0xfd2c1d05,0x848fd2c5,0xf6fb2299,800 LOAD_8 0xf523f357,0xa6327623,0x93a83531,0x56cccd02,0xacf08162,0x5a75ebb5,0x6e163697,0x88d273cc,832 LOAD_8 0xde966292,0x81b949d0,0x4c50901b,0x71c65614,0xe6c6c7bd,0x327a140a,0x45e1d006,0xc3f27b9a,864 LOAD_8 0xc9aa53fd,0x62a80f00,0xbb25bfe2,0x35bdd2f6,0x71126905,0xb2040222,0xb6cbcf7c,0xcd769c2b,896 LOAD_8 0x53113ec0,0x1640e3d3,0x38abbd60,0x2547adf0,0xba38209c,0xf746ce76,0x77afa1c5,0x20756060,928 LOAD_8 0x85cbfe4e,0x8ae88dd8,0x7aaaf9b0,0x4cf9aa7e,0x1948c25c,0x02fb8a8c,0x01c36ae4,0xd6ebe1f9,960 LOAD_8 0x90d4f869,0xa65cdea0,0x3f09252d,0xc208e69f,0xb74e6132,0xce77e25b,0x578fdfe3,0x3ac372e6,992 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 '.sbox' readable writeable S_BOXES rb 4096 ; ------------------------------------------------------------------------------------- section '.data' readable writeable P_ARR rb 72 KeyBits rb 72 nInputBytes dw 0 InputBuffer rb 1024 OutputBuffer rb 1024 bfDisplay rb 2400 szInputInfoText db "Enter the input as a hex number. Max length = 1024 bytes (2048 hex digits).",0 szOutputInfoText db "The output: Encrypted plain text or decrypted cipher text.",0 szKeyInfoText db "Enter the key as a hex number. Max length = 56 bytes (112 hex digits).",0 ; ------------------------------------------------------------------------------------- section '.data2' readable writeable bfShowSubKeys rb 10000 ; ------------------------------------------------------------------------------------- section '.rc' resource data readable directory RT_DIALOG,dialogs resource dialogs,IDD_THE_DIALOG,LANG_ENGLISH+SUBLANG_DEFAULT,blowfish_dialog dialog blowfish_dialog,\ 'Blowfish',50,50,360,415,\ DS_MODALFRAME+WS_MINIMIZEBOX+WS_POPUP+WS_VISIBLE+WS_CAPTION+WS_SYSMENU,\ 0,0,"Lucida Console",11 dialogitem 'BUTTON','Input',-1,7,5,346,150,BS_GROUPBOX+WS_VISIBLE,0 dialogitem 'BUTTON',"Output",-1,7,160,346,150,BS_GROUPBOX+WS_VISIBLE,0 dialogitem 'BUTTON',"Key",-1,7,315,220,90,BS_GROUPBOX+WS_VISIBLE,0 dialogitem 'EDIT',0,IDC_INPUT,13,17,335,130,ES_MULTILINE+ES_AUTOVSCROLL+ES_WANTRETURN+WS_VSCROLL+WS_BORDER+WS_VISIBLE,0 dialogitem 'EDIT',0,IDC_OUTPUT,13,172,335,130,ES_MULTILINE+ES_AUTOVSCROLL+ES_WANTRETURN+WS_VSCROLL+WS_BORDER+WS_VISIBLE,0 dialogitem 'EDIT',0,IDC_KEY,13,327,208,70,ES_MULTILINE+ES_AUTOVSCROLL+ES_WANTRETURN+WS_VSCROLL+WS_BORDER+WS_VISIBLE,0 dialogitem 'BUTTON',"Encrypt",IDC_BTN_ENCRYPT,231,319,60,14,BS_PUSHBUTTON+WS_VISIBLE,0 dialogitem 'BUTTON',"Decrypt",IDC_BTN_DECRYPT,293,319,60,14,BS_PUSHBUTTON+WS_VISIBLE,0 dialogitem 'BUTTON',"Input To Hex",IDC_BTN_TO_HEX,231,335,60,14,BS_PUSHBUTTON+WS_VISIBLE,0 dialogitem 'BUTTON',"Output To Text",IDC_BTN_TO_TXT,293,335,60,14,BS_PUSHBUTTON+WS_VISIBLE,0 dialogitem 'BUTTON',"Refresh Key",IDC_BTN_KEY,231,351,60,14,BS_PUSHBUTTON+WS_VISIBLE,0 dialogitem 'BUTTON',"Sub Keys",IDC_BTN_SUB_KEYS,293,351,60,14,BS_PUSHBUTTON+WS_VISIBLE,0 dialogitem 'BUTTON',"Clear",IDC_BTN_RESET,231,367,60,14,BS_PUSHBUTTON+WS_VISIBLE,0 enddialog ; ------------------------------------------------------------------------------------- ```