Um Scripts man-in-the-middle-sicher zu machen, habe ich einen symmetrischen Verschlüsselungsalgorithmus entwickelt, der POST-Variable ermöglicht, die nicht so einfach zu entschlüsseln sind (ohne Kenntnis des Schlüssels eigentlich überhaupt nicht).
Mich interessiert es, ob es Experten gibt, die die Schwachstellen dieses Verfahrens nennen können.
Das Prinzip besteht aus einer mehrfachen Codierung des zu verschlüsselnden Strings. Aus dem Schlüssel wird ein MD5 Hash gebildet, der als Schlüssel für die zweite Stufe verwendet wird.
Weiterhin wird der Schlüssel reversiert und dieser Schlüssel wird als dritter Schlüssel verwendet.
Um die Sicherheit weiter zu erhöhen, werden zwei Zufallszahlen gebildet. Die erste ist zwischen 1 und der Länge des Schlüssels, die zweite zwischen 1 und 32. Mit Hilfe dieser Zufallszahlen werden die Schlüssel modifiziert.
Wenn beispielsweise der Schlüssel 50 Stellen hat und die erste Zufallszahl 18 ist, dann wird der verwendete Schlüssel aus Position 18-50 und aus Position 1-17 zusammen gesetzt. Das gleiche gilt für den zweiten Schlüssel mit Zufallszahl 2 und den dritten Schlüssel auch mit Zufallszahl 2.
Die beiden Zufallszahlen werden in das Chiffrat eingebaut.
Es wird noch eine Prüfziffer aus einem MD5-Hash des Ergebnisses gebildet und in das Chiffrat eingebaut. Wenn ein Angebot im TryAndError-Verfahren versuchen sollte, die Auswirkungen auf Manipulationen des Chiffrats zu erforschen, so bekommt er kein Ergebnis zurück, weil die Prüfziffernfolge nicht mehr stimmt.
Das Ergebnis wird base32-codiert, so dass das Chiffrat nur aus Ziffern und Kleinbuchstaben besteht. Eine weitere base64- oder URL-Codierung ist demnach nicht erforderlich.
Aus meiner Sicht ist durch die Schlüssel-Länge und die durch Zufallszahlen gesteuerte Vervielfachung der möglichen Schlüssel in Kombination mit der dreistufigen Verschlüsselung ein Knacken der Chiffrate eigentlich unmöglich. Aber vielleicht habe ich ja einen Denkfehler dabei und jemand kann mir helfen, diesen zu finden.
Im Übrigen stelle ich die Funktion über die GNU-Lizenz für jedermann zur freien Verfügung.
Für den Ablauf werden die Funktionen base32_encode und base32_decode verwendet:
Mich interessiert es, ob es Experten gibt, die die Schwachstellen dieses Verfahrens nennen können.
Das Prinzip besteht aus einer mehrfachen Codierung des zu verschlüsselnden Strings. Aus dem Schlüssel wird ein MD5 Hash gebildet, der als Schlüssel für die zweite Stufe verwendet wird.
Weiterhin wird der Schlüssel reversiert und dieser Schlüssel wird als dritter Schlüssel verwendet.
Um die Sicherheit weiter zu erhöhen, werden zwei Zufallszahlen gebildet. Die erste ist zwischen 1 und der Länge des Schlüssels, die zweite zwischen 1 und 32. Mit Hilfe dieser Zufallszahlen werden die Schlüssel modifiziert.
Wenn beispielsweise der Schlüssel 50 Stellen hat und die erste Zufallszahl 18 ist, dann wird der verwendete Schlüssel aus Position 18-50 und aus Position 1-17 zusammen gesetzt. Das gleiche gilt für den zweiten Schlüssel mit Zufallszahl 2 und den dritten Schlüssel auch mit Zufallszahl 2.
Die beiden Zufallszahlen werden in das Chiffrat eingebaut.
Es wird noch eine Prüfziffer aus einem MD5-Hash des Ergebnisses gebildet und in das Chiffrat eingebaut. Wenn ein Angebot im TryAndError-Verfahren versuchen sollte, die Auswirkungen auf Manipulationen des Chiffrats zu erforschen, so bekommt er kein Ergebnis zurück, weil die Prüfziffernfolge nicht mehr stimmt.
Das Ergebnis wird base32-codiert, so dass das Chiffrat nur aus Ziffern und Kleinbuchstaben besteht. Eine weitere base64- oder URL-Codierung ist demnach nicht erforderlich.
Aus meiner Sicht ist durch die Schlüssel-Länge und die durch Zufallszahlen gesteuerte Vervielfachung der möglichen Schlüssel in Kombination mit der dreistufigen Verschlüsselung ein Knacken der Chiffrate eigentlich unmöglich. Aber vielleicht habe ich ja einen Denkfehler dabei und jemand kann mir helfen, diesen zu finden.
Im Übrigen stelle ich die Funktion über die GNU-Lizenz für jedermann zur freien Verfügung.
<?php
/* PHP function brbcrypt Copyright (C) 2018 Bernhard Blasen
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Don't remove this text from source code if you distribute it
*/
////////////////////////////////////////////////////////////////////////////////////////
// Aufruf: «returnstring» = brbcrypt(«key», «value», «"encode"|"decode"»);
// Achtung!!!!!
////////////////////////////////////////////////////////////////////////////////////////
if ( ! function_exists("base32_encode")) {
include("base32.php");
}
if ( ! function_exists("brbcrypt")) {
function brbcrypt($key, $text, $direction) {
$text_sv = $text;
$l_k = strlen($key);
if($l_k == 0) { // Ohne Key keine Verschlüsselung!!!
return $text;
}
$key2 = md5($key);
$key3 = strrev($key);
$l_t = strlen($text);
$rettext = "";
$rettext_u = "";
$k = 0; // Position im Key
$k2 = 0; // Position in Key2
if ($direction != "encode") {
$text = substr($text,0,3) . base32_decode(substr($text,3,strlen($text)-3));
$md = substr($text,6,4);
$text = substr($text,0,6).substr($text,9,$l_t - 9);
$k = ord(substr($text,4,1)) - 64;
$k2 = ord(substr($text,5,1)) - 64;
$text = substr($text,3,1).substr($text,7,$l_t - 9);
if ($md != substr(md5($text),0,4)) {
return false;
}
$l_t = strlen($text);
} else {
$k = mt_rand(1,$l_k);
while ($k > 23 && $k < 33) {
$k = $k - mt_rand(10,23);
}
if ($k < 1) { $k = $k + mt_rand(1,3); }
if ($k > 56) { $k = $k - mt_rand(10,40); }
if ($k > 25 && $k < 34) { $k = $k / 2 ; }
if ($k2 < 1) { $k2 = $k2 + mt_rand(1,3); }
if ($k2 > 58) { $k2 = $k2 - mt_rand(8,50); }
$k2 = mt_rand(1,32);
while ($k2 > 23) {
$k2 = $k2 - mt_rand(1,23);
}
}
if ($k > $k2) {
$k3 = $k2;
} else {
$k3 = $k;
}
$k_save = $k;
$k2_save = $k2;
for($i_text = 0; $i_text < $l_t; $i_text++) {
if($k > $l_k-1) {$k = 0;} // Wenn ende des keys, dann wieder von vorne
if($k2 > strlen($key2)) {$k2 = 0;} // Wenn ende des keys, dann wieder von vorne
if ( $direction == "encode" ) {
$z=ord(substr($text,$i_text,1))+ord(substr($key,$k,1));
if ( $z > 255 ) {
$z=$z-256;
}
$z = $z+ord(substr($key2,$k2,1));
if ( $z > 255 ) {
$z=$z-256;
}
$z = $z+ord(substr($key3,$k3,1));
if ( $z > 255 ) {
$z=$z-256;
}
} else {
if ( ord(substr($text,$i_text,1)) < ord(substr($key3,$k3,1)) ) {
$z = ord(substr($text,$i_text,1)) + 256 - ord(substr($key3,$k3,1));
} else {
$z = ord(substr($text,$i_text,1)) - ord(substr($key3,$k3,1));
}
if ( $z < ord(substr($key2,$k2,1)) ) {
$z = $z + 256 - ord(substr($key2,$k2,1));
} else {
$z = $z - ord(substr($key2,$k2,1));
}
if ( $z < ord(substr($key,$k,1)) ) {
$z = $z + 256 - ord(substr($key,$k,1));
} else {
$z = $z - ord(substr($key,$k,1));
}
}
$rettext.= chr($z); // Verschlüsselung
$k++;
$k2++;
}
if ($direction == "encode") {
$md = substr(md5($rettext),0,4);
$x = substr($rettext,0,1).chr($k_save + 64).chr($k2_save + 64).$md.substr($rettext,1,strlen($rettext) - 1);
return "bv3" . base32_encode($x);
} else {
return $rettext;
}
}
}
?>
/* PHP function brbcrypt Copyright (C) 2018 Bernhard Blasen
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Don't remove this text from source code if you distribute it
*/
////////////////////////////////////////////////////////////////////////////////////////
// Aufruf: «returnstring» = brbcrypt(«key», «value», «"encode"|"decode"»);
// Achtung!!!!!
////////////////////////////////////////////////////////////////////////////////////////
if ( ! function_exists("base32_encode")) {
include("base32.php");
}
if ( ! function_exists("brbcrypt")) {
function brbcrypt($key, $text, $direction) {
$text_sv = $text;
$l_k = strlen($key);
if($l_k == 0) { // Ohne Key keine Verschlüsselung!!!
return $text;
}
$key2 = md5($key);
$key3 = strrev($key);
$l_t = strlen($text);
$rettext = "";
$rettext_u = "";
$k = 0; // Position im Key
$k2 = 0; // Position in Key2
if ($direction != "encode") {
$text = substr($text,0,3) . base32_decode(substr($text,3,strlen($text)-3));
$md = substr($text,6,4);
$text = substr($text,0,6).substr($text,9,$l_t - 9);
$k = ord(substr($text,4,1)) - 64;
$k2 = ord(substr($text,5,1)) - 64;
$text = substr($text,3,1).substr($text,7,$l_t - 9);
if ($md != substr(md5($text),0,4)) {
return false;
}
$l_t = strlen($text);
} else {
$k = mt_rand(1,$l_k);
while ($k > 23 && $k < 33) {
$k = $k - mt_rand(10,23);
}
if ($k < 1) { $k = $k + mt_rand(1,3); }
if ($k > 56) { $k = $k - mt_rand(10,40); }
if ($k > 25 && $k < 34) { $k = $k / 2 ; }
if ($k2 < 1) { $k2 = $k2 + mt_rand(1,3); }
if ($k2 > 58) { $k2 = $k2 - mt_rand(8,50); }
$k2 = mt_rand(1,32);
while ($k2 > 23) {
$k2 = $k2 - mt_rand(1,23);
}
}
if ($k > $k2) {
$k3 = $k2;
} else {
$k3 = $k;
}
$k_save = $k;
$k2_save = $k2;
for($i_text = 0; $i_text < $l_t; $i_text++) {
if($k > $l_k-1) {$k = 0;} // Wenn ende des keys, dann wieder von vorne
if($k2 > strlen($key2)) {$k2 = 0;} // Wenn ende des keys, dann wieder von vorne
if ( $direction == "encode" ) {
$z=ord(substr($text,$i_text,1))+ord(substr($key,$k,1));
if ( $z > 255 ) {
$z=$z-256;
}
$z = $z+ord(substr($key2,$k2,1));
if ( $z > 255 ) {
$z=$z-256;
}
$z = $z+ord(substr($key3,$k3,1));
if ( $z > 255 ) {
$z=$z-256;
}
} else {
if ( ord(substr($text,$i_text,1)) < ord(substr($key3,$k3,1)) ) {
$z = ord(substr($text,$i_text,1)) + 256 - ord(substr($key3,$k3,1));
} else {
$z = ord(substr($text,$i_text,1)) - ord(substr($key3,$k3,1));
}
if ( $z < ord(substr($key2,$k2,1)) ) {
$z = $z + 256 - ord(substr($key2,$k2,1));
} else {
$z = $z - ord(substr($key2,$k2,1));
}
if ( $z < ord(substr($key,$k,1)) ) {
$z = $z + 256 - ord(substr($key,$k,1));
} else {
$z = $z - ord(substr($key,$k,1));
}
}
$rettext.= chr($z); // Verschlüsselung
$k++;
$k2++;
}
if ($direction == "encode") {
$md = substr(md5($rettext),0,4);
$x = substr($rettext,0,1).chr($k_save + 64).chr($k2_save + 64).$md.substr($rettext,1,strlen($rettext) - 1);
return "bv3" . base32_encode($x);
} else {
return $rettext;
}
}
}
?>
<?php
/* PHP function base32_encode und base32_decode Copyright (C) 2018 Bernhard Blasen
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Don't remove this text from source code if you distribute it
*/
function base32_encode($data) {
$chars = '0123456789abcdefghjkmnpqrstvwxyz';
$mask = 0b11111;
$dataSize = strlen($data);
$res = '';
$remainder = 0;
$remainderSize = 0;
for($i = 0; $i < $dataSize; $i++) {
$b = ord($data[$i]);
$remainder = ($remainder << 8) | $b;
$remainderSize += 8;
while($remainderSize > 4) {
$remainderSize -= 5;
$c = $remainder & ($mask << $remainderSize);
$c >>= $remainderSize;
$res .= $chars[$c];
}
}
if($remainderSize > 0) {
$remainder <<= (5 - $remainderSize);
$c = $remainder & $mask;
$res .= $chars[$c];
}
return $res;
}
function base32_decode($data) {
$map = [
'0' => 0,
'O' => 0,
'o' => 0,
'1' => 1,
'I' => 1,
'i' => 1,
'L' => 1,
'l' => 1,
'2' => 2,
'3' => 3,
'4' => 4,
'5' => 5,
'6' => 6,
'7' => 7,
'8' => 8,
'9' => 9,
'A' => 10,
'a' => 10,
'B' => 11,
'b' => 11,
'C' => 12,
'c' => 12,
'D' => 13,
'd' => 13,
'E' => 14,
'e' => 14,
'F' => 15,
'f' => 15,
'G' => 16,
'g' => 16,
'H' => 17,
'h' => 17,
'J' => 18,
'j' => 18,
'K' => 19,
'k' => 19,
'M' => 20,
'm' => 20,
'N' => 21,
'n' => 21,
'P' => 22,
'p' => 22,
'Q' => 23,
'q' => 23,
'R' => 24,
'r' => 24,
'S' => 25,
's' => 25,
'T' => 26,
't' => 26,
'V' => 27,
'v' => 27,
'W' => 28,
'w' => 28,
'X' => 29,
'x' => 29,
'Y' => 30,
'y' => 30,
'Z' => 31,
'z' => 31,
];
$data = strtolower($data);
$dataSize = strlen($data);
$buf = 0;
$bufSize = 0;
$res = '';
for($i = 0; $i < $dataSize; $i++) {
$c = $data[$i];
if(!isset($map[$c])) {
throw new \Exception("Unsupported character $c (0x".bin2hex($c).") at position $i");
}
$b = $map[$c];
$buf = ($buf << 5) | $b;
$bufSize += 5;
if($bufSize > 7) {
$bufSize -= 8;
$b = ($buf & (0xff << $bufSize)) >> $bufSize;
$res .= chr($b);
}
}
return $res;
}
?>
/* PHP function base32_encode und base32_decode Copyright (C) 2018 Bernhard Blasen
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Don't remove this text from source code if you distribute it
*/
function base32_encode($data) {
$chars = '0123456789abcdefghjkmnpqrstvwxyz';
$mask = 0b11111;
$dataSize = strlen($data);
$res = '';
$remainder = 0;
$remainderSize = 0;
for($i = 0; $i < $dataSize; $i++) {
$b = ord($data[$i]);
$remainder = ($remainder << 8) | $b;
$remainderSize += 8;
while($remainderSize > 4) {
$remainderSize -= 5;
$c = $remainder & ($mask << $remainderSize);
$c >>= $remainderSize;
$res .= $chars[$c];
}
}
if($remainderSize > 0) {
$remainder <<= (5 - $remainderSize);
$c = $remainder & $mask;
$res .= $chars[$c];
}
return $res;
}
function base32_decode($data) {
$map = [
'0' => 0,
'O' => 0,
'o' => 0,
'1' => 1,
'I' => 1,
'i' => 1,
'L' => 1,
'l' => 1,
'2' => 2,
'3' => 3,
'4' => 4,
'5' => 5,
'6' => 6,
'7' => 7,
'8' => 8,
'9' => 9,
'A' => 10,
'a' => 10,
'B' => 11,
'b' => 11,
'C' => 12,
'c' => 12,
'D' => 13,
'd' => 13,
'E' => 14,
'e' => 14,
'F' => 15,
'f' => 15,
'G' => 16,
'g' => 16,
'H' => 17,
'h' => 17,
'J' => 18,
'j' => 18,
'K' => 19,
'k' => 19,
'M' => 20,
'm' => 20,
'N' => 21,
'n' => 21,
'P' => 22,
'p' => 22,
'Q' => 23,
'q' => 23,
'R' => 24,
'r' => 24,
'S' => 25,
's' => 25,
'T' => 26,
't' => 26,
'V' => 27,
'v' => 27,
'W' => 28,
'w' => 28,
'X' => 29,
'x' => 29,
'Y' => 30,
'y' => 30,
'Z' => 31,
'z' => 31,
];
$data = strtolower($data);
$dataSize = strlen($data);
$buf = 0;
$bufSize = 0;
$res = '';
for($i = 0; $i < $dataSize; $i++) {
$c = $data[$i];
if(!isset($map[$c])) {
throw new \Exception("Unsupported character $c (0x".bin2hex($c).") at position $i");
}
$b = $map[$c];
$buf = ($buf << 5) | $b;
$bufSize += 5;
if($bufSize > 7) {
$bufSize -= 8;
$b = ($buf & (0xff << $bufSize)) >> $bufSize;
$res .= chr($b);
}
}
return $res;
}
?>
Kommentar