Skip to content

Instantly share code, notes, and snippets.

@teknogeek
Created June 17, 2015 16:02
Show Gist options
  • Save teknogeek/a9b796afaf2483b28b1d to your computer and use it in GitHub Desktop.
Save teknogeek/a9b796afaf2483b28b1d to your computer and use it in GitHub Desktop.
<?php
class TelegramEncryption
{
public $key;
public $iv;
public $cipherText;
public $plainText;
public $debug;
public function __construct($key, $iv, $cipherText, $plainText, $debug = false)
{
$this->key = $key;
$this->iv = $iv;
$this->cipherText = $cipherText;
$this->plainText = $plainText;
$this->debug = $debug;
}
public function decrypt()
{
$decrypted = $this->IGE256Decrypt();
if($this->hexArrayToString($decrypted) == $this->hexArrayToString($this->plainText))
{
return true;
}
else
{
return false;
}
}
public function IGE256Decrypt()
{
$key = $this->key;
$IV = $this->iv;
$message = $this->cipherText;
$blockSize = mcrypt_get_block_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_ECB);
$xPrev = array_slice($IV, 0, $blockSize);
$yPrev = array_slice($IV, $blockSize, count($IV));
$decrypted = array();
for($i = 0; $i < count($message); $i += $blockSize)
{
$x = array_slice($message, $i, $i + $blockSize);
$this->debugLog("x: " . $this->hexArrayToString($x) . "\n");
$yXOR = $this->exor($x, $yPrev);
$this->debugLog("yPrev: " . $this->hexArrayToString($yPrev) . "\n");
$this->debugLog("yXOR: " . $this->hexArrayToString($yXOR) . "\n");
$yFinal = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, hex2bin($this->hexArrayToString($key)), hex2bin($this->hexArrayToString($yXOR)), MCRYPT_MODE_ECB);
$yFinal = bin2hex($yFinal);
$yFinal = $this->hexStringToArray($yFinal);
$yFinal = array_pad($yFinal, count($xPrev), 0);
$this->debugLog("yFinal: " . $this->hexArrayToString($yFinal) . "\n");
$y = $this->exor($yFinal, $xPrev);
$this->debugLog("xPrev: " . $this->hexArrayToString($xPrev) . "\n");
$this->debugLog("y: " . $this->hexArrayToString($y) . "\n\n");
$xPrev = $x;
$yPrev = $y;
$decrypted = array_merge($decrypted, $y);
}
return $decrypted;
}
public function debugLog($message)
{
if($this->debug)
{
echo $message;
}
}
public function exor($array1, $array2)
{
$res = array();
$len = (count($array1) <= count($array2)) ? count($array2) : count($array1);
$res = array_pad($res, $len, 0);
$array1 = array_pad($array1, $len, 0);
$array2 = array_pad($array2, $len, 0);
$i = 0;
foreach($array1 as $byte)
{
$byte = dechex($byte);
$byte2 = dechex($array2[$i++]);
$byte = $this->hexDecSigned($byte);
$byte2 = $this->hexDecSigned($byte2);
$hex = $byte ^ $byte2;
$hex = str_pad($hex, 2, "0", STR_PAD_LEFT);
$res[$i - 1] = strtoupper($hex);
}
return $res;
}
//http://php.net/manual/en/function.hexdec.php#97172
public function hexDecSigned($hex)
{
// ignore non hex characters
$hex = preg_replace("/[^0-9A-Fa-f]/", "", $hex);
// converted decimal value:
$dec = hexdec($hex);
// maximum decimal value based on length of hex + 1:
// number of bits in hex number is 8 bits for each 2 hex -> max = 2^n
// use 'pow(2,n)' since '1 << n' is only for integers and therefore limited to integer size.
$max = pow(2, 4 * (strlen($hex) + (strlen($hex) % 2)));
// complement = maximum - converted hex:
$_dec = $max - $dec;
// if dec value is larger than its complement we have a negative value (first bit is set)
return $dec > $_dec ? -$_dec : $dec;
}
public function hexStringToArray($hexString)
{
$finalArray = array();
for($i = 0; $i < strlen($hexString); $i += 2)
{
$hexPart = substr($hexString, $i, 2);
if(strlen($hexPart) == 1)
{
$hexPart = "0{$hexPart}";
}
$finalArray[] = $this->hexDecSigned($hexPart);
}
return $finalArray;
}
public function hexArrayToString($array)
{
$string = "";
foreach($array as $hex)
{
$hex &= 0xFF;
$string .= strtoupper(str_pad(dechex($hex), 2, "0", STR_PAD_LEFT));
}
return $string;
}
}
<?php
include_once("./TelegramEncryption.php");
//data from http://www.links.org/files/openssl-ige.pdf
$keys = array(
array(0x00, 0x01, 0x02, 0x03,
0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0A, 0x0B,
0x0C, 0x0D, 0x0E, 0x0F),
array(0x54, 0x68, 0x69, 0x73,
0x20, 0x69, 0x73, 0x20,
0x61, 0x6E, 0x20, 0x69,
0x6D, 0x70, 0x6C, 0x65)
);
$ivs = array(
array(0x00, 0x01, 0x02, 0x03,
0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0A, 0x0B,
0x0C, 0x0D, 0x0E, 0x0F,
0x10, 0x11, 0x12, 0x13,
0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1A, 0x1B,
0x1C, 0x1D, 0x1E, 0x1F),
array(0x6D, 0x65, 0x6E, 0x74,
0x61, 0x74, 0x69, 0x6F,
0x6E, 0x20, 0x6F, 0x66,
0x20, 0x49, 0x47, 0x45,
0x20, 0x6D, 0x6F, 0x64,
0x65, 0x20, 0x66, 0x6F,
0x72, 0x20, 0x4F, 0x70,
0x65, 0x6E, 0x53, 0x53)
);
$plainTexts = array(
array(0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00),
array(0x99, 0x70, 0x64, 0x87,
0xA1, 0xCD, 0xE6, 0x13,
0xBC, 0x6D, 0xE0, 0xB6,
0xF2, 0x4B, 0x1C, 0x7A,
0xA4, 0x48, 0xC8, 0xB9,
0xC3, 0x40, 0x3E, 0x34,
0x67, 0xA8, 0xCA, 0xD8,
0x93, 0x40, 0xF5, 0x3B)
);
$cipherTexts = array(
array(0x1A, 0x85, 0x19, 0xA6,
0x55, 0x7B, 0xE6, 0x52,
0xE9, 0xDA, 0x8E, 0x43,
0xDA, 0x4E, 0xF4, 0x45,
0x3C, 0xF4, 0x56, 0xB4,
0xCA, 0x48, 0x8A, 0xA3,
0x83, 0xC7, 0x9C, 0x98,
0xB3, 0x47, 0x97, 0xCB),
array(0x4C, 0x2E, 0x20, 0x4C,
0x65, 0x74, 0x27, 0x73,
0x20, 0x68, 0x6F, 0x70,
0x65, 0x20, 0x42, 0x65,
0x6E, 0x20, 0x67, 0x6F,
0x74, 0x20, 0x69, 0x74,
0x20, 0x72, 0x69, 0x67,
0x68, 0x74, 0x21, 0x0A)
);
$results = array();
for($i = 0; $i < count($keys); $i++)
{
$key = $keys[$i];
$iv = $ivs[$i];
$cipherText = $cipherTexts[$i];
$plainText = $plainTexts[$i];
$debug = true;
$telegram = new TelegramEncryption($key, $iv, $cipherText, $plainText, $debug);
$results[] = $telegram->decrypt();
}
foreach($results as $index => $res)
{
$msg = "Test #{$index}: ";
if($res)
$msg .= "Success!";
else
$msg .= "Failure :(";
echo "{$msg}\n";
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment