diff --git a/crypt.php b/crypt.php index 80e7dd4b..1aa60dec 100644 --- a/crypt.php +++ b/crypt.php @@ -2,57 +2,59 @@ set_include_path(get_include_path() . PATH_SEPARATOR . dirname(__FILE__) . DIRECTORY_SEPARATOR . 'libpy2php'); require_once ('libpy2php.php'); require_once ('AES.class.php'); -function ige_encrypt($message, $key, $iv) { - return py2php_kwargs_function_call('_ige', [$message, $key, $iv], ["operation" => 'encrypt']); -} -function ige_decrypt($message, $key, $iv) { - return py2php_kwargs_function_call('_ige', [$message, $key, $iv], ["operation" => 'decrypt']); -} -/** - * Given a key, given an iv, and message - * do whatever operation asked in the operation field. - * Operation will be checked for: "decrypt" and "encrypt" strings. - * Returns the message encrypted/decrypted. - * message must be a multiple by 16 bytes (for division in 16 byte blocks) - * key must be 32 byte - * iv must be 32 byte (it's not internally used in AES 256 ECB, but it's - * needed for IGE) - */ -function _ige($message, $key, $iv, $operation = 'decrypt') { - $message = $bytes($message); - if ((count($key) != 32)) { - throw new $ValueError('key must be 32 bytes long (was ' . pyjslib_str(count($key)) . ' bytes)'); +class crypt { + function ige_encrypt($message, $key, $iv) { + return _ige($message, $key, $iv, 'encrypt'); } - if ((count($iv) != 32)) { - throw new $ValueError('iv must be 32 bytes long (was ' . pyjslib_str(count($iv)) . ' bytes)'); + function ige_decrypt($message, $key, $iv) { + return _ige($message, $key, $iv, 'decrypt'); } - $cipher = new AES($key); - $cipher = $cipher->encrypt($iv); - $blocksize = $cipher->block_size; - if (((count($message) % $blocksize) != 0)) { - throw new $ValueError('message must be a multiple of 16 bytes (try adding ' . pyjslib_str((16 - (count($message) % 16))) . ' bytes of padding)'); - } - $ivp = array_slice($iv, 0, $blocksize - 0); - $ivp2 = array_slice($iv, $blocksize, null); - $ciphered = $bytes(); - foreach (pyjslib_range(0, count($message), $blocksize) as $i) { - $indata = array_slice($message, $i, ($i + $blocksize) - $i); - if (($operation == 'decrypt')) { - $xored = new strxor($indata, $ivp2); - $decrypt_xored = $cipher->decrypt($xored); - $outdata = new strxor($decrypt_xored, $ivp); - $ivp = $indata; - $ivp2 = $outdata; - } else if (($operation == 'encrypt')) { - $xored = new strxor($indata, $ivp); - $encrypt_xored = $cipher->encrypt($xored); - $outdata = new strxor($encrypt_xored, $ivp2); - $ivp = $outdata; - $ivp2 = $indata; - } else { - throw new $ValueError('operation must be either \'decrypt\' or \'encrypt\''); + /** + * Given a key, given an iv, and message + * do whatever operation asked in the operation field. + * Operation will be checked for: "decrypt" and "encrypt" strings. + * Returns the message encrypted/decrypted. + * message must be a multiple by 16 bytes (for division in 16 byte blocks) + * key must be 32 byte + * iv must be 32 byte (it's not internally used in AES 256 ECB, but it's + * needed for IGE) + */ + function _ige($message, $key, $iv, $operation = 'decrypt') { + $message = str_split($message); + if ((len($key) != 32)) { + throw new Exception('key must be 32 bytes long (was ' . len($key) . ' bytes)'); } - $ciphered+= $outdata; + if ((len($iv) != 32)) { + throw new Exception('iv must be 32 bytes long (was ' . len($iv) . ' bytes)'); + } + $cipher = new AES($key); + $cipher = $cipher->encrypt($iv); + $blocksize = $cipher->block_size; + if ((len($message) % $blocksize) != 0) { + throw new Exception('message must be a multiple of 16 bytes (try adding ' . (16 - (count($message) % 16)) . ' bytes of padding)'); + } + $ivp = substr($iv, 0, $blocksize - 0); + $ivp2 = substr($iv, $blocksize, null); + $ciphered = null; + foreach (pyjslib_range(0, len($message), $blocksize) as $i) { + $indata = substr($message, $i, ($i + $blocksize) - $i); + if (($operation == 'decrypt')) { + $xored = strxor($indata, $ivp2); + $decrypt_xored = $cipher->decrypt($xored); + $outdata = strxor($decrypt_xored, $ivp); + $ivp = $indata; + $ivp2 = $outdata; + } else if (($operation == 'encrypt')) { + $xored = strxor($indata, $ivp); + $encrypt_xored = $cipher->encrypt($xored); + $outdata = strxor($encrypt_xored, $ivp2); + $ivp = $outdata; + $ivp2 = $indata; + } else { + throw new Exception('operation must be either \'decrypt\' or \'encrypt\''); + } + $ciphered .= $outdata; + } + return $ciphered; } - return $ciphered; -} +} \ No newline at end of file diff --git a/mtproto.php b/mtproto.php index 3f26db44..982e3964 100755 Binary files a/mtproto.php and b/mtproto.php differ diff --git a/mtproto.py b/mtproto.py index db69b89a..869b157d 100644 --- a/mtproto.py +++ b/mtproto.py @@ -40,7 +40,7 @@ def vis(bs): if not len(bs) % symbols_in_one_line == 0: print(str((i+1)*symbols_in_one_line)+" | "+" ".join(["%02X" % b for b in bs[(i+1)*symbols_in_one_line:]])+"\n") # for last line - +vis(b'ddd') class Session: """ Manages TCP Transport. encryption and message frames """ def __init__(self, ip, port, auth_key=None, server_salt=None):