RC4 bzw. PureBasic vs PHP

Für allgemeine Fragen zur Programmierung mit PureBasic.
Benutzeravatar
coder
Beiträge: 204
Registriert: 25.09.2005 17:53
Computerausstattung: Intel Core2Quad Q8200 @ 2.33GHz
ASUS P5Q3, 2GB DDR3-1066 RAM, ATi Raedeon HD 4850
Wohnort: Deutschland
Kontaktdaten:

RC4 bzw. PureBasic vs PHP

Beitrag von coder »

Hallo,

Ich bastel zur Zeit an einem kleinen Projekt, was über curl mit einem PHP-Script auf einem Webserver kommunizieren soll, um ein mindest Maß an Sicherheit zu gewährleisten brauche ich eine simple und zügige Verschlüsselung. Dazu hab ich den RC4 implementiert, der auf beiden Seiten für sich genommen auch ohne Probleme funktioniert. Das Problem dabei ist jetzt nur, dass ja beide Codes das selbe Ergebnis produzieren müssen und da steh ich so'n bisschen auf dem Schlauch...

Die Ausgaben sehen wie folgt aus:
PHP:

Code: Alles auswählen

The quick brown fox jumps over the lazy dog.
aohDrcAggE9z7xeFyi0JzM2K9m3ddmtjReAaqneYc49vKgcezOmGx+8t5T0=
6a 88 43 ad c0 20 80 4f 73 ef 17 85 ca 2d 9 cc cd 8a f6 6d dd 76 6b 63 45 e0 1a aa 77 98 73 8f 6f 2a 7 1e cc e9 86 c7 ef 2d e5 3d
The quick brown fox jumps over the lazy dog.

PureBasic:

Code: Alles auswählen

The quick brown fox jumps over the lazy dog.
+ba+j5yAlPz4bExp5EGPB/7d9XlsoB2lgfoaFoBPHofLIMuzxNF2xlGqZQw=
F9 B6 BE 8F 9C 80 94 FC F8 6C 4C 69 E4 41 8F 7 FE DD F5 79 6C A0 1D A5 81 FA 1A 16 80 4F 1E 87 CB 20 CB B3 C4 D1 76 C6 51 AA 65 C 4 
The quick brown fox jumps over the lazy dog.
Hier nun der Code, für PureBasic hab ich die sha256 Routine von Helle verwendet (http://www.purebasic.fr/german/viewtopi ... =8&t=24669)
PureBasic:

Code: Alles auswählen

XIncludeFile "sha256.pbi"

Structure memarray
  StructureUnion
    a.a[0]
    b.b[0]
  EndStructureUnion
EndStructure

Procedure encrypt( *Input.memarray, InputSize, *Output.memarray, *Key, KeySize )
  Protected hash$
  Protected hashlen, x, j, i, n, z
  Protected *hash.memarray, *sbox.memarray
  
  ; RC4 mit s-box aus sha256
  hash$ = SHA256Fingerprint_32( *Key, KeySize )
  
  hashlen = StringByteLength( hash$ )
  *hash = AllocateMemory( hashlen + 1)
  PokeS(*hash, hash$, hashlen )
  
  ; S-Box erstellen
  *sbox = AllocateMemory( 256 )
  For i = 0 To 255 Step 1
    *sbox\a[i] = i
  Next
  
  ; Permutation der S-Box
  x = 0 : j = 0 : i = 0
  For i = 0 To 255 Step 1
    j = ( j + *sbox\a[i] + *hash\a[i % hashlen] ) % 256
    x = *sbox\a[i] : *sbox\a[i] = *sbox\a[j] : *sbox\a[j] = x    ; Verstauschen von s[i] und s[j]
  Next
  
  ; Berchnung der Zufallsfolge - Verschlüsselung
  For n = 0 To InputSize Step 1
    i = (i + 1) % 256
    j = (j + *sbox\a[i]) % 256
    x = *sbox\a[i] : *sbox\a[i] = *sbox\a[j] : *sbox\a[j] = x    ; Verstauschen von s[i] und s[j]
    z = (*sbox\a[i] + *sbox\a[j]) % 256       ; Zufallszahl berechnen
    *Output\a[n] = *Input\a[n] ! z    ; XOR
  Next
  
  FreeMemory( *hash )
  FreeMemory( *sbox )
  
  ProcedureReturn #True
  
EndProcedure

Procedure decrypt( *Input.memarray, InputSize, *Output.memarray, *Key, KeySize )
  
  ProcedureReturn encrypt( *Input, InputSize, *Output, *Key, KeySize )
  
EndProcedure


; #size = 1024
; key$ = "blubber"
; 
; base64$ = Space(#size * 1.4)
; *mem = AllocateMemory(#size)
; *crypt = AllocateMemory(#size)
; *mem2 = AllocateMemory(#size)
; 
; RandomData( *mem, #size )
; Base64Encoder( *mem, #size, @base64$, StringByteLength(base64$) )
; Debug base64$
; 
; encrypt( *mem, #size, *crypt, @key$, StringByteLength(key$) )
; base64$ = Space(#size * 1.4)
; Base64Encoder( *crypt, #size, @base64$, StringByteLength(base64$) )
; Debug base64$
; 
; decrypt( *crypt, #size, *mem2, @key$, StringByteLength(key$) )
; base64$ = Space(#size * 1.4)
; Base64Encoder( *mem2, #size, @base64$, StringByteLength(base64$) )
; Debug base64$
; 
; FreeMemory(*mem)
; FreeMemory(*crypt)
; FreeMemory(*mem2)
; 
; ; -----------------------------------------------------------------------------
; Debug ""
; Debug "--------"
; Debug ""

key$ = "flubber"
string$ = "The quick brown fox jumps over the lazy dog."
size = StringByteLength( string$ )

base64$ = Space(size * 1.4)
string2$ = Space(size)
*crypt.memarray = AllocateMemory(size)

Debug string$

encrypt( @string$, size, *crypt, @key$, StringByteLength(key$) )
Base64Encoder( *crypt, size, @base64$, StringByteLength(base64$) )
Debug base64$

hex$ = ""
For i = 0 To size
  hex$ + Hex( *crypt\a[i] ) + " "
Next
Debug hex$

decrypt( *crypt, size, @string2$, @key$, StringByteLength(key$) )
Debug string2$
PHP:

Code: Alles auswählen

<?php
/**
 * Verschlüsselt einen String
 * @param String $string
 * @param String $key Der Schlüssel
 */
function encrypt( $string, $key ) {
	$hash = hash( 'sha256', $key );
	$hashlen = strlen( $hash );
	$stringlen = strlen( $string );
	// RC4 mit s-box aus sha256
	
	// S-Box erstellen
	$s = array();
	for( $i = 0; $i<256; $i++ ) {
		$s[$i] =  $i;
	}
	
	// Permutation der S-Box
	$x = 0; $j = 0;
	for( $i = 0; $i<256; $i++ ) {
		$j = ( $j + $s[$i] + ord( $hash[$i % $hashlen] ) ) % 256;
		$x = $s[$i]; $s[$i] = $s[$j]; $s[$j] = $x;		// Vertausche s[i] mit s[j]
	}
	
	// "Berechnung der Zufallsfolge" - Verschlüsselung
	$return = '';
	for( $n = 0; $n < $stringlen; $n++ ) {
		$i = ($i + 1) % 256;
		$j = ($j + $s[$i]) & 256;
		$x = $s[$i]; $s[$i] = $s[$j]; $s[$j] = $x;		// Vertausche s[i] mit s[j]
		$zufallszahl = ($s[$i] + $s[$j]) % 256;		// Zufallszahl berechnen
		$return .= $string[$n] ^ chr( $zufallszahl );
	}
	return $return;
}

/**
 * Entschlüsselt einen String
 * @param String $string
 * @param String $key
 */
function decrypt( $string, $key ) {
	return encrypt( $string, $key );
}

$string = "The quick brown fox jumps over the lazy dog.";
$key = "flubber";
$crypt = encrypt( $string, $key );
echo $string . "<br />\n";
echo base64_encode( $crypt ) . "<br />\n";
$cryptlen = strlen( $crypt );
for( $i = 0; $i < $cryptlen; $i++ ) {
	echo dechex( ord( $crypt[$i] ) ) . ' ';
}
echo "<br />\n";
echo decrypt( $crypt, $key );
?>
Windows 7 x64 | PureBasic 4.60 4.50 4.02
Ja verdammt, meine Eltern wohnen immer noch bei mir!
jamirokwai
Beiträge: 65
Registriert: 02.06.2008 16:10

Re: RC4 bzw. PureBasic vs PHP

Beitrag von jamirokwai »

Hi Coder,

hab' leider nicht so viel Ahnung von Verschlüsselung und so, aber ich brauchte auch mal RC4 für ein Projekt in PHP und PB. Versuch' mal ob dieses Skript (als Beispiel) das gleiche Ergebnis wie Dein PB-Code gibt:

http://phpseclib.sourceforge.net/

Eigentlich dürfte bei gleichem Verfahren ja nichts unterschiedliches Rauskommen!?

Grüßle
J.
Benutzeravatar
HeX0R
Beiträge: 3040
Registriert: 10.09.2004 09:59
Computerausstattung: AMD Ryzen 7 5800X
96Gig Ram
NVIDIA GEFORCE RTX 3060TI/8Gig
Win11 64Bit
G19 Tastatur
2x 24" + 1x27" Monitore
Glorious O Wireless Maus
PB 3.x-PB 6.x
Oculus Quest 2 + 3
Kontaktdaten:

Re: RC4 bzw. PureBasic vs PHP

Beitrag von HeX0R »

RC4 für Windows gibts auch hier.
(Oder inkl. base64 hier)
Benutzeravatar
coder
Beiträge: 204
Registriert: 25.09.2005 17:53
Computerausstattung: Intel Core2Quad Q8200 @ 2.33GHz
ASUS P5Q3, 2GB DDR3-1066 RAM, ATi Raedeon HD 4850
Wohnort: Deutschland
Kontaktdaten:

Re: RC4 bzw. PureBasic vs PHP

Beitrag von coder »

Hmm, ich muss zugeben an das englische Forum hab ich noch nicht gedacht -.-
Aber Windows-Api ist leider keine Alternative für mich, da das ganze später auch auf Linux laufen soll/muss

@jamirokwai:
Danke für den Link, ich habs mal getestet und jetzt hab ich eine dritte Variante :mrgreen:

Also aus dem Bauch raus würde ich den Fehler im PureBasic Code vermuten, oder aber in den Wirren der Zeichsätze...
Windows 7 x64 | PureBasic 4.60 4.50 4.02
Ja verdammt, meine Eltern wohnen immer noch bei mir!
Dark
Beiträge: 93
Registriert: 24.08.2007 20:36
Kontaktdaten:

Re: RC4 bzw. PureBasic vs PHP

Beitrag von Dark »

Hi,

dein PB und PHP Code ist fast richtig, es gibt jedoch 3 kleine Fehler.

1. SHA256Fingerprint_32 liefert den Hash in Großbuchstaben, die PHP Hash Funktion jedoch als Kleinbuchstaben, also muss es folgendermaßen abgeändert werden:

Code: Alles auswählen

hash$ = LCase(SHA256Fingerprint_32( *Key, KeySize ))
2. Du hast einen Fehler im PHP Code und zwar hast du an einer Stelle & 256 anstatt % 256

Code: Alles auswählen

$j = ($j + $s[$i]) & 256 //<-- hier muss ein % hin!
3. Du gibst ein Zeichen zu viel aus bei der Hex Ausgabe, so wäre es richtig:

Code: Alles auswählen

For i = 0 To size - 1
Nun liefern beide Codes das selbe Ergebnis.

Mfg,
Dark
Zuletzt geändert von Dark am 05.03.2012 13:16, insgesamt 2-mal geändert.
Sirius-2337
Beiträge: 71
Registriert: 29.05.2010 20:55

Re: RC4 bzw. PureBasic vs PHP

Beitrag von Sirius-2337 »

Kleiner Hiweis:

Dieser Code lässt sich etwas kürzer Schreiben

Code: Alles auswählen

x = *sbox\a[i] : *sbox\a[i] = *sbox\a[j] : *sbox\a[j] = x    ; Verstauschen von s[i] und s[j]
undzwar so:

Code: Alles auswählen

swap *sbox\a[i], *sbox\a[j]
Benutzeravatar
coder
Beiträge: 204
Registriert: 25.09.2005 17:53
Computerausstattung: Intel Core2Quad Q8200 @ 2.33GHz
ASUS P5Q3, 2GB DDR3-1066 RAM, ATi Raedeon HD 4850
Wohnort: Deutschland
Kontaktdaten:

Re: RC4 bzw. PureBasic vs PHP

Beitrag von coder »

@Dark: Ach, ich danke dir :)
Werd das nachher gleich mal testen

@Sirius-2337: Danke für den Tipp, wird auch gleich eingebaut
Windows 7 x64 | PureBasic 4.60 4.50 4.02
Ja verdammt, meine Eltern wohnen immer noch bei mir!
Dark
Beiträge: 93
Registriert: 24.08.2007 20:36
Kontaktdaten:

Re: RC4 bzw. PureBasic vs PHP

Beitrag von Dark »

Mir ist noch ein kleiner Fehler in deinem Code aufgefallen. Die Zufallszahl die du berechnest ist im Original RC4 Algorithmus ein Index zu einem Element in der Sbox. Du müsstest es also in PB4 (und entsprechend auch in PHP) so abändern:

Code: Alles auswählen

z = *sbox\a[(*sbox\a[i] + *sbox\a[j]) % 256]
Es wäre natürlich auch gut wenn du überprüfst ob der Speicher überhaupt reserviert wurde. :wink:
Und wenn es schon um Optimierung geht, könntest du i, j auch als Unsigned Byte (.a) deklarieren und dir an vielen Stellen das % 256 sparen.
Dann würde z.B. aus

Code: Alles auswählen

i = (i + 1) % 256
einfach

Code: Alles auswählen

i + 1
Dark
Benutzeravatar
coder
Beiträge: 204
Registriert: 25.09.2005 17:53
Computerausstattung: Intel Core2Quad Q8200 @ 2.33GHz
ASUS P5Q3, 2GB DDR3-1066 RAM, ATi Raedeon HD 4850
Wohnort: Deutschland
Kontaktdaten:

Re: RC4 bzw. PureBasic vs PHP

Beitrag von coder »

Tut mir Leid, dass ich mich jetzt erst wieder melde, aber Klausuren und Schule haben doch momentan etwas vorrang. Aufjedenfall läuft es jetzt einwandfrei :)
Nochmal Danke euch beiden und hier die korriegierten Funktionen, falls es mal jemand brauchen kann:

PureBasic:

Code: Alles auswählen

Structure memarray
  StructureUnion
    a.a[0]
    b.b[0]
  EndStructureUnion
EndStructure

Procedure encrypt( *Input.memarray, InputSize, *Output.memarray, *Key, KeySize )
  Protected hash$
  Protected hashlen, x, j, i, n, z
  Protected *hash.memarray, *sbox.memarray
  
  ; RC4 mit s-box aus sha256
  hash$ = LCase(SHA256Fingerprint_32( *Key, KeySize ))
  
  hashlen = StringByteLength( hash$ )
  *hash = AllocateMemory( hashlen + 1)
  PokeS(*hash, hash$, hashlen )
  
  ; S-Box erstellen
  *sbox = AllocateMemory( 256 )
  For i = 0 To 255 Step 1
    *sbox\a[i] = i
  Next
  
  ; Permutation der S-Box
  x = 0 : j = 0 : i = 0
  For i = 0 To 255 Step 1
    j = ( j + *sbox\a[i] + *hash\a[i % hashlen] ) % 256
    ;x = *sbox\a[i] : *sbox\a[i] = *sbox\a[j] : *sbox\a[j] = x
    Swap *sbox\a[i], *sbox\a[j]    ; Verstauschen von s[i] und s[j]
  Next
  
  ; Berchnung der Zufallsfolge - Verschlüsselung
  For n = 0 To InputSize Step 1
    i = (i + 1) % 256
    j = (j + *sbox\a[i]) % 256
    Swap *sbox\a[i], *sbox\a[j]    ; Verstauschen von s[i] und s[j]
    z = *sbox\a[(*sbox\a[i] + *sbox\a[j]) % 256]    ; Zufallszahl berechnen
    *Output\a[n] = *Input\a[n] ! z    ; XOR
  Next
  
  FreeMemory( *hash )
  FreeMemory( *sbox )
  
  ProcedureReturn #True
  
EndProcedure
PHP:

Code: Alles auswählen

/**
 * Verschlüsselt einen String
 * @param String $string
 * @param String $key Der Schlüssel
 */
function encrypt( $string, $key ) {
	$hash = strtolower(hash( 'sha256', $key ));
	$hashlen = strlen( $hash );
	$stringlen = strlen( $string );
	// RC4 mit s-box aus sha256
	
	// S-Box erstellen
	$s = array();
	for( $i = 0; $i<256; $i++ ) {
		$s[$i] =  $i;
	}
	
	// Permutation der S-Box
	$x = 0; $j = 0;
	for( $i = 0; $i<256; $i++ ) {
		$j = ( $j + $s[$i] + ord( $hash[$i % $hashlen] ) ) % 256;
		$x = $s[$i]; $s[$i] = $s[$j]; $s[$j] = $x;		// Vertausche s[i] mit s[j]
	}
	
	// "Berechnung der Zufallsfolge" - Verschlüsselung
	$return = '';
	for( $n = 0; $n < $stringlen; $n++ ) {
		$i = ($i + 1) % 256;
		$j = ($j + $s[$i]) % 256;
		$x = $s[$i]; $s[$i] = $s[$j]; $s[$j] = $x;		// Vertausche s[i] mit s[j]
		$zufallszahl = $s[($s[$i] + $s[$j]) % 256];		// Zufallszahl berechnen
		$return .= $string[$n] ^ chr( $zufallszahl );
	}
	return $return;
}
Windows 7 x64 | PureBasic 4.60 4.50 4.02
Ja verdammt, meine Eltern wohnen immer noch bei mir!
Dark
Beiträge: 93
Registriert: 24.08.2007 20:36
Kontaktdaten:

Re: RC4 bzw. PureBasic vs PHP

Beitrag von Dark »

Hier noch mal eine Version ohne die ganzen Modulos (die man besser auch als "& 255" schreiben sollte, da der CPU einfache Bitmanipulationen schneller berechnen kann als Divisionen):

Code: Alles auswählen

Structure memarray
  a.a[0]
EndStructure
  
Structure SBOX
  a.a[256]
EndStructure

Procedure RC4_PB( *Input.memarray, InputSize, *Output.memarray, *Key.memarray, KeySize )
  
  Protected sbox.SBOX, j.a = 0, i.a, z.a
  
  For i = 0 To 255 
    sbox\a[i] = i
  Next
  
  For i = 0 To 255
    j + sbox\a[i] + *Key\a[i % KeySize]
    Swap sbox\a[i], sbox\a[j]
  Next
  
  j = 0 : i = 0
  For n = 0 To InputSize
    i + 1
    j + sbox\a[i]
    Swap sbox\a[i], sbox\a[j]
    z = sbox\a[(sbox\a[i] + sbox\a[j]) & 255]   
    *Output\a[n] = *Input\a[n] ! z 
  Next

EndProcedure

Procedure encrypt( *Input.memarray, InputSize, *Output.memarray, *Key, KeySize )
  Protected hash$
  
  hash$ = LCase(SHA256Fingerprint_32( *Key, KeySize ))

  RC4_PB(*Input, InputSize, *Output, @hash$, StringByteLength(hash$))

EndProcedure
Dark
Antworten