Math_BigInteger
[ class tree: Math_BigInteger ] [ index: Math_BigInteger ] [ all elements ]

Source for file ssh_demo.php

Documentation is available at ssh_demo.php

  1. <?
  2. // $Id: ssh_demo.php,v 1.4 2006/11/16 15:42:08 terrafrost Exp $
  3. // Example of Math_BigInteger's speed.  The numbers are obtained by partially negotiating an SSHv1 session with
  4. // shell.sourceforge.net.
  5.  
  6. // On a 1.6GHz Intel Pentium-M running PHP5, the modular exponentiation took less than a fifth of a second, whereas
  7. // with the BCMath functions, it took a hundreths of a second.  That BCMath is faster, however, should come as no
  8. // surprise, given that BCMath has been pre-compiled into assembly and in all likelyhood uses 64-bit integers - something
  9. // that PHP, quite simply, does not support, as yet.
  10.  
  11. // bcpowmod is included with Math_BigInteger.php via PHP_Compat.
  12.  
  13.  
  14.  
  15. include('../Math_BigInteger.php');
  16. define('SSH_SMSG_PUBLIC_KEY',2);
  17.  
  18. //define('MATH_BIGINTEGER_MODE',MATH_BIGINTEGER_MODE_INTERNAL);
  19.  
  20. error_reporting(E_STRICT);
  21.  
  22. // if shell.sourceforge.net doesn't work for you, try another domain name.
  23. ssh1_connect('shell.sourceforge.net',22);
  24. //ssh1_connect('black.cs.utexas.edu',22);
  25.  
  26. function ssh1_connect($host,$port{
  27.     $identifier 'SSH-1.5-'.basename(__FILE__);
  28.  
  29.     $fsock fsockopen($host,$port,$errno,$errstr,10);
  30.     if (!$fsock{
  31.         die("Error $errno$errstr");
  32.     }
  33.  
  34.     $init_line fgets($fsock,255);
  35.     if (!preg_match('#SSH-([0-9\.]+)-(.+)#',$init_line,$parts)) {
  36.         die('Not an SSH server on the other side.');
  37.     }
  38.     if ($parts[1]{0!= 1{
  39.         die("SSH version {$parts[1]} is not supported!");
  40.     }
  41.     echo "Connecting to $init_line\r\n";
  42.  
  43.     fputs($fsock,"$identifier\n");
  44.  
  45.     $packet get_binary_packet($fsock);
  46.     if ($packet['type'!= SSH_SMSG_PUBLIC_KEY{    
  47.         die('Expected SSH_SMSG_PUBLIC_KEY!');
  48.     }
  49.  
  50.     $anti_spoofing_cookie string_shift($packet['data'],8);
  51.  
  52.     string_shift($packet['data'],4);
  53.  
  54.     $temp unpack('nlen',string_shift($packet['data'],2));
  55.     $server_key_public_exponent = new Math_BigInteger(string_shift($packet['data'],ceil($temp['len'/ 8)),256);
  56.  
  57.     $temp unpack('nlen',string_shift($packet['data'],2));
  58.     $server_key_public_modulus = new Math_BigInteger(string_shift($packet['data'],ceil($temp['len'/ 8)),256);
  59.  
  60.     $temp unpack('nlen',string_shift($packet['data'],2));
  61.     $host_key_public_exponent = new Math_BigInteger(string_shift($packet['data'],ceil($temp['len'/ 8)),256);
  62.  
  63.     $temp unpack('nlen',string_shift($packet['data'],2));
  64.     $host_key_public_modulus = new Math_BigInteger(string_shift($packet['data'],ceil($temp['len'/ 8)),256);
  65.  
  66.     $session_id pack('H*',md5($host_key_public_modulus.$server_key_public_modulus.$anti_spoofing_cookie));
  67.  
  68.     // ought to use a cryptographically secure random number generator (which mt_srand is not)
  69.     list($sec$usecexplode(' 'microtime());
  70.     mt_srand((float) $sec ((float) $usec * 100000));
  71.  
  72.     $session_key '';
  73.     for ($i=0; $i<32; $i++{
  74.         $session_key .= chr(mt_rand(0,255));
  75.     }
  76.     $double_encrypted_session_key $session_key str_pad($session_id,32,chr(0));
  77.  
  78.     if ($server_key_public_modulus->compare($host_key_public_modulus< 0{
  79.         $prepped_key prep_session_key($double_encrypted_session_key,$server_key_public_modulus);
  80.         rsa_crypt(
  81.             $prepped_key,
  82.             array(
  83.                 $server_key_public_exponent,
  84.                 $server_key_public_modulus
  85.             )
  86.         );
  87.         rsa_crypt2(
  88.             $prepped_key,
  89.             array(
  90.                 $server_key_public_exponent,
  91.                 $server_key_public_modulus
  92.             )
  93.         );
  94.     else {
  95.         $prepped_key prep_session_key($double_encrypted_session_key,$host_key_public_modulus);
  96.         rsa_crypt(
  97.             $prepped_key,
  98.             array(
  99.                 $host_key_public_exponent,
  100.                 $host_key_public_modulus
  101.             )
  102.         );
  103.         rsa_crypt2(
  104.             $prepped_key,
  105.             array(
  106.                 $host_key_public_exponent,
  107.                 $host_key_public_modulus
  108.             )
  109.         );
  110.     }
  111. }
  112.  
  113. // see 'The Binary Packet Protocol' section of ssh1-draft.txt for more info.
  114. // also, this function could be improved upon by adding detection for the following exploit:
  115. // http://www.securiteam.com/securitynews/5LP042K3FY.html
  116.  
  117. function get_binary_packet($fsock{
  118.     $temp unpack('Nlen',fread($fsock4));
  119.  
  120.     $padding_length = 8 - ($temp['len'7);
  121.  
  122.     $raw fread($fsock$temp['len'$padding_length);
  123.  
  124.     $padding substr($raw,0,$padding_length);
  125.     $type $raw{$padding_length};
  126.     $data substr($raw,$padding_length+1,-4);
  127.     $temp unpack('Ncrc',substr($raw,-4));
  128.  
  129.     if $temp['crc'!= crc($padding.$type.$data) ) {
  130.         die('Bad CRC in packet from server');
  131.     }
  132.  
  133.     return array(
  134.         'type' => ord($type),
  135.         'data' => $data
  136.     );
  137. }
  138.  
  139. function string_shift(&$string$index = 1{
  140.     $substr substr($string,0,$index);
  141.     $string substr($string,$index);
  142.     return $substr;
  143. }
  144.  
  145. // PHP's crc32 function is implemented slightly differently than the one that SSH v1 uses, so
  146. // we've reimplemented it. A more detailed discussion of the differences can be found after
  147. // $crc_lookup_table's initialization.
  148.  
  149. function crc($text{
  150.     static $crc_lookup_table = array(
  151.         0x000000000x770730960xEE0E612C0x990951BA,
  152.         0x076DC4190x706AF48F0xE963A5350x9E6495A3,
  153.         0x0EDB88320x79DCB8A40xE0D5E91E0x97D2D988,
  154.         0x09B64C2B0x7EB17CBD0xE7B82D070x90BF1D91,
  155.         0x1DB710640x6AB020F20xF3B971480x84BE41DE,
  156.         0x1ADAD47D0x6DDDE4EB0xF4D4B5510x83D385C7,
  157.         0x136C98560x646BA8C00xFD62F97A0x8A65C9EC,
  158.         0x14015C4F0x63066CD90xFA0F3D630x8D080DF5,
  159.         0x3B6E20C80x4C69105E0xD56041E40xA2677172,
  160.         0x3C03E4D10x4B04D4470xD20D85FD0xA50AB56B,
  161.         0x35B5A8FA0x42B2986C0xDBBBC9D60xACBCF940,
  162.         0x32D86CE30x45DF5C750xDCD60DCF0xABD13D59,
  163.         0x26D930AC0x51DE003A0xC8D751800xBFD06116,
  164.         0x21B4F4B50x56B3C4230xCFBA95990xB8BDA50F,
  165.         0x2802B89E0x5F0588080xC60CD9B20xB10BE924,
  166.         0x2F6F7C870x58684C110xC1611DAB0xB6662D3D,
  167.         0x76DC41900x01DB71060x98D220BC0xEFD5102A,
  168.         0x71B185890x06B6B51F0x9FBFE4A50xE8B8D433,
  169.         0x7807C9A20x0F00F9340x9609A88E0xE10E9818,
  170.         0x7F6A0DBB0x086D3D2D0x91646C970xE6635C01,
  171.         0x6B6B51F40x1C6C61620x856530D80xF262004E,
  172.         0x6C0695ED0x1B01A57B0x8208F4C10xF50FC457,
  173.         0x65B0D9C60x12B7E9500x8BBEB8EA0xFCB9887C,
  174.         0x62DD1DDF0x15DA2D490x8CD37CF30xFBD44C65,
  175.         0x4DB261580x3AB551CE0xA3BC00740xD4BB30E2,
  176.         0x4ADFA5410x3DD895D70xA4D1C46D0xD3D6F4FB,
  177.         0x4369E96A0x346ED9FC0xAD6788460xDA60B8D0,
  178.         0x44042D730x33031DE50xAA0A4C5F0xDD0D7CC9,
  179.         0x5005713C0x270241AA0xBE0B10100xC90C2086,
  180.         0x5768B5250x206F85B30xB966D4090xCE61E49F,
  181.         0x5EDEF90E0x29D9C9980xB0D098220xC7D7A8B4,
  182.         0x59B33D170x2EB40D810xB7BD5C3B0xC0BA6CAD,
  183.         0xEDB883200x9ABFB3B60x03B6E20C0x74B1D29A,
  184.         0xEAD547390x9DD277AF0x04DB26150x73DC1683,
  185.         0xE3630B120x94643B840x0D6D6A3E0x7A6A5AA8,
  186.         0xE40ECF0B0x9309FF9D0x0A00AE270x7D079EB1,
  187.         0xF00F93440x8708A3D20x1E01F2680x6906C2FE,
  188.         0xF762575D0x806567CB0x196C36710x6E6B06E7,
  189.         0xFED41B760x89D32BE00x10DA7A5A0x67DD4ACC,
  190.         0xF9B9DF6F0x8EBEEFF90x17B7BE430x60B08ED5,
  191.         0xD6D6A3E80xA1D1937E0x38D8C2C40x4FDFF252,
  192.         0xD1BB67F10xA6BC57670x3FB506DD0x48B2364B,
  193.         0xD80D2BDA0xAF0A1B4C0x36034AF60x41047A60,
  194.         0xDF60EFC30xA867DF550x316E8EEF0x4669BE79,
  195.         0xCB61B38C0xBC66831A0x256FD2A00x5268E236,
  196.         0xCC0C77950xBB0B47030x220216B90x5505262F,
  197.         0xC5BA3BBE0xB2BD0B280x2BB45A920x5CB36A04,
  198.         0xC2D7FFA70xB5D0CF310x2CD99E8B0x5BDEAE1D,
  199.         0x9B64C2B00xEC63F2260x756AA39C0x026D930A,
  200.         0x9C0906A90xEB0E363F0x720767850x05005713,
  201.         0x95BF4A820xE2B87A140x7BB12BAE0x0CB61B38,
  202.         0x92D28E9B0xE5D5BE0D0x7CDCEFB70x0BDBDF21,
  203.         0x86D3D2D40xF1D4E2420x68DDB3F80x1FDA836E,
  204.         0x81BE16CD0xF6B9265B0x6FB077E10x18B74777,
  205.         0x88085AE60xFF0F6A700x66063BCA0x11010B5C,
  206.         0x8F659EFF0xF862AE690x616BFFD30x166CCF45,
  207.         0xA00AE2780xD70DD2EE0x4E0483540x3903B3C2,
  208.         0xA76726610xD06016F70x4969474D0x3E6E77DB,
  209.         0xAED16A4A0xD9D65ADC0x40DF0B660x37D83BF0,
  210.         0xA9BCAE530xDEBB9EC50x47B2CF7F0x30B5FFE9,
  211.         0xBDBDF21C0xCABAC28A0x53B393300x24B4A3A6,
  212.         0xBAD036050xCDD706930x54DE57290x23D967BF,
  213.         0xB3667A2E0xC4614AB80x5D681B020x2A6F2B94,
  214.         0xB40BBE370xC30C8EA10x5A05DF1B0x2D02EF8D
  215.     );
  216.  
  217.     // For this function to yield the same output as PHP's crc32 function, $crc would have to be
  218.     // set to 0xFFFFFFFF, initially - not 0x00000000 as it currently is.
  219.     
  220.     $crc = 0x00000000;
  221.     $length = strlen($text);
  222.  
  223.     for ($i=0;$i<$length;$i++{
  224.         // We AND $crc >> 8 with 0x00FFFFFF because we want the eight newly added bits to all
  225.         // be zero.  PHP, unfortunately, doesn't always do this.  0x80000000 >> 8, as an example,
  226.         // yields 0xFF800000 - not 0x00800000.  The following link elaborates:
  227.         // http://www.php.net/manual/en/language.operators.bitwise.php#57281
  228.         $crc (($crc >> 80x00FFFFFF$crc_lookup_table[($crc 0xFFord($text{$i})];
  229.     }
  230.  
  231.     // In addition to having to set $crc to 0xFFFFFFFF, initially, the return value must be XOR'd with
  232.     // 0xFFFFFFFF for this function to return the same thing that PHP's crc32 function would.
  233.     return $crc;
  234. }
  235.  
  236.  
  237. function prep_session_key($session_key,$modulus{
  238.     $result chr(0).chr(2);
  239.     $modulus $modulus->toBytes();
  240.     $length strlen($modulus)-strlen($session_key)-3;
  241.     for ($i=0; $i<$length$i++{
  242.         $result .= chr(mt_rand(1,255));
  243.     }
  244.     $result .= chr(0).$session_key;
  245.  
  246.     return new Math_BigInteger($result,256);
  247. }
  248.  
  249. // returns mod(pow($m,$e),$n), where $n should be the product of two (large) primes $p and $q and where $e
  250. // should be a number with the property that gcd($e,($p-1)*($q-1)) == 1.  could just make anything that
  251. // calls this call modexp, instead, but I think this makes things clearer, maybe...
  252.  
  253. function rsa_crypt($m$key{
  254.     echo "\r\nRSA with Math_BigInteger\r\n\r\n(".$m->toString().' ^ '.$key[0]->toString().') % '.$key[1]->toString()."\r\n\r\n";
  255.  
  256.     $start microtime_float();
  257.     $temp $m->modPow($key[0],$key[1]);
  258.     $end microtime_float()-$start;
  259.     echo $temp->toString();
  260.  
  261.     echo "\r\n\r\nElapsed Time == $end\r\n";
  262.  
  263.     return;
  264. }
  265.  
  266. function rsa_crypt2($m$key{
  267.     $m bytes2bcint($m->toBytes());
  268.     $key[0bytes2bcint($key[0]->toBytes());
  269.     $key[1bytes2bcint($key[1]->toBytes());
  270.  
  271.     echo "\r\nRSA with BCMath\r\n\r\n($m ^ {$key[0]}) % {$key[1]}\r\n\r\n";
  272.  
  273.     $start microtime_float();
  274.     $temp = bcpowmod($m,$key[0],$key[1],0);
  275.     $end microtime_float()-$start;
  276.     echo $temp;
  277.  
  278.     echo "\r\n\r\nElapsed Time == $end\r\n";
  279.  
  280.     return;
  281. }
  282.  
  283. function bytes2bcint($x{
  284.     $value = 0;
  285.  
  286.     $len strlen($x);
  287.     $len+= (3*$len)%4; // rounds $len to the nearest 4.
  288.  
  289.     $x str_pad($x,$len,chr(0),STR_PAD_LEFT);
  290.  
  291.     for ($i=0;$i<$len;$i+=4{
  292.         $value = bcmul($value,4294967296)// 4294967296 == 2**32
  293.         $value = bcadd($value,0x1000000*ord($x{$i}((ord($x{$i+1})<<16(ord($x{$i+2})<<8ord($x{$i+3})));
  294.     }
  295.     return $value;
  296. }
  297.  
  298. function bcint2bytes($x{
  299.     $value '';
  300.  
  301.     while (bccomp($x,0> 0{
  302.         $temp = bcmod($x,4294967296);
  303.         $value chr(floor($temp/0x1000000)).chr($temp >> 16).chr($temp >> 8).chr($temp).$value;
  304.         $x = bcdiv($x,4294967296);
  305.     }
  306.  
  307.     return ltrim($value,chr(0));
  308. }
  309.  
  310. function microtime_float({
  311.     list($usec$secexplode(' 'microtime());
  312.     return ((float)$usec + (float)$sec);
  313. }
  314. ?>

Documentation generated on Thu, 16 Nov 2006 21:00:10 -0500 by phpDocumentor 1.3.0. PEAR Logo Copyright © PHP Group 2004.