Aus Langeweile und ggf. für spätere Projekte (yafu2) habe ich mir dieses Wochenende eine RC4-Implementation für PHP gebastelt.
Solche gibt es zwar bereits einige, doch wollte ich eine Implementation die Public Domain, also gemeinfrei, ist. Zudem ist meine Implementation nicht eine Verschlüsselungsfunktion, sondern eine PHP-Streamklasse, das eigentliche Verknüpfen der Daten müsst ihr selber vornehmen.
Die Funktionsweise von RC4 ist in der Wikipedia nachzulesen, wichtig zu wissen ist eigentlich nur, dass RC4 eine Stromchiffre ist und somit unendlich lange Chiffren erzeugt, die man danach mit seinen Daten XOR-Verknüpfen kann.
Wem das jetzt zu verwirrend ist, der schaue sich folgendes Code-Schnippsel an:
Beispielcode:
/* Klasse als Streaming-Protokoll registrieren */
stream_wrapper_register("rc4", "RC4Stream");
/* Stream öffnen */
$rc4Stream = fopen("rc4://geheimerSchluessel", "r");
/* Klartext definieren */
$plainText = "Dies ist ein streng geheimer Satz.";
echo("Klartext: ".$plainText."\n");
/* Chiffrenstrom für die Länge des Klartextes holen */
$cipherStream = fread($rc4Stream, strlen($plainText));
/* Die beiden Strings verknüpfen und somit den Text verschlüsseln */
$encryptedText = $plainText ^ $cipherStream;
echo("Verschlüsselter Text (hexdezimal): ".bin2hex($encryptedText)."\n");
/* Das ganze noch einmal um den Text wieder zu entschlüsseln */
$plainText = $encryptedText ^ $cipherStream;
echo("Klartext: ".$plainText."\n");
/* Bonus: Anzeige, wie viele Bytes an Chiffren bereits generiert wurde */
echo("Bisherige Stromlänge: ".ftell($rc4Stream));
/* Stream schliessen */
fclose($rc4Stream);
Alles anzeigen
Ausgabe:
ZitatKlartext: Dies ist ein streng geheimer Satz.Verschlüsselter Text (hexdezimal): dfeea1f9556672672f...32ebd1Klartext: Dies ist ein streng geheimer Satz.Bisherige Stromlänge: 34
Das Password wird via fopen() mitgeteilt und mit fread() enthält man dann die Stromchiffre. Funktionen wie fwrite() oder feof() funktionieren selbstverständlich nicht, da der Strom unendlich und unveränderlich sein muss.
Hier die Klasse als PHP-Code:
Spoiler anzeigen
<?php
class RC4Stream {
var $key;
var $box;
var $count;
function stream_open($path, $mode, $options, &$opened_path) {
$url = parse_url($path);
$keyphrase = str_split($url["host"]);
$this->box = range(0, 255);
$this->count = 0;
for($i = $j = 0; $i < 256; $i++) {
$this->key[$i] = ord($keyphrase[$i % count($keyphrase)]);
$j = ($j + $this->box[$i] + $this->key[$i]) % 256;
/* swap'em */
$this->box[$i] ^= $this->box[$j] ^= $this->box[$i] ^= $this->box[$j];
}
return true;
}
function stream_read($count) {
$tmpCipher = '';
static $i = 0;
static $j = 0;
for($k = 0; $k < $count; $k++) {
$i = ($i + 1) % 256;
$j = ($j + $this->box[$i]) % 256;
$this->box[$i] ^= $this->box[$j] ^= $this->box[$i] ^= $this->box[$j];
$tmpCipher .= chr($this->box[($this->box[$i] + $this->box[$j]) % 256]);
$this->count++;
}
return $tmpCipher;
}
function stream_eof() {
return false;
}
function stream_flush() {
return false;
}
function stream_seek($offset, $whence) {
return false;
}
function stream_tell() {
return $this->count;
}
function stream_write($data) {
return 0;
}
}
?>
Alles anzeigen