最近,我一直在研究密码学。 为了更好地理解所有这些,我一直在尝试用PHP编写更高级的XOR cypher版本。 我的加密功能工作得很好,但解密功能输出很奇怪,与输入的信息完全不同。
该算法的思想是首先对第一个和最后一个字符运行XOR运算,然后对第二个字符和最后一个字符运行XOR运算,依此类推。 之后,它对前两个字符和后两个字符运行XOR运算,然后是第三个和第四个字符,第二个和第三个字符为最后一个,依此类推。 这将继续使用3,4,5和更多字符的块。
我现在的代码:
<?php
function encrypt($message, $key) {
$output_text = '';
// Add zeros at the end until the length of the message corresponds with the length of
the key
$message = str_pad($message,strlen($key),0);
if((strlen($message) % 2)) {
// The lenght of the message is odd, add a zero
$message = $message . 0;
}
// Define the final length of the message
$length = strlen($message);
// Firstly, take 1 character, then 2, then 3, etc. until you reach half the length of the message
for($characters=1; $characters<=($length/2); $characters++) {
// Loop from i til half the length of the message
for($i=0; $i<=(($length/2)-1); $i += $characters) {
// Take the first and last character, the the first two and the last two, etc.
// Stop when it crosses half the length
if( ($i + $characters ) >= ( $length / 2 ) ) break;
// firstly, the characters at the beginning
$beginning = substr($message, $i, $characters);
for($j=0; $j<$characters; $j++) {
$position = ( $i + 1 ) + $j;
$output_text .= chr(ord($beginning{$j}) ^ ord($key{$position}));
}
// Then those at the end
$ending = substr($message, $length-(($i+1) * $characters), $characters);
for($j=0; $j<$characters; $j++) {
$position = ( $length - ( ( $i + 1 )* $characters) ) + $j;
$output_text .= chr(ord($ending{$j}) ^ ord($key{$position}));
}
}
}
return $output_text;
}
function decrypt($message, $key) {
$output_text = null;
// Define the final length of the message
$length = strlen($message);
// Firstly, take 1 character, then 2, then 3, etc. until you reach half the length of the message
for($characters=1; $characters<=($length/2); $characters++) {
// Loop from i til half the length of the message
for($i=0; $i<=(($length/2)-1); $i += $characters) {
// Take the first and last character, the the first two and the last two, etc.
// Stop when it crosses half the length
if( ($i + $characters ) >= ( $length / 2 ) ) break;
// firstly, the characters at the beginning
$beginning = substr($message, $i, $characters);
for($j=0; $j<$characters; $j++) {
$position = ( $i + 1 ) + $j;
$output_text .= chr(ord($key{$position}) ^ ord($beginning{$j}));
}
// The those at the end
$ending = substr($message, $length-(($i+1) * $characters), $characters);
for($j=0; $j<$characters; $j++) {
$position = ( $length - ( ( $i + 1 )* $characters) ) + $j;
$output_text .= chr(ord($key{$position}) ^ ord($ending{$j}));
}
}
}
return $output_text;
}
$message = 'sampletextjusttotrythisoutcreatedin2012';
$key = '123';
$output_text = encrypt($message, $key);
echo $output_text . '<br /><hr />';
echo decrypt($output_text, $key);
提前感谢您帮助我!
答案 0 :(得分:2)
让我们从更简单的事情开始 - 给定一条消息和一个密钥,对带有加密密钥的消息进行异或。使用密钥对加密的消息进行XOR解密。
$msg = "The rooster crows at midnight!";
$key = "secret key";
$cipher_text = simple_xor($msg, $key);
$plain_text = simple_xor($cipher_text, $key);
echo "Original msg: $msg\n";
echo "Supplied key: $key\n";
echo "\n";
echo "Cipher Text: " . base64_encode($cipher_text) . "\n";
echo " Decrypted: " . $plain_text . "\n";
function simple_xor($input, $key) {
# Input must be of even length.
if (strlen($input) % 2)
$input .= '0';
# Keys longer than the input will be truncated.
if (strlen($key) > strlen($input))
$key = substr($key, 0, strlen($input));
# Keys shorter than the input will be padded.
if (strlen($key) < strlen($input))
$key = str_pad($key, strlen($input), '0', STR_PAD_RIGHT);
# Now the key and input are the same length.
# Zero is used for any trailing padding required.
# Simple XOR'ing, each input byte with each key byte.
$result = '';
for ($i = 0; $i < strlen($input); $i++) {
$result .= $input{$i} ^ $key{$i};
}
return $result;
}
在这里你可以看到XOR的内在价值。给定Msg XOR Key = C
,然后C XOR Key = Msg
和C XOR Msg = Key
。
现在让我们回到您的方法 - 看起来您希望将更多的角色混合在一起,以产生更强大的&#39;加密结果。在此之前,请花点时间思考以这种方式使用XOR时创建加密强度的原因。在此过程中,假设攻击者具有上述代码,但不是$msg
或$key
。
攻击者将知道您的消息和密钥有多长,因为此算法始终生成的结果与消息和密钥的字节数相同。
最强的密钥是每个字节不同的密钥 - 这样结果将不包含模式。例如,如果使用仅包含一个重复字节的密钥加密英文文本,我可能会注意到密文包含多次重复的一个字节。这可能是字母&#39; e&#39;在你的纯文本中,最流行的元音。如果密钥包含完全随机的字节,那么在密文中发现的任何模式都无法帮助我识别纯文本。
所以,这是一个&#39; Feet&#39; &#39; abcd&#39;的关键强大?嗯,它肯定比使用&00; 0000&#39;的键强,但它可能更强。攻击者可能会认为您使用的是一个简单的密钥,只包含小写字母。这意味着强行攻击这个密钥,攻击者需要尝试26 ^ 8个可能的选项。这可以在现代计算机上在不到一秒的时间内完成。更好的密钥将包含大写字母,数字,标点符号和其他字符。更好的密钥也包括不可打印的字符,例如:$key = chr(27) . chr(6) . 'q.';
使用此算法需要考虑的另一个有趣元素是,它要求密钥与msg的长度相等。这意味着强烈加密大量文本(例如小说)需要一个完全随机的密钥,只要小说。大多数主流算法通过在块中加密消息来避免此要求。有许多不同的方法来实现块编码,让我举例说明一种称为密码块链接(CBC)。
简单CBC通过获取纯文本的前几个字节来工作,使用密钥对其进行异或,从而生成密文的前几个字节。纯文本的下几个字节通过XOR加密,并使用密文和密钥的前几个字节进行加密。重复此过程,直到所有纯文本都加密。这将创建一个链,其中密文中的每个块都是使用先前的块和密钥创建的。要解密最后一个结果,您必须使用前一个密文块对Xip密文进行异或,然后再使用密钥进行异或。
强大的算法结合了其他功能,以确保密码文本尽可能随机,包括允许您确定加密邮件是否已被修改的功能。阅读更多关于分组密码模式的好地方是维基百科:http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation
“密码学”页面还提供了大量有关不同加密形式和密码分析过程的介绍性信息。 http://en.wikipedia.org/wiki/Cryptography
答案 1 :(得分:1)
现在,“解密”字符串最困难的部分是弄清楚输入的时间。如果我们将其作为附加参数,我们几乎可以解密它:
function decrypt($cipher, $messagelen, $key) {
if($messagelen % 2) { $messagelen++; }
$x = substr($cipher, -$messagelen + 2);
$y = substr($x, 0, strlen($key) - 1) ^ substr($key, 1);
$z = substr($x, strlen($key) - 1);
return $y . $z;
}
这变得更加容易,因为大多数消息都出现在密文末尾的清除中。哎呀。该重复中唯一被“加密”的字符是前几个,只是与密钥进行异或。
由于加密中的一个错误,中间的两个字符无法挽回地丢失。关于如何解决这个问题的注意事项在我的评论中。