Created
August 30, 2014 03:40
-
-
Save shonenada/336a8054da7a95457cc7 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
DEFAULT_KEY = 'abcdefgh'; | |
// $string 明文 或 密文 | |
// $operation: decode =》 解密,其他是加密 | |
// $key: 秘钥 | |
// $expiry: 有效期 | |
function authcode($string, $operation = 'DECODE', $key = '', $expiry = 0) { | |
// 动态密钥长度,相同的明文会生成不同密文就是艺考动态密钥 (初始化向量 IV) | |
$ckey_length = 4; | |
// 随机密钥长度取值 0 ~ 32 | |
// 加入随机密钥,可以令密文无任何规律,即便是原文和密钥完全相同,加密结果也会每次不同, | |
// 增大破解难度(实际上就是 IV) | |
// 取值越大,密文变动规律越大,密文变化 = 16 的 $ckey_length 次方 | |
// 此值为 0 的时候,则不产生随机秘钥 | |
$key = md5($key ? $key : DEFAULT_KEY); | |
// 参与加密、解密 | |
$keya = md5(substr($key, 0, 16)); | |
// 做数据完整性验证 | |
$keyb = md5(substr($key, 16, 16)); | |
// 用于变化生成的密文 初始化向量 IV | |
$keyc = $ckey_length ? | |
($operation == 'DECODE' ? | |
substr($string, 0, $ckey_length) : | |
substr(md5(microtime()), -$ckey_length)) : ''; | |
$cryptkey = $keya . md5($keya . $keyc); | |
$key_length = $strlen($cryptkey); | |
// 明文,前 10 位用来保存时间戳,解密时验证数据有效性, 10 到 26 位用来保存 $keyb | |
// 解密时会通过这个密钥验证数据完整性 | |
// 如果是解码的话,会从第 $ckey_length 为开始,因为密文前 $ckey_length 位保存动态密钥 | |
// 以保证解密正确。 | |
$string = $opertaion == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0) . substr(md5($string . $keyb), 0, 16).$string; | |
$string_length = strlen($string); | |
$result = ''; | |
$box = range(0, 255); | |
$rndkey = array(); | |
// 产生密钥簿 | |
for ($i=0; $i <= 255; $i++) { | |
$rndkey[$i] = ord($cryptkey[$i % $key_length]); | |
} | |
// 用固定算法打乱密钥簿,增加随机性,实际上不会增加密文强度. | |
for($j = $i = 0; $i < 256; $i++) { | |
$j = ($j + $box[$i] + $rndkey[$i]) % 256; | |
$tmp = $box[$i]; | |
$box[$i] = $box[$j]; | |
$box[$j] = $tmp; | |
} | |
// 核心加密、解密部分 | |
for ($a = $i = $i = 0; $i < $string_length; $i++) { | |
$a = ($a + 1) % 256; | |
$j = ($j + $box[$a]) % 256; | |
$tmp = $box[$a]; | |
$box[$j] = $tmp; | |
// 从密钥簿得出密钥进行亦或,再转成字符 | |
$result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256])); | |
} | |
if ($operation == 'DECODE') { | |
if ((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && | |
substr($result, 10, 16) == substr(md5(substr($result, 26) . $keyb), 0, 16)) { | |
return substr($result, 26); | |
} else { | |
return ''; | |
} | |
} else { | |
// 把动态密钥保存在密文里,这也是为什么同样的明文,产生不同密文后能解密的原因 | |
// 因为加密后的密文可能是 一些特殊字符,复制过程可能是会丢失所以用 base64 编码 | |
return $keyc . str_replace('=', '', base64_encode($result)); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
require 'authcode.php'; | |
$plaintext_1 = 'aaaabbbb'; | |
$plaintext_2 = 'ccccdddd'; | |
echo "plaintext_1 is: " . $plaintext_1 . "<br />"; | |
echo "plaintext_2 is: " . $plaintext_2 . "<br />"; | |
$cipher_1 = base64_decode(substr(authcode($plaintext_1, "ENCODE", DEFAULT_KEY), 0)); | |
echo "Cipher_1 is: " . hex($cipher_1) . "<br /><br />"; | |
$cipher_2 = base64_decode(substr(authcode($plaintext_2), "ENCODE", DEFAULT_KEY), 0)); | |
echo "Cipher_2 is:" . hex($cipher_2) . "<br /><br />"; | |
function hex($str) { | |
$result = ''; | |
for ($i = 0;$i<strlen($str);$i++) { | |
$result .= "\\x" . ord($str[$i]); | |
} | |
} | |
echo "crack result is: " . crack($plaintext_1, $cipher_1, $cipher_2); | |
function crack($plain, $cipher_p, $cipher_t) { | |
$target = ''; | |
$len = strlen($plain); | |
$tmp_p = substr($cipher_p, 26); | |
echo hex($tmp_p) . "<br />"; | |
$tmp_t = substr($cipher_t, 26); | |
echo hex($tmp_t) . "<br />"; | |
for ($i=0; $i < strlen($plain); $i++) { | |
$target .= chr(ord($plain[$i]) ^ ord($tmp_p[$i]) ^ ord($tmp_p[$i])); | |
} | |
return $target; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
require 'authcode.php'; | |
$plaintext_1 = 'aaaabbbb'; | |
$plaintext_2 = 'ccccdddd'; | |
$guess_result = ''; | |
$time_start = time(); | |
$dict = array(); | |
global $ckey_length; | |
$ckey_length = 4; | |
echo "Collecting Dictionar (XOR Keys). \n"; | |
$cipher2 = authcode($plaintext_2, 'ENCODE', DEFAULT_KEY); | |
$counter = 0; | |
for (;;) { | |
$counter ++; | |
$cipher1 = authcode($plaintext1, 'ENCODE', DEFAULT_KEY); | |
$keyc1 = substr($cipher1, 0, $ckey_length); | |
$cipher1 = base64_decode(substr($cipher1, $ckey_length)); | |
$dict[$keyc1] = $cipher1; | |
if ($counter % 1000 == 0) { | |
echo "."; | |
if ($guess_result = guess($dict, $cipher)) { | |
break; | |
} | |
} | |
} | |
array_unique($dict); | |
echo "\nDictionary Collecting Finished..\n"; | |
echo "Collected " . count($dict) . " XOR Keys\n"; | |
function guess($dict, $cipher2) { | |
global $plaintext1, $ckey_length; | |
$keyc2 = substr($cipher2, 0, $ckey_length); | |
$cipher2 = base64_decode(substr($cipher2, $ckey_length)); | |
for($i=0;$i<count($dict); $i++) { | |
if (array_key_exists($keyc2, $dict)) { | |
echo "\nFound key in dictionary!\n"; | |
echo "keyc is :" . $keyc2 . "\n"; | |
return crack($plaintext1, $dict[$keyc2], $cipher2); | |
break; | |
} | |
} | |
return False; | |
} | |
echo "\ncounter is " . $counter . "\n"; | |
$time_spend = time() - $time_start; | |
echo "crack time is : " . $time_speed . "seconds \n"; | |
echo "crack result is: " . $guess_result . "\n"; | |
function crack($plain, $cipher_p, $cipher_t) { | |
$target = ''; | |
$tmp_p = substr($cipher_p, 26); | |
$tmp_t = substr($cipher_t, 26); | |
for ($i=0;$i<strlen($plain);$i++) { | |
$target .= chr(ord($pliain[$i]) ^ ord($tmp_p[$i]) ^ ord($tmp_t[$i])); | |
} | |
return $target; | |
} | |
function hex($str) { | |
$result = ''; | |
for ($i=0;$i<strlen($str);$i++) { | |
$result .= "\\x" . ord($str[$i]); | |
} | |
return $result; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment