Created
June 17, 2015 16:02
-
-
Save teknogeek/a9b796afaf2483b28b1d to your computer and use it in GitHub Desktop.
This file contains 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 | |
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; | |
} | |
} |
This file contains 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 | |
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