Seite 1 von 1

RC4 bzw. PureBasic vs PHP

Verfasst: 04.03.2012 13:30
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 );
?>

Re: RC4 bzw. PureBasic vs PHP

Verfasst: 04.03.2012 13:38
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.

Re: RC4 bzw. PureBasic vs PHP

Verfasst: 04.03.2012 13:45
von HeX0R
RC4 für Windows gibts auch hier.
(Oder inkl. base64 hier)

Re: RC4 bzw. PureBasic vs PHP

Verfasst: 04.03.2012 13:54
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...

Re: RC4 bzw. PureBasic vs PHP

Verfasst: 04.03.2012 20:50
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

Re: RC4 bzw. PureBasic vs PHP

Verfasst: 04.03.2012 22:11
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]

Re: RC4 bzw. PureBasic vs PHP

Verfasst: 05.03.2012 19:22
von coder
@Dark: Ach, ich danke dir :)
Werd das nachher gleich mal testen

@Sirius-2337: Danke für den Tipp, wird auch gleich eingebaut

Re: RC4 bzw. PureBasic vs PHP

Verfasst: 05.03.2012 21:08
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

Re: RC4 bzw. PureBasic vs PHP

Verfasst: 10.03.2012 17:19
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;
}

Re: RC4 bzw. PureBasic vs PHP

Verfasst: 10.03.2012 18:00
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