RC4 Verschlüsselung in MASM implementieren
-
Hallo! Ich bin Einsteiger im Gebiet von Assembler und möchte die RC4-Verschlüsselung implementieren.
[]0x1. Gibt es andere Möglichkeiten als Inline-Assembler zum Einfügen von Assembler in C/C++-Code?
[]0x2. Ist der Performancegewinn hoch?Ich kenne mich leider nur mit C/C++ aus, aber möchte den Teil in meinem C++ Projekt einfügen. Wie mache ich das und kennt jemand eine möglichst einfache Implementierung von RC4 in Asm? Meine IDE ist MS Visual C++ 2010, daher halte ich MASM für passend. Korrigiert mich, wenn ich falsch liege...
Bitte um Nachsicht, da ich erst ins Thema einsteige...
Danke.
-
Omicron schrieb:
[]0x1. Gibt es andere Möglichkeiten als Inline-Assembler zum Einfügen von Assembler in C/C++-Code?
[]0x2. Ist der Performancegewinn hoch?Ja, es gibt noch eine Möglichkeit. Du musst deine Funktion in Assembler implementieren, mit masm assemblieren und die resultierende Objektdatei mit deinem Programm verlinken. In deinem C/C++ Programm sagst du dann irgendwo
extern "C" void RC4_encode(...);
damit der Compiler weiss, wie die (externe) Funktion aussieht und das war's
Um die Frage mit der Performance zu beantworten, musst du deine Assembler-Funktion mit irgend einer anderen Funktion vergleichen können, sonst kannst du nicht einfach so behaupten, die Funktion sei in Assembler geschrieben, deshalb schneller als alles andere. Das wäre falsch.
Du musst eine zweite Funktion void RC_encode(...) rein in C/C++ implementieren, messen, wie schnell sie ist und die Ergebnisse mit deiner Assembler-Implementierung vergleichen.
-
.686 .model flat,stdcall option casemap:none RC4Init proto :DWORD,:DWORD RC4Encrypt proto :DWORD,:DWORD .data? align 4 rc4_key db 256 dup(?) rc4_x dd ? rc4_y dd ? .code align 4 RC4Init proc uses esi edi ebx pKey:DWORD,dwKeyLen:DWORD xor eax,eax mov ecx,256-16 mov rc4_x,eax mov rc4_y,eax mov esi,offset rc4_key mov edx,0FFFEFDFCh mov eax,0FBFAF9F8h mov ebx,0F7F6F5F4h mov edi,0F3F2F1F0h .repeat mov [esi+ecx+3*4],edx mov [esi+ecx+2*4],eax mov [esi+ecx+1*4],ebx mov [esi+ecx+0*4],edi sub edx,010101010h sub eax,010101010h sub ebx,010101010h sub edi,010101010h sub ecx,16 .until sign?;esi < offset rc4_key xor edx,edx xor ecx,ecx mov esi,pKey xor ebx,ebx mov edi,dwKeyLen .repeat @@: mov al,rc4_key[ecx] add dl,[esi+ebx] add dl,al mov ah,rc4_key[edx] inc ebx mov rc4_key[edx],al mov rc4_key[ecx],ah cmp ebx,edi jae @F inc cl jnz @B .break @@: xor ebx,ebx inc cl .until zero? ret RC4Init endp align 4 RC4Encrypt proc uses esi edi ebx pBlock:DWORD,dwBlockLen:DWORD mov edi,pBlock mov edx,rc4_x mov ecx,dwBlockLen mov ebx,rc4_y dec edi xor eax,eax .repeat add bl,rc4_key[edx+1] mov al,rc4_key[edx+1] mov ch,rc4_key[ebx] mov rc4_key[ebx],al mov rc4_key[edx+1],ch add al,ch inc edi mov al,rc4_key[eax] inc dl xor [edi],al dec cl .until zero? mov rc4_x,edx mov rc4_y,ebx ret RC4Encrypt endp RC4Decrypt equ <RC4Encrypt> end
Wie müsste ich das Extern bei dieser Implementierung aufrufen?
-
Bei den ganzen partiellen Registerzugriffen wird mir schlecht
Wie dem auch sei, bei RC4 ist so wie so die Geschwindigkeit des Datenträgers der limitierende Faktor.
-
Huh, dachte ich mir bei diesem Code auch gerade. Selbst die schlechteren aktuell verbreiteten C++-Compiler sollten wohl in der Lage sein, fuer eine gute Implementierung in C++ effizienteren Code zu generieren. Falls es dir wirklich um Geschwindigkeit dieses Codes geht (warum auch immer), such dir besser was anderes.
Prinzipiell sollte sich das aber mit einer extern-Deklaration wie
extern void RC4Encrypt (void* pBlock, uint32_t dwBlockLen);
aufrufen lassen...
-
Ich bräuchte eine Implementation, wobei mich ausschließlich die RC4 Verschlüsselungsfunktion interessiert. Also ein reines Rc4-Snippet, wenn man so will, sodass ich das vlt. auch inline in meinem C++ Code verwenden kann... Leider fand ich bisher nichts gescheites... Hat jemand eine Idee?!
Danke.
-
Darf ich fragen, warum die Funktion in Assembler sein muss... reicht die Performance der C oder C++ Implementierung nicht aus?
-
Weil ich zur Zeit mit Asm experimentiere.
-
Hier gibt es ausführliche Info: http://de.wikipedia.org/wiki/RC4#Algorithmus
Implementiere es in Assembler und poste den Quellcode deiner Funktion hier im Forum Wenn du es nicht machst, dann macht's auch keiner.
-
abc.w schrieb:
Wenn du es nicht machst, dann macht's auch keiner.
So, ich hab's gemacht und hier is mein Quellcode, habe ein wenig getestet, scheint so zu funktionieren und ich hoffe, habe keine Fehler eingebaut. Viel Spass damit.
.global rc4init # Constants for accessing function parameters on stack: # int rc4init(const char key[], size_t L, char sbox[]) .equ key, 4 .equ L, 8 .equ sbox, 12 # Constants for accessing local stack frame .equ saved_ebx, -4 .equ jcnt, -8 .equ icnt, -12 .equ kcnt, -16 .equ tmp, -20 .equ saved_esi, -28 .section .text rc4init: xorl %eax, %eax cmpl %eax, key(%esp) # Check for NULL pointer key[] je key_is_null cmpl $5, L(%esp) # Check for valid range of L jl L_range_wrong cmpl $256, L(%esp) jg L_range_wrong cmpl %eax, sbox(%esp) # Check for NULL pointer sbox[] je sbox_is_null movl %ebx, saved_ebx(%esp) # Save registers movl %esi, saved_esi(%esp) movl sbox(%esp), %ebx # Load address of sbox[0] movl key(%esp), %esi # Load address of key[0] movl $63, %ecx # Loop counter movl $0xFFFEFDFC, %eax # Contains initial value for sbox[] movl $0x04040404, %edx # Decrement value 0: # Loop for initializing sbox[] movl %eax, (%ebx, %ecx, 4) # Save new values in sbox[] subl %edx, %eax # Compute next values decl %ecx jnz 0b movl %eax, (%ebx) # Save rest values in sbox[] movl %ecx, jcnt(%esp) # Reset the counters i, j and k (use the movl %ecx, icnt(%esp) # loop counter, because it is zero here) movl %ecx, kcnt(%esp) 1: movzbl (%esi, %ecx), %eax # Load key[k] incl %ecx # Compute k = ((k + 1) mod L) cmpl %ecx, L(%esp) jl 2f xorl %ecx, %ecx 2: movl %ecx, kcnt(%esp) movl icnt(%esp), %ecx movzbl (%ebx, %ecx), %ecx # Load sbox[i] addl %eax, %ecx # Compute (sbox[i] + key[k]) addl jcnt(%esp), %ecx # Compute j = ((j + sbox[i] + key[k mod L]) mod 256) andl $0x000000FF, %ecx movl %ecx, jcnt(%esp) movl icnt(%esp), %eax movzbl (%ebx, %eax), %edx # Load sbox[i] and save it in tmp movl %edx, tmp(%esp) movzbl (%ebx, %ecx), %edx # Load sbox[j] and overwrite sbox[i] with it movb %dl, (%ebx, %eax) movl tmp(%esp), %edx # Load saved sbox[i] and overwrite sbox[j] with it movb %dl, (%ebx, %ecx) incl %eax movl kcnt(%esp), %ecx # Load k counter here, it will be used at top of the loop movl %eax, icnt(%esp) cmpl $256, %eax jb 1b movl saved_ebx(%esp), %ebx # Restore registers movl saved_esi(%esp), %esi xorl %eax, %eax # Return no errors ret key_is_null: movl $-1, %eax # Return error code ret L_range_wrong: movl $-2, %eax # Return error code ret sbox_is_null: movl $-3, %eax # Return error code ret
.global rc4run # Constants for accessing function parameters on stack: # int rc4run(const char buf_in[], size_t len, char buf_out[], char sbox[]) .equ buf_in, 4 .equ len, 8 .equ buf_out, 12 .equ sbox, 16 # Constants for accessing local stack frame .equ saved_ebx, -4 .equ saved_esi, -8 .equ saved_edi, -12 .equ jcnt, -16 .equ icnt, -20 .equ ncnt, -24 .equ tmp, -28 .section .text rc4run: xorl %eax, %eax cmpl %eax, buf_in(%esp) # Check for NULL pointer buf_in[] je buf_in_is_null cmpl %eax, buf_out(%esp) # Check for NULL pointer buf_out[] je buf_out_is_null cmpl %eax, sbox(%esp) # Check for NULL pointer sbox[] je sbox_is_null cmpl %eax, len(%esp) # Check for valid range of len je len_range_is_wrong movl %ebx, saved_ebx(%esp) # Save registers movl %esi, saved_esi(%esp) movl %edi, saved_edi(%esp) movl sbox(%esp), %ebx # Load address of sbox[0] movl buf_in(%esp), %esi # Load address of buf_in[0] movl buf_out(%esp), %edi # Load address of buf_out[0] movl %eax, icnt(%esp) # Reset the counters i, j and n movl %eax, jcnt(%esp) movl %eax, ncnt(%esp) 0: movl icnt(%esp), %eax # Compute i = ((i + 1) mod 256) incl %eax andl $0x000000FF, %eax movl %eax, icnt(%esp) movzbl (%ebx, %eax), %edx # Load sbox[i] and save it in tmp movl %edx, tmp(%esp) addl jcnt(%esp), %edx # Compute j = ((j + sbox[i]) mod 256) andl $0x000000FF, %edx movl %edx, jcnt(%esp) movzbl (%ebx, %edx), %ecx # Load sbox[j] and overwrite sbox[i] with it movb %cl, (%ebx, %eax) movl %ecx, %eax movl tmp(%esp), %ecx # Load saved value sbox[i] and overwrite sbox[j] with it movb %cl, (%ebx, %edx) addl %ecx, %eax # Compute index = ((sbox[i] + sbox[j]) mod 256) andl $0x000000FF, %eax movzbl (%ebx, %eax), %ecx # Load sbox[index], this is a new random number movl ncnt(%esp), %eax # Load buf_in[n] movzbl (%esi, %eax), %edx xorl %ecx, %edx # Encrypt movb %dl, (%edi, %eax) # Save new encrypted value in buf_out[n] incl %eax # Compute n = (n + 1) and check, end of buf_in[] reached or not movl %eax, ncnt(%esp) cmpl len(%esp), %eax jb 0b movl saved_ebx(%esp), %ebx # Restore registers movl saved_esi(%esp), %esi movl saved_edi(%esp), %edi xorl %eax, %eax # Return no errors ret buf_in_is_null: movl $-1, %eax # Return error code ret buf_out_is_null: movl $-2, %eax # Return error code ret sbox_is_null: movl $-3, %eax # Return error code ret len_range_is_wrong: movl $-4, %eax # Return error code ret
Die beiden Funktionen sehen so aus:
int rc4init(const char key[], size_t L, char sbox[]); int rc4run(const char buf_in[], size_t len, char buf_out[], char sbox[]);