Skip to content

Instantly share code, notes, and snippets.

@ircmaxell
Created April 8, 2015 21:04
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ircmaxell/160b4a2f98f56ee6c890 to your computer and use it in GitHub Desktop.
Save ircmaxell/160b4a2f98f56ee6c890 to your computer and use it in GitHub Desktop.

This gist determines keys for the "RADICORE ENCRYPTION CLASS": http://pastebin.com/2j2G83AH.

It relies on knowing the settings, but not the key.

See the demo.php file for a test situation using weak random keys.

It takes approximately 10 seconds to work out a 50 character random key.

One interesting thing is that there are colliding keys for a given plaintext.

For example:

plaintext:

lz~?xr98Mn/zYqFMUj$VY9By !CeTsh[kM3pvLpS]nY+@rnI&fgv4@l_d)EpO1N^|wne kA4

encrypted with

o#1C4zKf{Bg@v4&lUM7t<F+6:QL~eo(FyBIS

is decryptable with

o#1C4zKf{Bg@v4&lUM7t<F+6:LQ~eo(F$BIR

There are lots of examples:

[VFy,/pm+?7Qouv.,gB0fDv0dB6)nUY_]_ tgFc0k>~7vGX)?X84IJD],}k3p:tDkvi ;b,ex:HyA4fcI%3ow{
%`c=*MGU)f^J+YG/4bG+wm`0$aq6KoKz?cER8E(bm!
%`c=*MGU)f@JsYG/4bG+&1`0$=-6KoKz?cER8E(<1!

etc.

So to derive the exact key, you'd need multiple plaintext/ciphertext pairs.

<?php
$enc = new encryption_class;
const KEYSPACE = "! #$%&()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~";
define("KEYSPACE_LEN", strlen(KEYSPACE));
for ($n = 6; $n < 64; $n++) {
$key = '';
for ($i = 0; $i < $n; $i++) {
$key .= substr(KEYSPACE, mt_rand(0, KEYSPACE_LEN - 1), 1);
}
$plaintext = "";
for ($i = 0; $i < 2 * $n; $i++) {
$plaintext .= substr(KEYSPACE, mt_rand(0, KEYSPACE_LEN-1), 1);
}
echo "Trying $n\n";
$s = microtime(true);
$k = decodeKey($enc, $enc->encrypt($key, $plaintext, strlen($plaintext)), $plaintext);
$e = microtime(true);
if ($k !== $key) {
echo "Error in $k\n";
echo "Should be $key\n";
}
echo "Key[$n] in " . number_format($e - $s) . " seconds\n";
}
<?php
function decodeKey($enc, $encrypted, $plain) {
$calls = 0;
$keylen = [];
for ($i = 0; $i < 255; $i++) {
$calls++;
if ($plain[0] === $enc->decrypt(str_repeat("a", $i), $encrypted, strlen($encrypted))[0]) {
$keylen[] = $i;
}
}
foreach ($keylen as $len) {
$try = decodeKeyLen($enc, $encrypted, $plain, "", $len, $calls);
if ($try) {
var_dump($calls);
return $try;
}
}
}
function decodeKeyLen($enc, $encrypted, $plain, $prefix, $len, &$calls) {
$key = $prefix;
for ($i = strlen($prefix); $i < $len; $i++) {
$candidates = [];
for ($j = 0; $j < KEYSPACE_LEN; $j++) {
$c = substr(KEYSPACE, $j, 1);
$calls++;
$tKey = $key . str_repeat($c, $len - $i);
$t = $enc->decrypt($tKey, $encrypted, strlen($encrypted));
if (!isset($t[$i + 1]) || $t[$i + 1] === $plain[$i + 1]) {
$candidates[] = $c;
}
}
if (count($candidates) === 1) {
$key .= $candidates[0];
} elseif (empty($candidates)) {
return false;
} elseif (count($candidates) === KEYSPACE_LEN) {
return $key;
} else {
foreach ($candidates as $candidate) {
$try = decodeKeyLen($enc, $encrypted, $plain, $key . $candidate, $len, $calls);
if ($try) {
return $try;
}
}
// if we get here, there was a problem
return false;
}
}
return $key;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment