-
w3challs authorede563c163
<?php
define ("ALLOWED_TIME", 600);
define ("NB_CHALLENGES", 5);
define ("NB_ALLOWED_PT", 32);
@session_start();
header("Content-Type: text/html; charset=utf-8");
/************************/
/* FUNCTIONS */
/************************/
// returns the determinant of a 3*3 matrix
function det33($matrix)
{
if (count($matrix) != 3 or count($matrix[0]) != 3 or count($matrix[1]) != 3 or count($matrix[2]) != 3)
return False;
return $matrix[0][0] * ($matrix[1][1]*$matrix[2][2] - $matrix[1][2]*$matrix[2][1])
+ $matrix[0][1] * ($matrix[1][2]*$matrix[2][0] - $matrix[1][0]*$matrix[2][2])
+ $matrix[0][2] * ($matrix[1][0]*$matrix[2][1] - $matrix[1][1]*$matrix[2][0]) ;
}
// returns a random matrix (3*3, integer values in range 1..25)
function get_matrix()
{
$matrix = array();
for ($i = 0; $i < 3; $i++)
{
$vect = array();
for ($j = 0; $j < 3; $j++)
$vect[] = rand(1, 25);
$matrix[] = $vect;
}
return $matrix;
}
// returns a matrix invertible modulo 26
function get_key_matrix()
{
while (True)
{
$matrix = get_matrix();
$det = det33($matrix);
if ($det % 2 != 0 and $det % 13 != 0)
return $matrix;
}
}
// returns a random 3-letter text
function get_random_trigraph()
{
$text = "";
for ($i = 0; $i < 3; $i++)
$text.= chr(rand(0, 25) + 0x41);
return $text;
}
function get_permutation()
{
$perm = range(0, 25);
shuffle($perm);
return $perm;
}
function hill($keymatrix, $permutation, $inputtext)
{
7172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
$blocsize = count($keymatrix);
if (strlen($inputtext) != $blocsize)
return False;
// compute the inverse permutation
$inverseperm = range(0, 25);
for ($i = 0; $i < 26; $i++)
$inverseperm[$permutation[$i]] = $i;
// conversion (letters -> numbers)
$inputvector = array();
for ($i = 0; $i < $blocsize; $i++)
{
$letter = $inputtext[$i];
if ($letter < 'A' or $letter > 'Z')
return False;
$inputvector[] = $permutation[ ord($letter)-ord('A')];
}
// multiply the vector
$outputvector = array();
for ($i = 0; $i < $blocsize; $i++)
{
$sum = 0;
for ($j = 0; $j < $blocsize; $j++)
$sum += $keymatrix[$i][$j] * ($permutation[ord($inputtext[$j]) - 0x41]);
$outputvector[] = $sum % 26;
}
// conversion (numbers -> letters)
$outputtext = "";
for ($i = 0; $i < $blocsize; $i++)
$outputtext.= chr($inverseperm[$outputvector[$i]] + 0x41);
return $outputtext;
}
// small static test
function test()
{
$perm = array(3, 22, 7, 25, 2, 11, 13, 4, 20, 12, 16, 14, 9, 21, 19, 6, 18, 0, 23, 8, 1, 24, 5, 10, 17, 15);
$mat = array(array(15, 22, 23), array(18, 1, 22), array(20, 6, 25));
return (hill($mat, $perm, "ABC") == "LBA" and hill($mat, $perm, "DEF") == "BQC" and hill($mat, $perm, "GHI") == "ZEH");
}
// clean the session variables and die
function die_clean($message)
{
echo $message;
$_SESSION['VORTEXCPTA_STARTED'] = False;
//unset($_SESSION['VORTEXCPTA_STARTED']);
unset($_SESSION['VORTEXCPTA_TIME']);
unset($_SESSION['VORTEXCPTA_MATRIX']);
unset($_SESSION['VORTEXCPTA_PERM']);
die();
}
/************************/
/* CHALLENGE */
/************************/
$VARNAMES = array("VORTEXCPTA_TIME", "VORTEXCPTA_MATRIX", "VORTEXCPTA_PERM", "VORTEXCPTA_CHALL");
// a new problem is requested
if (isset($_GET["cpta"]))
{
// check the variable format
$regex_cpta = '/^[A-Z]{3}(_[A-Z]{3}){0,'. strval(NB_ALLOWED_PT-1).'}$/';
141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
if (!preg_match( $regex_cpta, $_GET['cpta'])) {
die_clean("Bad input format.\n");
} else {
$plaintexts = explode('_', $_GET['cpta']);
$matrix = get_key_matrix();
$perm = get_permutation();
foreach ($plaintexts as $plain)
{
$cipher = hill($matrix, $perm, $plain);
echo "$plain -> $cipher <br />\n";
}
$chall = array();
for ($i = 1; $i <= NB_CHALLENGES; $i++)
{
$trig = get_random_trigraph();
echo "Challenge #$i: $trig <br />\n";
$chall[] = $trig;
}
$_SESSION['VORTEXCPTA_CHALL'] = $chall;
$_SESSION['VORTEXCPTA_MATRIX'] = $matrix;
$_SESSION['VORTEXCPTA_PERM'] = $perm;
$_SESSION['VORTEXCPTA_STARTED'] = True;
$_SESSION['VORTEXCPTA_TIME'] = time();
}
}
// 2nd call: check the solution
else if (isset($_GET['solution']))
{
if (!isset($_SESSION['VORTEXCPTA_STARTED']) or $_SESSION['VORTEXCPTA_STARTED'] != True)
die_clean("The challenge isn't initialized.\n");
// check that all variables are there
foreach ($VARNAMES as $varname)
if (!isset($_SESSION[$varname]))
die_clean("Bug: variable $varname is not initialized.\n");
$time = $_SESSION['VORTEXCPTA_TIME'];
if (time() - $time > ALLOWED_TIME)
die_clean("Too late!\n");
// check input format
$regex_solution = '/^[A-Z]{3}(_[A-Z]{3}){'. strval(NB_CHALLENGES-1).'}$/';
if (!preg_match($regex_solution, $_GET["solution"]))
die_clean("Bad input format.\n");
$matrix = $_SESSION['VORTEXCPTA_MATRIX'];
$perm = $_SESSION['VORTEXCPTA_PERM'];
$chall = $_SESSION['VORTEXCPTA_CHALL'];
$answers = explode( '_', $_GET['solution'] );
// check the proposed solution
for ($i = 0; $i < NB_CHALLENGES; $i++)
{
$answercrypt = hill($matrix, $perm, $answers[$i]);
if ($answercrypt != $chall[$i])
{
die_clean("Wrong answer: ".$answers[$i]." -> $answercrypt != ".$chall[$i]."\n");
}
}
$flag = "..."; // No, it's not "...". You really have to solve the chall.
echo "Congratulations! The flag is $flag <br />\n";
die_clean("");
}