diff --git a/boot.php b/boot.php index 33102194b..cdd75de8d 100644 --- a/boot.php +++ b/boot.php @@ -9,8 +9,8 @@ require_once('include/language.php'); require_once('include/nav.php'); require_once('include/cache.php'); -define ( 'FRIENDICA_PLATFORM', 'Red'); -define ( 'FRIENDICA_VERSION', trim(file_get_contents('version.inc'))); +define ( 'FRIENDICA_PLATFORM', 'Friendica Red'); +define ( 'FRIENDICA_VERSION', trim(file_get_contents('version.inc')) . 'R'); define ( 'DFRN_PROTOCOL_VERSION', '2.23' ); define ( 'DB_UPDATE_VERSION', 1153 ); @@ -573,7 +573,7 @@ if(! class_exists('App')) { $this->page['htmlhead'] = replace_macros($tpl,array( '$baseurl' => $this->get_baseurl(), // FIXME for z_path!!!! '$local_user' => local_user(), - '$generator' => 'Friendica' . ' ' . FRIENDICA_VERSION, + '$generator' => FRIENDICA_PLATFORM . ' ' . FRIENDICA_VERSION, '$delitem' => t('Delete this item?'), '$comment' => t('Comment'), '$showmore' => t('show more'), @@ -879,8 +879,6 @@ if(! function_exists('login')) { ); } - $noid = get_config('system','no_openid'); - $dest_url = $a->get_baseurl(true) . '/' . $a->query_string; if(local_user()) { @@ -898,11 +896,8 @@ if(! function_exists('login')) { '$logout' => t('Logout'), '$login' => t('Login'), - '$lname' => array('username', t('Nickname or Email address: ') , '', ''), - '$lpassword' => array('password', t('Password: '), '', ''), - - '$openid' => !$noid, - '$lopenid' => array('openid_url', t('Or login using OpenID: '),'',''), + '$lname' => array('username', t('Email') , '', ''), + '$lpassword' => array('password', t('Password'), '', ''), '$hiddens' => $hiddens, diff --git a/include/conversation.php b/include/conversation.php index 7f3980e70..06b643a05 100644 --- a/include/conversation.php +++ b/include/conversation.php @@ -916,6 +916,7 @@ function item_photo_menu($item){ if(! count($a->contacts)) load_contact_links(local_user()); } + $poke_link=""; $contact_url=""; $pm_url=""; $status_link=""; @@ -945,6 +946,7 @@ function item_photo_menu($item){ } } if(($cid) && (! $item['self'])) { + $poke_link = $a->get_baseurl($ssl_state) . '/poke/?f=&c=' . $cid; $contact_url = $a->get_baseurl($ssl_state) . '/contacts/' . $cid; $posts_link = $a->get_baseurl($ssl_state) . '/network/?cid=' . $cid; @@ -967,6 +969,7 @@ function item_photo_menu($item){ t("Network Posts") => $posts_link, t("Edit Contact") => $contact_url, t("Send PM") => $pm_url, + t("Poke") => $poke_link ); @@ -978,7 +981,7 @@ function item_photo_menu($item){ $o = ""; foreach($menu as $k=>$v){ - if ($v!="") $o .= "
- * echo $des->encrypt(substr($plaintext, 0, 8));
- * echo $des->encrypt(substr($plaintext, 8, 8));
- *
- *
- * echo $des->encrypt($plaintext);
- *
- *
- * The solution is to enable the continuous buffer. Although this will resolve the above discrepancy, it creates
- * another, as demonstrated with the following:
- *
- *
- * $des->encrypt(substr($plaintext, 0, 8));
- * echo $des->decrypt($des->encrypt(substr($plaintext, 8, 8)));
- *
- *
- * echo $des->decrypt($des->encrypt(substr($plaintext, 8, 8)));
- *
- *
- * With the continuous buffer disabled, these would yield the same output. With it enabled, they yield different
- * outputs. The reason is due to the fact that the initialization vector's change after every encryption /
- * decryption round when the continuous buffer is enabled. When it's disabled, they remain constant.
- *
- * Put another way, when the continuous buffer is enabled, the state of the Crypt_DES() object changes after each
- * encryption / decryption round, whereas otherwise, it'd remain constant. For this reason, it's recommended that
- * continuous buffers not be used. They do offer better security and are, in fact, sometimes required (SSH uses them),
- * however, they are also less intuitive and more likely to cause you problems.
- *
- * @see Crypt_DES::disableContinuousBuffer()
- * @access public
- */
- function enableContinuousBuffer()
- {
- $this->continuousBuffer = true;
- }
-
- /**
- * Treat consecutive packets as if they are a discontinuous buffer.
- *
- * The default behavior.
- *
- * @see Crypt_DES::enableContinuousBuffer()
- * @access public
- */
- function disableContinuousBuffer()
- {
- $this->continuousBuffer = false;
- $this->encryptIV = $this->iv;
- $this->decryptIV = $this->iv;
- }
-
- /**
- * Pad "packets".
- *
- * DES works by encrypting eight bytes at a time. If you ever need to encrypt or decrypt something that's not
- * a multiple of eight, it becomes necessary to pad the input so that it's length is a multiple of eight.
- *
- * Padding is enabled by default. Sometimes, however, it is undesirable to pad strings. Such is the case in SSH1,
- * where "packets" are padded with random bytes before being encrypted. Unpad these packets and you risk stripping
- * away characters that shouldn't be stripped away. (SSH knows how many bytes are added because the length is
- * transmitted separately)
- *
- * @see Crypt_DES::disablePadding()
- * @access public
- */
- function enablePadding()
- {
- $this->padding = true;
- }
-
- /**
- * Do not pad packets.
- *
- * @see Crypt_DES::enablePadding()
- * @access public
- */
- function disablePadding()
- {
- $this->padding = false;
- }
-
- /**
- * Pads a string
- *
- * Pads a string using the RSA PKCS padding standards so that its length is a multiple of the blocksize (8).
- * 8 - (strlen($text) & 7) bytes are added, each of which is equal to chr(8 - (strlen($text) & 7)
- *
- * If padding is disabled and $text is not a multiple of the blocksize, the string will be padded regardless
- * and padding will, hence forth, be enabled.
- *
- * @see Crypt_DES::_unpad()
- * @access private
- */
- function _pad($text)
- {
- $length = strlen($text);
-
- if (!$this->padding) {
- if (($length & 7) == 0) {
- return $text;
- } else {
- user_error("The plaintext's length ($length) is not a multiple of the block size (8)", E_USER_NOTICE);
- $this->padding = true;
- }
- }
-
- $pad = 8 - ($length & 7);
- return str_pad($text, $length + $pad, chr($pad));
- }
-
- /**
- * Unpads a string
- *
- * If padding is enabled and the reported padding length is invalid the encryption key will be assumed to be wrong
- * and false will be returned.
- *
- * @see Crypt_DES::_pad()
- * @access private
- */
- function _unpad($text)
- {
- if (!$this->padding) {
- return $text;
- }
-
- $length = ord($text[strlen($text) - 1]);
-
- if (!$length || $length > 8) {
- return false;
- }
-
- return substr($text, 0, -$length);
- }
-
- /**
- * Encrypts or decrypts a 64-bit block
- *
- * $mode should be either CRYPT_DES_ENCRYPT or CRYPT_DES_DECRYPT. See
- * {@link http://en.wikipedia.org/wiki/Image:Feistel.png Feistel.png} to get a general
- * idea of what this function does.
- *
- * @access private
- * @param String $block
- * @param Integer $mode
- * @return String
- */
- function _processBlock($block, $mode)
- {
- // s-boxes. in the official DES docs, they're described as being matrices that
- // one accesses by using the first and last bits to determine the row and the
- // middle four bits to determine the column. in this implementation, they've
- // been converted to vectors
- static $sbox = array(
- array(
- 14, 0, 4, 15, 13, 7, 1, 4, 2, 14, 15, 2, 11, 13, 8, 1,
- 3, 10 ,10, 6, 6, 12, 12, 11, 5, 9, 9, 5, 0, 3, 7, 8,
- 4, 15, 1, 12, 14, 8, 8, 2, 13, 4, 6, 9, 2, 1, 11, 7,
- 15, 5, 12, 11, 9, 3, 7, 14, 3, 10, 10, 0, 5, 6, 0, 13
- ),
- array(
- 15, 3, 1, 13, 8, 4, 14, 7, 6, 15, 11, 2, 3, 8, 4, 14,
- 9, 12, 7, 0, 2, 1, 13, 10, 12, 6, 0, 9, 5, 11, 10, 5,
- 0, 13, 14, 8, 7, 10, 11, 1, 10, 3, 4, 15, 13, 4, 1, 2,
- 5, 11, 8, 6, 12, 7, 6, 12, 9, 0, 3, 5, 2, 14, 15, 9
- ),
- array(
- 10, 13, 0, 7, 9, 0, 14, 9, 6, 3, 3, 4, 15, 6, 5, 10,
- 1, 2, 13, 8, 12, 5, 7, 14, 11, 12, 4, 11, 2, 15, 8, 1,
- 13, 1, 6, 10, 4, 13, 9, 0, 8, 6, 15, 9, 3, 8, 0, 7,
- 11, 4, 1, 15, 2, 14, 12, 3, 5, 11, 10, 5, 14, 2, 7, 12
- ),
- array(
- 7, 13, 13, 8, 14, 11, 3, 5, 0, 6, 6, 15, 9, 0, 10, 3,
- 1, 4, 2, 7, 8, 2, 5, 12, 11, 1, 12, 10, 4, 14, 15, 9,
- 10, 3, 6, 15, 9, 0, 0, 6, 12, 10, 11, 1, 7, 13, 13, 8,
- 15, 9, 1, 4, 3, 5, 14, 11, 5, 12, 2, 7, 8, 2, 4, 14
- ),
- array(
- 2, 14, 12, 11, 4, 2, 1, 12, 7, 4, 10, 7, 11, 13, 6, 1,
- 8, 5, 5, 0, 3, 15, 15, 10, 13, 3, 0, 9, 14, 8, 9, 6,
- 4, 11, 2, 8, 1, 12, 11, 7, 10, 1, 13, 14, 7, 2, 8, 13,
- 15, 6, 9, 15, 12, 0, 5, 9, 6, 10, 3, 4, 0, 5, 14, 3
- ),
- array(
- 12, 10, 1, 15, 10, 4, 15, 2, 9, 7, 2, 12, 6, 9, 8, 5,
- 0, 6, 13, 1, 3, 13, 4, 14, 14, 0, 7, 11, 5, 3, 11, 8,
- 9, 4, 14, 3, 15, 2, 5, 12, 2, 9, 8, 5, 12, 15, 3, 10,
- 7, 11, 0, 14, 4, 1, 10, 7, 1, 6, 13, 0, 11, 8, 6, 13
- ),
- array(
- 4, 13, 11, 0, 2, 11, 14, 7, 15, 4, 0, 9, 8, 1, 13, 10,
- 3, 14, 12, 3, 9, 5, 7, 12, 5, 2, 10, 15, 6, 8, 1, 6,
- 1, 6, 4, 11, 11, 13, 13, 8, 12, 1, 3, 4, 7, 10, 14, 7,
- 10, 9, 15, 5, 6, 0, 8, 15, 0, 14, 5, 2, 9, 3, 2, 12
- ),
- array(
- 13, 1, 2, 15, 8, 13, 4, 8, 6, 10, 15, 3, 11, 7, 1, 4,
- 10, 12, 9, 5, 3, 6, 14, 11, 5, 0, 0, 14, 12, 9, 7, 2,
- 7, 2, 11, 1, 4, 14, 1, 7, 9, 4, 12, 10, 14, 8, 2, 13,
- 0, 15, 6, 12, 10, 9, 13, 0, 15, 3, 3, 5, 5, 6, 8, 11
- )
- );
-
- $keys = $this->keys;
-
- $temp = unpack('Na/Nb', $block);
- $block = array($temp['a'], $temp['b']);
-
- // because php does arithmetic right shifts, if the most significant bits are set, right
- // shifting those into the correct position will add 1's - not 0's. this will intefere
- // with the | operation unless a second & is done. so we isolate these bits and left shift
- // them into place. we then & each block with 0x7FFFFFFF to prevennt 1's from being added
- // for any other shifts.
- $msb = array(
- ($block[0] >> 31) & 1,
- ($block[1] >> 31) & 1
- );
- $block[0] &= 0x7FFFFFFF;
- $block[1] &= 0x7FFFFFFF;
-
- // we isolate the appropriate bit in the appropriate integer and shift as appropriate. in
- // some cases, there are going to be multiple bits in the same integer that need to be shifted
- // in the same way. we combine those into one shift operation.
- $block = array(
- (($block[1] & 0x00000040) << 25) | (($block[1] & 0x00004000) << 16) |
- (($block[1] & 0x00400001) << 7) | (($block[1] & 0x40000100) >> 2) |
- (($block[0] & 0x00000040) << 21) | (($block[0] & 0x00004000) << 12) |
- (($block[0] & 0x00400001) << 3) | (($block[0] & 0x40000100) >> 6) |
- (($block[1] & 0x00000010) << 19) | (($block[1] & 0x00001000) << 10) |
- (($block[1] & 0x00100000) << 1) | (($block[1] & 0x10000000) >> 8) |
- (($block[0] & 0x00000010) << 15) | (($block[0] & 0x00001000) << 6) |
- (($block[0] & 0x00100000) >> 3) | (($block[0] & 0x10000000) >> 12) |
- (($block[1] & 0x00000004) << 13) | (($block[1] & 0x00000400) << 4) |
- (($block[1] & 0x00040000) >> 5) | (($block[1] & 0x04000000) >> 14) |
- (($block[0] & 0x00000004) << 9) | ( $block[0] & 0x00000400 ) |
- (($block[0] & 0x00040000) >> 9) | (($block[0] & 0x04000000) >> 18) |
- (($block[1] & 0x00010000) >> 11) | (($block[1] & 0x01000000) >> 20) |
- (($block[0] & 0x00010000) >> 15) | (($block[0] & 0x01000000) >> 24)
- ,
- (($block[1] & 0x00000080) << 24) | (($block[1] & 0x00008000) << 15) |
- (($block[1] & 0x00800002) << 6) | (($block[0] & 0x00000080) << 20) |
- (($block[0] & 0x00008000) << 11) | (($block[0] & 0x00800002) << 2) |
- (($block[1] & 0x00000020) << 18) | (($block[1] & 0x00002000) << 9) |
- ( $block[1] & 0x00200000 ) | (($block[1] & 0x20000000) >> 9) |
- (($block[0] & 0x00000020) << 14) | (($block[0] & 0x00002000) << 5) |
- (($block[0] & 0x00200000) >> 4) | (($block[0] & 0x20000000) >> 13) |
- (($block[1] & 0x00000008) << 12) | (($block[1] & 0x00000800) << 3) |
- (($block[1] & 0x00080000) >> 6) | (($block[1] & 0x08000000) >> 15) |
- (($block[0] & 0x00000008) << 8) | (($block[0] & 0x00000800) >> 1) |
- (($block[0] & 0x00080000) >> 10) | (($block[0] & 0x08000000) >> 19) |
- (($block[1] & 0x00000200) >> 3) | (($block[0] & 0x00000200) >> 7) |
- (($block[1] & 0x00020000) >> 12) | (($block[1] & 0x02000000) >> 21) |
- (($block[0] & 0x00020000) >> 16) | (($block[0] & 0x02000000) >> 25) |
- ($msb[1] << 28) | ($msb[0] << 24)
- );
-
- for ($i = 0; $i < 16; $i++) {
- // start of "the Feistel (F) function" - see the following URL:
- // http://en.wikipedia.org/wiki/Image:Data_Encryption_Standard_InfoBox_Diagram.png
- $temp = (($sbox[0][((($block[1] >> 27) & 0x1F) | (($block[1] & 1) << 5)) ^ $keys[$mode][$i][0]]) << 28)
- | (($sbox[1][(($block[1] & 0x1F800000) >> 23) ^ $keys[$mode][$i][1]]) << 24)
- | (($sbox[2][(($block[1] & 0x01F80000) >> 19) ^ $keys[$mode][$i][2]]) << 20)
- | (($sbox[3][(($block[1] & 0x001F8000) >> 15) ^ $keys[$mode][$i][3]]) << 16)
- | (($sbox[4][(($block[1] & 0x0001F800) >> 11) ^ $keys[$mode][$i][4]]) << 12)
- | (($sbox[5][(($block[1] & 0x00001F80) >> 7) ^ $keys[$mode][$i][5]]) << 8)
- | (($sbox[6][(($block[1] & 0x000001F8) >> 3) ^ $keys[$mode][$i][6]]) << 4)
- | ( $sbox[7][((($block[1] & 0x1F) << 1) | (($block[1] >> 31) & 1)) ^ $keys[$mode][$i][7]]);
-
- $msb = ($temp >> 31) & 1;
- $temp &= 0x7FFFFFFF;
- $newBlock = (($temp & 0x00010000) << 15) | (($temp & 0x02020120) << 5)
- | (($temp & 0x00001800) << 17) | (($temp & 0x01000000) >> 10)
- | (($temp & 0x00000008) << 24) | (($temp & 0x00100000) << 6)
- | (($temp & 0x00000010) << 21) | (($temp & 0x00008000) << 9)
- | (($temp & 0x00000200) << 12) | (($temp & 0x10000000) >> 27)
- | (($temp & 0x00000040) << 14) | (($temp & 0x08000000) >> 8)
- | (($temp & 0x00004000) << 4) | (($temp & 0x00000002) << 16)
- | (($temp & 0x00442000) >> 6) | (($temp & 0x40800000) >> 15)
- | (($temp & 0x00000001) << 11) | (($temp & 0x20000000) >> 20)
- | (($temp & 0x00080000) >> 13) | (($temp & 0x00000004) << 3)
- | (($temp & 0x04000000) >> 22) | (($temp & 0x00000480) >> 7)
- | (($temp & 0x00200000) >> 19) | ($msb << 23);
- // end of "the Feistel (F) function" - $newBlock is F's output
-
- $temp = $block[1];
- $block[1] = $block[0] ^ $newBlock;
- $block[0] = $temp;
- }
-
- $msb = array(
- ($block[0] >> 31) & 1,
- ($block[1] >> 31) & 1
- );
- $block[0] &= 0x7FFFFFFF;
- $block[1] &= 0x7FFFFFFF;
-
- $block = array(
- (($block[0] & 0x01000004) << 7) | (($block[1] & 0x01000004) << 6) |
- (($block[0] & 0x00010000) << 13) | (($block[1] & 0x00010000) << 12) |
- (($block[0] & 0x00000100) << 19) | (($block[1] & 0x00000100) << 18) |
- (($block[0] & 0x00000001) << 25) | (($block[1] & 0x00000001) << 24) |
- (($block[0] & 0x02000008) >> 2) | (($block[1] & 0x02000008) >> 3) |
- (($block[0] & 0x00020000) << 4) | (($block[1] & 0x00020000) << 3) |
- (($block[0] & 0x00000200) << 10) | (($block[1] & 0x00000200) << 9) |
- (($block[0] & 0x00000002) << 16) | (($block[1] & 0x00000002) << 15) |
- (($block[0] & 0x04000000) >> 11) | (($block[1] & 0x04000000) >> 12) |
- (($block[0] & 0x00040000) >> 5) | (($block[1] & 0x00040000) >> 6) |
- (($block[0] & 0x00000400) << 1) | ( $block[1] & 0x00000400 ) |
- (($block[0] & 0x08000000) >> 20) | (($block[1] & 0x08000000) >> 21) |
- (($block[0] & 0x00080000) >> 14) | (($block[1] & 0x00080000) >> 15) |
- (($block[0] & 0x00000800) >> 8) | (($block[1] & 0x00000800) >> 9)
- ,
- (($block[0] & 0x10000040) << 3) | (($block[1] & 0x10000040) << 2) |
- (($block[0] & 0x00100000) << 9) | (($block[1] & 0x00100000) << 8) |
- (($block[0] & 0x00001000) << 15) | (($block[1] & 0x00001000) << 14) |
- (($block[0] & 0x00000010) << 21) | (($block[1] & 0x00000010) << 20) |
- (($block[0] & 0x20000080) >> 6) | (($block[1] & 0x20000080) >> 7) |
- ( $block[0] & 0x00200000 ) | (($block[1] & 0x00200000) >> 1) |
- (($block[0] & 0x00002000) << 6) | (($block[1] & 0x00002000) << 5) |
- (($block[0] & 0x00000020) << 12) | (($block[1] & 0x00000020) << 11) |
- (($block[0] & 0x40000000) >> 15) | (($block[1] & 0x40000000) >> 16) |
- (($block[0] & 0x00400000) >> 9) | (($block[1] & 0x00400000) >> 10) |
- (($block[0] & 0x00004000) >> 3) | (($block[1] & 0x00004000) >> 4) |
- (($block[0] & 0x00800000) >> 18) | (($block[1] & 0x00800000) >> 19) |
- (($block[0] & 0x00008000) >> 12) | (($block[1] & 0x00008000) >> 13) |
- ($msb[0] << 7) | ($msb[1] << 6)
- );
-
- return pack('NN', $block[0], $block[1]);
- }
-
- /**
- * Creates the key schedule.
- *
- * @access private
- * @param String $key
- * @return Array
- */
- function _prepareKey($key)
- {
- static $shifts = array( // number of key bits shifted per round
- 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1
- );
-
- // pad the key and remove extra characters as appropriate.
- $key = str_pad(substr($key, 0, 8), 8, chr(0));
-
- $temp = unpack('Na/Nb', $key);
- $key = array($temp['a'], $temp['b']);
- $msb = array(
- ($key[0] >> 31) & 1,
- ($key[1] >> 31) & 1
- );
- $key[0] &= 0x7FFFFFFF;
- $key[1] &= 0x7FFFFFFF;
-
- $key = array(
- (($key[1] & 0x00000002) << 26) | (($key[1] & 0x00000204) << 17) |
- (($key[1] & 0x00020408) << 8) | (($key[1] & 0x02040800) >> 1) |
- (($key[0] & 0x00000002) << 22) | (($key[0] & 0x00000204) << 13) |
- (($key[0] & 0x00020408) << 4) | (($key[0] & 0x02040800) >> 5) |
- (($key[1] & 0x04080000) >> 10) | (($key[0] & 0x04080000) >> 14) |
- (($key[1] & 0x08000000) >> 19) | (($key[0] & 0x08000000) >> 23) |
- (($key[0] & 0x00000010) >> 1) | (($key[0] & 0x00001000) >> 10) |
- (($key[0] & 0x00100000) >> 19) | (($key[0] & 0x10000000) >> 28)
- ,
- (($key[1] & 0x00000080) << 20) | (($key[1] & 0x00008000) << 11) |
- (($key[1] & 0x00800000) << 2) | (($key[0] & 0x00000080) << 16) |
- (($key[0] & 0x00008000) << 7) | (($key[0] & 0x00800000) >> 2) |
- (($key[1] & 0x00000040) << 13) | (($key[1] & 0x00004000) << 4) |
- (($key[1] & 0x00400000) >> 5) | (($key[1] & 0x40000000) >> 14) |
- (($key[0] & 0x00000040) << 9) | ( $key[0] & 0x00004000 ) |
- (($key[0] & 0x00400000) >> 9) | (($key[0] & 0x40000000) >> 18) |
- (($key[1] & 0x00000020) << 6) | (($key[1] & 0x00002000) >> 3) |
- (($key[1] & 0x00200000) >> 12) | (($key[1] & 0x20000000) >> 21) |
- (($key[0] & 0x00000020) << 2) | (($key[0] & 0x00002000) >> 7) |
- (($key[0] & 0x00200000) >> 16) | (($key[0] & 0x20000000) >> 25) |
- (($key[1] & 0x00000010) >> 1) | (($key[1] & 0x00001000) >> 10) |
- (($key[1] & 0x00100000) >> 19) | (($key[1] & 0x10000000) >> 28) |
- ($msb[1] << 24) | ($msb[0] << 20)
- );
-
- $keys = array();
- for ($i = 0; $i < 16; $i++) {
- $key[0] <<= $shifts[$i];
- $temp = ($key[0] & 0xF0000000) >> 28;
- $key[0] = ($key[0] | $temp) & 0x0FFFFFFF;
-
- $key[1] <<= $shifts[$i];
- $temp = ($key[1] & 0xF0000000) >> 28;
- $key[1] = ($key[1] | $temp) & 0x0FFFFFFF;
-
- $temp = array(
- (($key[1] & 0x00004000) >> 9) | (($key[1] & 0x00000800) >> 7) |
- (($key[1] & 0x00020000) >> 14) | (($key[1] & 0x00000010) >> 2) |
- (($key[1] & 0x08000000) >> 26) | (($key[1] & 0x00800000) >> 23)
- ,
- (($key[1] & 0x02400000) >> 20) | (($key[1] & 0x00000001) << 4) |
- (($key[1] & 0x00002000) >> 10) | (($key[1] & 0x00040000) >> 18) |
- (($key[1] & 0x00000080) >> 6)
- ,
- ( $key[1] & 0x00000020 ) | (($key[1] & 0x00000200) >> 5) |
- (($key[1] & 0x00010000) >> 13) | (($key[1] & 0x01000000) >> 22) |
- (($key[1] & 0x00000004) >> 1) | (($key[1] & 0x00100000) >> 20)
- ,
- (($key[1] & 0x00001000) >> 7) | (($key[1] & 0x00200000) >> 17) |
- (($key[1] & 0x00000002) << 2) | (($key[1] & 0x00000100) >> 6) |
- (($key[1] & 0x00008000) >> 14) | (($key[1] & 0x04000000) >> 26)
- ,
- (($key[0] & 0x00008000) >> 10) | ( $key[0] & 0x00000010 ) |
- (($key[0] & 0x02000000) >> 22) | (($key[0] & 0x00080000) >> 17) |
- (($key[0] & 0x00000200) >> 8) | (($key[0] & 0x00000002) >> 1)
- ,
- (($key[0] & 0x04000000) >> 21) | (($key[0] & 0x00010000) >> 12) |
- (($key[0] & 0x00000020) >> 2) | (($key[0] & 0x00000800) >> 9) |
- (($key[0] & 0x00800000) >> 22) | (($key[0] & 0x00000100) >> 8)
- ,
- (($key[0] & 0x00001000) >> 7) | (($key[0] & 0x00000088) >> 3) |
- (($key[0] & 0x00020000) >> 14) | (($key[0] & 0x00000001) << 2) |
- (($key[0] & 0x00400000) >> 21)
- ,
- (($key[0] & 0x00000400) >> 5) | (($key[0] & 0x00004000) >> 10) |
- (($key[0] & 0x00000040) >> 3) | (($key[0] & 0x00100000) >> 18) |
- (($key[0] & 0x08000000) >> 26) | (($key[0] & 0x01000000) >> 24)
- );
-
- $keys[] = $temp;
- }
-
- $temp = array(
- CRYPT_DES_ENCRYPT => $keys,
- CRYPT_DES_DECRYPT => array_reverse($keys)
- );
-
- return $temp;
- }
-}
-
-// vim: ts=4:sw=4:et:
-// vim6: fdl=1:
\ No newline at end of file
diff --git a/library/phpsec/Crypt/Hash.php b/library/phpsec/Crypt/Hash.php
deleted file mode 100644
index ef3a85802..000000000
--- a/library/phpsec/Crypt/Hash.php
+++ /dev/null
@@ -1,816 +0,0 @@
-
- * setKey('abcdefg');
- *
- * echo base64_encode($hash->hash('abcdefg'));
- * ?>
- *
- *
- * LICENSE: This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
- * MA 02111-1307 USA
- *
- * @category Crypt
- * @package Crypt_Hash
- * @author Jim Wigginton
- * echo $rc4->encrypt(substr($plaintext, 0, 8));
- * echo $rc4->encrypt(substr($plaintext, 8, 8));
- *
- *
- * echo $rc4->encrypt($plaintext);
- *
- *
- * The solution is to enable the continuous buffer. Although this will resolve the above discrepancy, it creates
- * another, as demonstrated with the following:
- *
- *
- * $rc4->encrypt(substr($plaintext, 0, 8));
- * echo $rc4->decrypt($des->encrypt(substr($plaintext, 8, 8)));
- *
- *
- * echo $rc4->decrypt($des->encrypt(substr($plaintext, 8, 8)));
- *
- *
- * With the continuous buffer disabled, these would yield the same output. With it enabled, they yield different
- * outputs. The reason is due to the fact that the initialization vector's change after every encryption /
- * decryption round when the continuous buffer is enabled. When it's disabled, they remain constant.
- *
- * Put another way, when the continuous buffer is enabled, the state of the Crypt_DES() object changes after each
- * encryption / decryption round, whereas otherwise, it'd remain constant. For this reason, it's recommended that
- * continuous buffers not be used. They do offer better security and are, in fact, sometimes required (SSH uses them),
- * however, they are also less intuitive and more likely to cause you problems.
- *
- * @see Crypt_RC4::disableContinuousBuffer()
- * @access public
- */
- function enableContinuousBuffer()
- {
- $this->continuousBuffer = true;
- }
-
- /**
- * Treat consecutive packets as if they are a discontinuous buffer.
- *
- * The default behavior.
- *
- * @see Crypt_RC4::enableContinuousBuffer()
- * @access public
- */
- function disableContinuousBuffer()
- {
- if ( CRYPT_RC4_MODE == CRYPT_RC4_MODE_INTERNAL ) {
- $this->encryptIndex = $this->decryptIndex = array(0, 0);
- $this->setKey($this->key);
- }
-
- $this->continuousBuffer = false;
- }
-
- /**
- * Dummy function.
- *
- * Since RC4 is a stream cipher and not a block cipher, no padding is necessary. The only reason this function is
- * included is so that you can switch between a block cipher and a stream cipher transparently.
- *
- * @see Crypt_RC4::disablePadding()
- * @access public
- */
- function enablePadding()
- {
- }
-
- /**
- * Dummy function.
- *
- * @see Crypt_RC4::enablePadding()
- * @access public
- */
- function disablePadding()
- {
- }
-
- /**
- * Class destructor.
- *
- * Will be called, automatically, if you're using PHP5. If you're using PHP4, call it yourself. Only really
- * needs to be called if mcrypt is being used.
- *
- * @access public
- */
- function __destruct()
- {
- if ( CRYPT_RC4_MODE == CRYPT_RC4_MODE_MCRYPT ) {
- $this->_closeMCrypt();
- }
- }
-
- /**
- * Properly close the MCrypt objects.
- *
- * @access prviate
- */
- function _closeMCrypt()
- {
- if ( $this->encryptStream !== false ) {
- if ( $this->continuousBuffer ) {
- mcrypt_generic_deinit($this->encryptStream);
- }
-
- mcrypt_module_close($this->encryptStream);
-
- $this->encryptStream = false;
- }
-
- if ( $this->decryptStream !== false ) {
- if ( $this->continuousBuffer ) {
- mcrypt_generic_deinit($this->decryptStream);
- }
-
- mcrypt_module_close($this->decryptStream);
-
- $this->decryptStream = false;
- }
- }
-}
\ No newline at end of file
diff --git a/library/phpsec/Crypt/RSA.php b/library/phpsec/Crypt/RSA.php
deleted file mode 100644
index 1c562082b..000000000
--- a/library/phpsec/Crypt/RSA.php
+++ /dev/null
@@ -1,2119 +0,0 @@
-
- * createKey());
- *
- * $plaintext = 'terrafrost';
- *
- * $rsa->loadKey($privatekey);
- * $ciphertext = $rsa->encrypt($plaintext);
- *
- * $rsa->loadKey($publickey);
- * echo $rsa->decrypt($ciphertext);
- * ?>
- *
- *
- * Here's an example of how to create signatures and verify signatures with this library:
- *
- * createKey());
- *
- * $plaintext = 'terrafrost';
- *
- * $rsa->loadKey($privatekey);
- * $signature = $rsa->sign($plaintext);
- *
- * $rsa->loadKey($publickey);
- * echo $rsa->verify($plaintext, $signature) ? 'verified' : 'unverified';
- * ?>
- *
- *
- * LICENSE: This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
- * MA 02111-1307 USA
- *
- * @category Crypt
- * @package Crypt_RSA
- * @author Jim Wigginton
- * echo $rijndael->encrypt(substr($plaintext, 0, 16));
- * echo $rijndael->encrypt(substr($plaintext, 16, 16));
- *
- *
- * echo $rijndael->encrypt($plaintext);
- *
- *
- * The solution is to enable the continuous buffer. Although this will resolve the above discrepancy, it creates
- * another, as demonstrated with the following:
- *
- *
- * $rijndael->encrypt(substr($plaintext, 0, 16));
- * echo $rijndael->decrypt($des->encrypt(substr($plaintext, 16, 16)));
- *
- *
- * echo $rijndael->decrypt($des->encrypt(substr($plaintext, 16, 16)));
- *
- *
- * With the continuous buffer disabled, these would yield the same output. With it enabled, they yield different
- * outputs. The reason is due to the fact that the initialization vector's change after every encryption /
- * decryption round when the continuous buffer is enabled. When it's disabled, they remain constant.
- *
- * Put another way, when the continuous buffer is enabled, the state of the Crypt_Rijndael() object changes after each
- * encryption / decryption round, whereas otherwise, it'd remain constant. For this reason, it's recommended that
- * continuous buffers not be used. They do offer better security and are, in fact, sometimes required (SSH uses them),
- * however, they are also less intuitive and more likely to cause you problems.
- *
- * @see Crypt_Rijndael::disableContinuousBuffer()
- * @access public
- */
- function enableContinuousBuffer()
- {
- $this->continuousBuffer = true;
- }
-
- /**
- * Treat consecutive packets as if they are a discontinuous buffer.
- *
- * The default behavior.
- *
- * @see Crypt_Rijndael::enableContinuousBuffer()
- * @access public
- */
- function disableContinuousBuffer()
- {
- $this->continuousBuffer = false;
- $this->encryptIV = $this->iv;
- $this->decryptIV = $this->iv;
- }
-
- /**
- * String Shift
- *
- * Inspired by array_shift
- *
- * @param String $string
- * @param optional Integer $index
- * @return String
- * @access private
- */
- function _string_shift(&$string, $index = 1)
- {
- $substr = substr($string, 0, $index);
- $string = substr($string, $index);
- return $substr;
- }
-}
-
-// vim: ts=4:sw=4:et:
-// vim6: fdl=1:
\ No newline at end of file
diff --git a/library/phpsec/Crypt/TripleDES.php b/library/phpsec/Crypt/TripleDES.php
deleted file mode 100644
index 4d0dbbca0..000000000
--- a/library/phpsec/Crypt/TripleDES.php
+++ /dev/null
@@ -1,690 +0,0 @@
-
- * setKey('abcdefghijklmnopqrstuvwx');
- *
- * $size = 10 * 1024;
- * $plaintext = '';
- * for ($i = 0; $i < $size; $i++) {
- * $plaintext.= 'a';
- * }
- *
- * echo $des->decrypt($des->encrypt($plaintext));
- * ?>
- *
- *
- * LICENSE: This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
- * MA 02111-1307 USA
- *
- * @category Crypt
- * @package Crypt_TripleDES
- * @author Jim Wigginton
- * echo $des->encrypt(substr($plaintext, 0, 8));
- * echo $des->encrypt(substr($plaintext, 8, 8));
- *
- *
- * echo $des->encrypt($plaintext);
- *
- *
- * The solution is to enable the continuous buffer. Although this will resolve the above discrepancy, it creates
- * another, as demonstrated with the following:
- *
- *
- * $des->encrypt(substr($plaintext, 0, 8));
- * echo $des->decrypt($des->encrypt(substr($plaintext, 8, 8)));
- *
- *
- * echo $des->decrypt($des->encrypt(substr($plaintext, 8, 8)));
- *
- *
- * With the continuous buffer disabled, these would yield the same output. With it enabled, they yield different
- * outputs. The reason is due to the fact that the initialization vector's change after every encryption /
- * decryption round when the continuous buffer is enabled. When it's disabled, they remain constant.
- *
- * Put another way, when the continuous buffer is enabled, the state of the Crypt_DES() object changes after each
- * encryption / decryption round, whereas otherwise, it'd remain constant. For this reason, it's recommended that
- * continuous buffers not be used. They do offer better security and are, in fact, sometimes required (SSH uses them),
- * however, they are also less intuitive and more likely to cause you problems.
- *
- * @see Crypt_TripleDES::disableContinuousBuffer()
- * @access public
- */
- function enableContinuousBuffer()
- {
- $this->continuousBuffer = true;
- if ($this->mode == CRYPT_DES_MODE_3CBC) {
- $this->des[0]->enableContinuousBuffer();
- $this->des[1]->enableContinuousBuffer();
- $this->des[2]->enableContinuousBuffer();
- }
- }
-
- /**
- * Treat consecutive packets as if they are a discontinuous buffer.
- *
- * The default behavior.
- *
- * @see Crypt_TripleDES::enableContinuousBuffer()
- * @access public
- */
- function disableContinuousBuffer()
- {
- $this->continuousBuffer = false;
- $this->encryptIV = $this->iv;
- $this->decryptIV = $this->iv;
-
- if ($this->mode == CRYPT_DES_MODE_3CBC) {
- $this->des[0]->disableContinuousBuffer();
- $this->des[1]->disableContinuousBuffer();
- $this->des[2]->disableContinuousBuffer();
- }
- }
-
- /**
- * Pad "packets".
- *
- * DES works by encrypting eight bytes at a time. If you ever need to encrypt or decrypt something that's not
- * a multiple of eight, it becomes necessary to pad the input so that it's length is a multiple of eight.
- *
- * Padding is enabled by default. Sometimes, however, it is undesirable to pad strings. Such is the case in SSH1,
- * where "packets" are padded with random bytes before being encrypted. Unpad these packets and you risk stripping
- * away characters that shouldn't be stripped away. (SSH knows how many bytes are added because the length is
- * transmitted separately)
- *
- * @see Crypt_TripleDES::disablePadding()
- * @access public
- */
- function enablePadding()
- {
- $this->padding = true;
- }
-
- /**
- * Do not pad packets.
- *
- * @see Crypt_TripleDES::enablePadding()
- * @access public
- */
- function disablePadding()
- {
- $this->padding = false;
- }
-
- /**
- * Pads a string
- *
- * Pads a string using the RSA PKCS padding standards so that its length is a multiple of the blocksize (8).
- * 8 - (strlen($text) & 7) bytes are added, each of which is equal to chr(8 - (strlen($text) & 7)
- *
- * If padding is disabled and $text is not a multiple of the blocksize, the string will be padded regardless
- * and padding will, hence forth, be enabled.
- *
- * @see Crypt_TripleDES::_unpad()
- * @access private
- */
- function _pad($text)
- {
- $length = strlen($text);
-
- if (!$this->padding) {
- if (($length & 7) == 0) {
- return $text;
- } else {
- user_error("The plaintext's length ($length) is not a multiple of the block size (8)", E_USER_NOTICE);
- $this->padding = true;
- }
- }
-
- $pad = 8 - ($length & 7);
- return str_pad($text, $length + $pad, chr($pad));
- }
-
- /**
- * Unpads a string
- *
- * If padding is enabled and the reported padding length is invalid the encryption key will be assumed to be wrong
- * and false will be returned.
- *
- * @see Crypt_TripleDES::_pad()
- * @access private
- */
- function _unpad($text)
- {
- if (!$this->padding) {
- return $text;
- }
-
- $length = ord($text[strlen($text) - 1]);
-
- if (!$length || $length > 8) {
- return false;
- }
-
- return substr($text, 0, -$length);
- }
-}
-
-// vim: ts=4:sw=4:et:
-// vim6: fdl=1:
\ No newline at end of file
diff --git a/library/phpsec/Math/BigInteger.php b/library/phpsec/Math/BigInteger.php
deleted file mode 100644
index 5b3a4fc8b..000000000
--- a/library/phpsec/Math/BigInteger.php
+++ /dev/null
@@ -1,3545 +0,0 @@
-> and << cannot be used, nor can the modulo operator %,
- * which only supports integers. Although this fact will slow this library down, the fact that such a high
- * base is being used should more than compensate.
- *
- * When PHP version 6 is officially released, we'll be able to use 64-bit integers. This should, once again,
- * allow bitwise operators, and will increase the maximum possible base to 2**31 (or 2**62 for addition /
- * subtraction).
- *
- * Numbers are stored in {@link http://en.wikipedia.org/wiki/Endianness little endian} format. ie.
- * (new Math_BigInteger(pow(2, 26)))->value = array(0, 1)
- *
- * Useful resources are as follows:
- *
- * - {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf Handbook of Applied Cryptography (HAC)}
- * - {@link http://math.libtomcrypt.com/files/tommath.pdf Multi-Precision Math (MPM)}
- * - Java's BigInteger classes. See /j2se/src/share/classes/java/math in jdk-1_5_0-src-jrl.zip
- *
- * Here's an example of how to use this library:
- *
- * add($b);
- *
- * echo $c->toString(); // outputs 5
- * ?>
- *
- *
- * LICENSE: This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
- * MA 02111-1307 USA
- *
- * @category Math
- * @package Math_BigInteger
- * @author Jim Wigginton
- * toString(); // outputs 50
- * ?>
- *
- *
- * @param optional $x base-10 number or base-$base number if $base set.
- * @param optional integer $base
- * @return Math_BigInteger
- * @access public
- */
- function Math_BigInteger($x = 0, $base = 10)
- {
- if ( !defined('MATH_BIGINTEGER_MODE') ) {
- switch (true) {
- case extension_loaded('gmp'):
- define('MATH_BIGINTEGER_MODE', MATH_BIGINTEGER_MODE_GMP);
- break;
- case extension_loaded('bcmath'):
- define('MATH_BIGINTEGER_MODE', MATH_BIGINTEGER_MODE_BCMATH);
- break;
- default:
- define('MATH_BIGINTEGER_MODE', MATH_BIGINTEGER_MODE_INTERNAL);
- }
- }
-
- switch ( MATH_BIGINTEGER_MODE ) {
- case MATH_BIGINTEGER_MODE_GMP:
- if (is_resource($x) && get_resource_type($x) == 'GMP integer') {
- $this->value = $x;
- return;
- }
- $this->value = gmp_init(0);
- break;
- case MATH_BIGINTEGER_MODE_BCMATH:
- $this->value = '0';
- break;
- default:
- $this->value = array();
- }
-
- if (empty($x)) {
- return;
- }
-
- switch ($base) {
- case -256:
- if (ord($x[0]) & 0x80) {
- $x = ~$x;
- $this->is_negative = true;
- }
- case 256:
- switch ( MATH_BIGINTEGER_MODE ) {
- case MATH_BIGINTEGER_MODE_GMP:
- $sign = $this->is_negative ? '-' : '';
- $this->value = gmp_init($sign . '0x' . bin2hex($x));
- break;
- case MATH_BIGINTEGER_MODE_BCMATH:
- // round $len to the nearest 4 (thanks, DavidMJ!)
- $len = (strlen($x) + 3) & 0xFFFFFFFC;
-
- $x = str_pad($x, $len, chr(0), STR_PAD_LEFT);
-
- for ($i = 0; $i < $len; $i+= 4) {
- $this->value = bcmul($this->value, '4294967296', 0); // 4294967296 == 2**32
- $this->value = bcadd($this->value, 0x1000000 * ord($x[$i]) + ((ord($x[$i + 1]) << 16) | (ord($x[$i + 2]) << 8) | ord($x[$i + 3])), 0);
- }
-
- if ($this->is_negative) {
- $this->value = '-' . $this->value;
- }
-
- break;
- // converts a base-2**8 (big endian / msb) number to base-2**26 (little endian / lsb)
- default:
- while (strlen($x)) {
- $this->value[] = $this->_bytes2int($this->_base256_rshift($x, 26));
- }
- }
-
- if ($this->is_negative) {
- if (MATH_BIGINTEGER_MODE != MATH_BIGINTEGER_MODE_INTERNAL) {
- $this->is_negative = false;
- }
- $temp = $this->add(new Math_BigInteger('-1'));
- $this->value = $temp->value;
- }
- break;
- case 16:
- case -16:
- if ($base > 0 && $x[0] == '-') {
- $this->is_negative = true;
- $x = substr($x, 1);
- }
-
- $x = preg_replace('#^(?:0x)?([A-Fa-f0-9]*).*#', '$1', $x);
-
- $is_negative = false;
- if ($base < 0 && hexdec($x[0]) >= 8) {
- $this->is_negative = $is_negative = true;
- $x = bin2hex(~pack('H*', $x));
- }
-
- switch ( MATH_BIGINTEGER_MODE ) {
- case MATH_BIGINTEGER_MODE_GMP:
- $temp = $this->is_negative ? '-0x' . $x : '0x' . $x;
- $this->value = gmp_init($temp);
- $this->is_negative = false;
- break;
- case MATH_BIGINTEGER_MODE_BCMATH:
- $x = ( strlen($x) & 1 ) ? '0' . $x : $x;
- $temp = new Math_BigInteger(pack('H*', $x), 256);
- $this->value = $this->is_negative ? '-' . $temp->value : $temp->value;
- $this->is_negative = false;
- break;
- default:
- $x = ( strlen($x) & 1 ) ? '0' . $x : $x;
- $temp = new Math_BigInteger(pack('H*', $x), 256);
- $this->value = $temp->value;
- }
-
- if ($is_negative) {
- $temp = $this->add(new Math_BigInteger('-1'));
- $this->value = $temp->value;
- }
- break;
- case 10:
- case -10:
- $x = preg_replace('#^(-?[0-9]*).*#', '$1', $x);
-
- switch ( MATH_BIGINTEGER_MODE ) {
- case MATH_BIGINTEGER_MODE_GMP:
- $this->value = gmp_init($x);
- break;
- case MATH_BIGINTEGER_MODE_BCMATH:
- // explicitly casting $x to a string is necessary, here, since doing $x[0] on -1 yields different
- // results then doing it on '-1' does (modInverse does $x[0])
- $this->value = (string) $x;
- break;
- default:
- $temp = new Math_BigInteger();
-
- // array(10000000) is 10**7 in base-2**26. 10**7 is the closest to 2**26 we can get without passing it.
- $multiplier = new Math_BigInteger();
- $multiplier->value = array(10000000);
-
- if ($x[0] == '-') {
- $this->is_negative = true;
- $x = substr($x, 1);
- }
-
- $x = str_pad($x, strlen($x) + (6 * strlen($x)) % 7, 0, STR_PAD_LEFT);
-
- while (strlen($x)) {
- $temp = $temp->multiply($multiplier);
- $temp = $temp->add(new Math_BigInteger($this->_int2bytes(substr($x, 0, 7)), 256));
- $x = substr($x, 7);
- }
-
- $this->value = $temp->value;
- }
- break;
- case 2: // base-2 support originally implemented by Lluis Pamies - thanks!
- case -2:
- if ($base > 0 && $x[0] == '-') {
- $this->is_negative = true;
- $x = substr($x, 1);
- }
-
- $x = preg_replace('#^([01]*).*#', '$1', $x);
- $x = str_pad($x, strlen($x) + (3 * strlen($x)) % 4, 0, STR_PAD_LEFT);
-
- $str = '0x';
- while (strlen($x)) {
- $part = substr($x, 0, 4);
- $str.= dechex(bindec($part));
- $x = substr($x, 4);
- }
-
- if ($this->is_negative) {
- $str = '-' . $str;
- }
-
- $temp = new Math_BigInteger($str, 8 * $base); // ie. either -16 or +16
- $this->value = $temp->value;
- $this->is_negative = $temp->is_negative;
-
- break;
- default:
- // base not supported, so we'll let $this == 0
- }
- }
-
- /**
- * Converts a BigInteger to a byte string (eg. base-256).
- *
- * Negative numbers are saved as positive numbers, unless $twos_compliment is set to true, at which point, they're
- * saved as two's compliment.
- *
- * Here's an example:
- *
- * toBytes(); // outputs chr(65)
- * ?>
- *
- *
- * @param Boolean $twos_compliment
- * @return String
- * @access public
- * @internal Converts a base-2**26 number to base-2**8
- */
- function toBytes($twos_compliment = false)
- {
- if ($twos_compliment) {
- $comparison = $this->compare(new Math_BigInteger());
- if ($comparison == 0) {
- return $this->precision > 0 ? str_repeat(chr(0), ($this->precision + 1) >> 3) : '';
- }
-
- $temp = $comparison < 0 ? $this->add(new Math_BigInteger(1)) : $this->copy();
- $bytes = $temp->toBytes();
-
- if (empty($bytes)) { // eg. if the number we're trying to convert is -1
- $bytes = chr(0);
- }
-
- if (ord($bytes[0]) & 0x80) {
- $bytes = chr(0) . $bytes;
- }
-
- return $comparison < 0 ? ~$bytes : $bytes;
- }
-
- switch ( MATH_BIGINTEGER_MODE ) {
- case MATH_BIGINTEGER_MODE_GMP:
- if (gmp_cmp($this->value, gmp_init(0)) == 0) {
- return $this->precision > 0 ? str_repeat(chr(0), ($this->precision + 1) >> 3) : '';
- }
-
- $temp = gmp_strval(gmp_abs($this->value), 16);
- $temp = ( strlen($temp) & 1 ) ? '0' . $temp : $temp;
- $temp = pack('H*', $temp);
-
- return $this->precision > 0 ?
- substr(str_pad($temp, $this->precision >> 3, chr(0), STR_PAD_LEFT), -($this->precision >> 3)) :
- ltrim($temp, chr(0));
- case MATH_BIGINTEGER_MODE_BCMATH:
- if ($this->value === '0') {
- return $this->precision > 0 ? str_repeat(chr(0), ($this->precision + 1) >> 3) : '';
- }
-
- $value = '';
- $current = $this->value;
-
- if ($current[0] == '-') {
- $current = substr($current, 1);
- }
-
- while (bccomp($current, '0', 0) > 0) {
- $temp = bcmod($current, '16777216');
- $value = chr($temp >> 16) . chr($temp >> 8) . chr($temp) . $value;
- $current = bcdiv($current, '16777216', 0);
- }
-
- return $this->precision > 0 ?
- substr(str_pad($value, $this->precision >> 3, chr(0), STR_PAD_LEFT), -($this->precision >> 3)) :
- ltrim($value, chr(0));
- }
-
- if (!count($this->value)) {
- return $this->precision > 0 ? str_repeat(chr(0), ($this->precision + 1) >> 3) : '';
- }
- $result = $this->_int2bytes($this->value[count($this->value) - 1]);
-
- $temp = $this->copy();
-
- for ($i = count($temp->value) - 2; $i >= 0; --$i) {
- $temp->_base256_lshift($result, 26);
- $result = $result | str_pad($temp->_int2bytes($temp->value[$i]), strlen($result), chr(0), STR_PAD_LEFT);
- }
-
- return $this->precision > 0 ?
- str_pad(substr($result, -(($this->precision + 7) >> 3)), ($this->precision + 7) >> 3, chr(0), STR_PAD_LEFT) :
- $result;
- }
-
- /**
- * Converts a BigInteger to a hex string (eg. base-16)).
- *
- * Negative numbers are saved as positive numbers, unless $twos_compliment is set to true, at which point, they're
- * saved as two's compliment.
- *
- * Here's an example:
- *
- * toHex(); // outputs '41'
- * ?>
- *
- *
- * @param Boolean $twos_compliment
- * @return String
- * @access public
- * @internal Converts a base-2**26 number to base-2**8
- */
- function toHex($twos_compliment = false)
- {
- return bin2hex($this->toBytes($twos_compliment));
- }
-
- /**
- * Converts a BigInteger to a bit string (eg. base-2).
- *
- * Negative numbers are saved as positive numbers, unless $twos_compliment is set to true, at which point, they're
- * saved as two's compliment.
- *
- * Here's an example:
- *
- * toBits(); // outputs '1000001'
- * ?>
- *
- *
- * @param Boolean $twos_compliment
- * @return String
- * @access public
- * @internal Converts a base-2**26 number to base-2**2
- */
- function toBits($twos_compliment = false)
- {
- $hex = $this->toHex($twos_compliment);
- $bits = '';
- for ($i = 0; $i < strlen($hex); $i+=8) {
- $bits.= str_pad(decbin(hexdec(substr($hex, $i, 8))), 32, '0', STR_PAD_LEFT);
- }
- return $this->precision > 0 ? substr($bits, -$this->precision) : ltrim($bits, '0');
- }
-
- /**
- * Converts a BigInteger to a base-10 number.
- *
- * Here's an example:
- *
- * toString(); // outputs 50
- * ?>
- *
- *
- * @return String
- * @access public
- * @internal Converts a base-2**26 number to base-10**7 (which is pretty much base-10)
- */
- function toString()
- {
- switch ( MATH_BIGINTEGER_MODE ) {
- case MATH_BIGINTEGER_MODE_GMP:
- return gmp_strval($this->value);
- case MATH_BIGINTEGER_MODE_BCMATH:
- if ($this->value === '0') {
- return '0';
- }
-
- return ltrim($this->value, '0');
- }
-
- if (!count($this->value)) {
- return '0';
- }
-
- $temp = $this->copy();
- $temp->is_negative = false;
-
- $divisor = new Math_BigInteger();
- $divisor->value = array(10000000); // eg. 10**7
- $result = '';
- while (count($temp->value)) {
- list($temp, $mod) = $temp->divide($divisor);
- $result = str_pad(isset($mod->value[0]) ? $mod->value[0] : '', 7, '0', STR_PAD_LEFT) . $result;
- }
- $result = ltrim($result, '0');
- if (empty($result)) {
- $result = '0';
- }
-
- if ($this->is_negative) {
- $result = '-' . $result;
- }
-
- return $result;
- }
-
- /**
- * Copy an object
- *
- * PHP5 passes objects by reference while PHP4 passes by value. As such, we need a function to guarantee
- * that all objects are passed by value, when appropriate. More information can be found here:
- *
- * {@link http://php.net/language.oop5.basic#51624}
- *
- * @access public
- * @see __clone()
- * @return Math_BigInteger
- */
- function copy()
- {
- $temp = new Math_BigInteger();
- $temp->value = $this->value;
- $temp->is_negative = $this->is_negative;
- $temp->generator = $this->generator;
- $temp->precision = $this->precision;
- $temp->bitmask = $this->bitmask;
- return $temp;
- }
-
- /**
- * __toString() magic method
- *
- * Will be called, automatically, if you're supporting just PHP5. If you're supporting PHP4, you'll need to call
- * toString().
- *
- * @access public
- * @internal Implemented per a suggestion by Techie-Michael - thanks!
- */
- function __toString()
- {
- return $this->toString();
- }
-
- /**
- * __clone() magic method
- *
- * Although you can call Math_BigInteger::__toString() directly in PHP5, you cannot call Math_BigInteger::__clone()
- * directly in PHP5. You can in PHP4 since it's not a magic method, but in PHP5, you have to call it by using the PHP5
- * only syntax of $y = clone $x. As such, if you're trying to write an application that works on both PHP4 and PHP5,
- * call Math_BigInteger::copy(), instead.
- *
- * @access public
- * @see copy()
- * @return Math_BigInteger
- */
- function __clone()
- {
- return $this->copy();
- }
-
- /**
- * __sleep() magic method
- *
- * Will be called, automatically, when serialize() is called on a Math_BigInteger object.
- *
- * @see __wakeup()
- * @access public
- */
- function __sleep()
- {
- $this->hex = $this->toHex(true);
- $vars = array('hex');
- if ($this->generator != 'mt_rand') {
- $vars[] = 'generator';
- }
- if ($this->precision > 0) {
- $vars[] = 'precision';
- }
- return $vars;
-
- }
-
- /**
- * __wakeup() magic method
- *
- * Will be called, automatically, when unserialize() is called on a Math_BigInteger object.
- *
- * @see __sleep()
- * @access public
- */
- function __wakeup()
- {
- $temp = new Math_BigInteger($this->hex, -16);
- $this->value = $temp->value;
- $this->is_negative = $temp->is_negative;
- $this->setRandomGenerator($this->generator);
- if ($this->precision > 0) {
- // recalculate $this->bitmask
- $this->setPrecision($this->precision);
- }
- }
-
- /**
- * Adds two BigIntegers.
- *
- * Here's an example:
- *
- * add($b);
- *
- * echo $c->toString(); // outputs 30
- * ?>
- *
- *
- * @param Math_BigInteger $y
- * @return Math_BigInteger
- * @access public
- * @internal Performs base-2**52 addition
- */
- function add($y)
- {
- switch ( MATH_BIGINTEGER_MODE ) {
- case MATH_BIGINTEGER_MODE_GMP:
- $temp = new Math_BigInteger();
- $temp->value = gmp_add($this->value, $y->value);
-
- return $this->_normalize($temp);
- case MATH_BIGINTEGER_MODE_BCMATH:
- $temp = new Math_BigInteger();
- $temp->value = bcadd($this->value, $y->value, 0);
-
- return $this->_normalize($temp);
- }
-
- $temp = $this->_add($this->value, $this->is_negative, $y->value, $y->is_negative);
-
- $result = new Math_BigInteger();
- $result->value = $temp[MATH_BIGINTEGER_VALUE];
- $result->is_negative = $temp[MATH_BIGINTEGER_SIGN];
-
- return $this->_normalize($result);
- }
-
- /**
- * Performs addition.
- *
- * @param Array $x_value
- * @param Boolean $x_negative
- * @param Array $y_value
- * @param Boolean $y_negative
- * @return Array
- * @access private
- */
- function _add($x_value, $x_negative, $y_value, $y_negative)
- {
- $x_size = count($x_value);
- $y_size = count($y_value);
-
- if ($x_size == 0) {
- return array(
- MATH_BIGINTEGER_VALUE => $y_value,
- MATH_BIGINTEGER_SIGN => $y_negative
- );
- } else if ($y_size == 0) {
- return array(
- MATH_BIGINTEGER_VALUE => $x_value,
- MATH_BIGINTEGER_SIGN => $x_negative
- );
- }
-
- // subtract, if appropriate
- if ( $x_negative != $y_negative ) {
- if ( $x_value == $y_value ) {
- return array(
- MATH_BIGINTEGER_VALUE => array(),
- MATH_BIGINTEGER_SIGN => false
- );
- }
-
- $temp = $this->_subtract($x_value, false, $y_value, false);
- $temp[MATH_BIGINTEGER_SIGN] = $this->_compare($x_value, false, $y_value, false) > 0 ?
- $x_negative : $y_negative;
-
- return $temp;
- }
-
- if ($x_size < $y_size) {
- $size = $x_size;
- $value = $y_value;
- } else {
- $size = $y_size;
- $value = $x_value;
- }
-
- $value[] = 0; // just in case the carry adds an extra digit
-
- $carry = 0;
- for ($i = 0, $j = 1; $j < $size; $i+=2, $j+=2) {
- $sum = $x_value[$j] * 0x4000000 + $x_value[$i] + $y_value[$j] * 0x4000000 + $y_value[$i] + $carry;
- $carry = $sum >= MATH_BIGINTEGER_MAX_DIGIT52; // eg. floor($sum / 2**52); only possible values (in any base) are 0 and 1
- $sum = $carry ? $sum - MATH_BIGINTEGER_MAX_DIGIT52 : $sum;
-
- $temp = (int) ($sum / 0x4000000);
-
- $value[$i] = (int) ($sum - 0x4000000 * $temp); // eg. a faster alternative to fmod($sum, 0x4000000)
- $value[$j] = $temp;
- }
-
- if ($j == $size) { // ie. if $y_size is odd
- $sum = $x_value[$i] + $y_value[$i] + $carry;
- $carry = $sum >= 0x4000000;
- $value[$i] = $carry ? $sum - 0x4000000 : $sum;
- ++$i; // ie. let $i = $j since we've just done $value[$i]
- }
-
- if ($carry) {
- for (; $value[$i] == 0x3FFFFFF; ++$i) {
- $value[$i] = 0;
- }
- ++$value[$i];
- }
-
- return array(
- MATH_BIGINTEGER_VALUE => $this->_trim($value),
- MATH_BIGINTEGER_SIGN => $x_negative
- );
- }
-
- /**
- * Subtracts two BigIntegers.
- *
- * Here's an example:
- *
- * subtract($b);
- *
- * echo $c->toString(); // outputs -10
- * ?>
- *
- *
- * @param Math_BigInteger $y
- * @return Math_BigInteger
- * @access public
- * @internal Performs base-2**52 subtraction
- */
- function subtract($y)
- {
- switch ( MATH_BIGINTEGER_MODE ) {
- case MATH_BIGINTEGER_MODE_GMP:
- $temp = new Math_BigInteger();
- $temp->value = gmp_sub($this->value, $y->value);
-
- return $this->_normalize($temp);
- case MATH_BIGINTEGER_MODE_BCMATH:
- $temp = new Math_BigInteger();
- $temp->value = bcsub($this->value, $y->value, 0);
-
- return $this->_normalize($temp);
- }
-
- $temp = $this->_subtract($this->value, $this->is_negative, $y->value, $y->is_negative);
-
- $result = new Math_BigInteger();
- $result->value = $temp[MATH_BIGINTEGER_VALUE];
- $result->is_negative = $temp[MATH_BIGINTEGER_SIGN];
-
- return $this->_normalize($result);
- }
-
- /**
- * Performs subtraction.
- *
- * @param Array $x_value
- * @param Boolean $x_negative
- * @param Array $y_value
- * @param Boolean $y_negative
- * @return Array
- * @access private
- */
- function _subtract($x_value, $x_negative, $y_value, $y_negative)
- {
- $x_size = count($x_value);
- $y_size = count($y_value);
-
- if ($x_size == 0) {
- return array(
- MATH_BIGINTEGER_VALUE => $y_value,
- MATH_BIGINTEGER_SIGN => !$y_negative
- );
- } else if ($y_size == 0) {
- return array(
- MATH_BIGINTEGER_VALUE => $x_value,
- MATH_BIGINTEGER_SIGN => $x_negative
- );
- }
-
- // add, if appropriate (ie. -$x - +$y or +$x - -$y)
- if ( $x_negative != $y_negative ) {
- $temp = $this->_add($x_value, false, $y_value, false);
- $temp[MATH_BIGINTEGER_SIGN] = $x_negative;
-
- return $temp;
- }
-
- $diff = $this->_compare($x_value, $x_negative, $y_value, $y_negative);
-
- if ( !$diff ) {
- return array(
- MATH_BIGINTEGER_VALUE => array(),
- MATH_BIGINTEGER_SIGN => false
- );
- }
-
- // switch $x and $y around, if appropriate.
- if ( (!$x_negative && $diff < 0) || ($x_negative && $diff > 0) ) {
- $temp = $x_value;
- $x_value = $y_value;
- $y_value = $temp;
-
- $x_negative = !$x_negative;
-
- $x_size = count($x_value);
- $y_size = count($y_value);
- }
-
- // at this point, $x_value should be at least as big as - if not bigger than - $y_value
-
- $carry = 0;
- for ($i = 0, $j = 1; $j < $y_size; $i+=2, $j+=2) {
- $sum = $x_value[$j] * 0x4000000 + $x_value[$i] - $y_value[$j] * 0x4000000 - $y_value[$i] - $carry;
- $carry = $sum < 0; // eg. floor($sum / 2**52); only possible values (in any base) are 0 and 1
- $sum = $carry ? $sum + MATH_BIGINTEGER_MAX_DIGIT52 : $sum;
-
- $temp = (int) ($sum / 0x4000000);
-
- $x_value[$i] = (int) ($sum - 0x4000000 * $temp);
- $x_value[$j] = $temp;
- }
-
- if ($j == $y_size) { // ie. if $y_size is odd
- $sum = $x_value[$i] - $y_value[$i] - $carry;
- $carry = $sum < 0;
- $x_value[$i] = $carry ? $sum + 0x4000000 : $sum;
- ++$i;
- }
-
- if ($carry) {
- for (; !$x_value[$i]; ++$i) {
- $x_value[$i] = 0x3FFFFFF;
- }
- --$x_value[$i];
- }
-
- return array(
- MATH_BIGINTEGER_VALUE => $this->_trim($x_value),
- MATH_BIGINTEGER_SIGN => $x_negative
- );
- }
-
- /**
- * Multiplies two BigIntegers
- *
- * Here's an example:
- *
- * multiply($b);
- *
- * echo $c->toString(); // outputs 200
- * ?>
- *
- *
- * @param Math_BigInteger $x
- * @return Math_BigInteger
- * @access public
- */
- function multiply($x)
- {
- switch ( MATH_BIGINTEGER_MODE ) {
- case MATH_BIGINTEGER_MODE_GMP:
- $temp = new Math_BigInteger();
- $temp->value = gmp_mul($this->value, $x->value);
-
- return $this->_normalize($temp);
- case MATH_BIGINTEGER_MODE_BCMATH:
- $temp = new Math_BigInteger();
- $temp->value = bcmul($this->value, $x->value, 0);
-
- return $this->_normalize($temp);
- }
-
- $temp = $this->_multiply($this->value, $this->is_negative, $x->value, $x->is_negative);
-
- $product = new Math_BigInteger();
- $product->value = $temp[MATH_BIGINTEGER_VALUE];
- $product->is_negative = $temp[MATH_BIGINTEGER_SIGN];
-
- return $this->_normalize($product);
- }
-
- /**
- * Performs multiplication.
- *
- * @param Array $x_value
- * @param Boolean $x_negative
- * @param Array $y_value
- * @param Boolean $y_negative
- * @return Array
- * @access private
- */
- function _multiply($x_value, $x_negative, $y_value, $y_negative)
- {
- //if ( $x_value == $y_value ) {
- // return array(
- // MATH_BIGINTEGER_VALUE => $this->_square($x_value),
- // MATH_BIGINTEGER_SIGN => $x_sign != $y_value
- // );
- //}
-
- $x_length = count($x_value);
- $y_length = count($y_value);
-
- if ( !$x_length || !$y_length ) { // a 0 is being multiplied
- return array(
- MATH_BIGINTEGER_VALUE => array(),
- MATH_BIGINTEGER_SIGN => false
- );
- }
-
- return array(
- MATH_BIGINTEGER_VALUE => min($x_length, $y_length) < 2 * MATH_BIGINTEGER_KARATSUBA_CUTOFF ?
- $this->_trim($this->_regularMultiply($x_value, $y_value)) :
- $this->_trim($this->_karatsuba($x_value, $y_value)),
- MATH_BIGINTEGER_SIGN => $x_negative != $y_negative
- );
- }
-
- /**
- * Performs long multiplication on two BigIntegers
- *
- * Modeled after 'multiply' in MutableBigInteger.java.
- *
- * @param Array $x_value
- * @param Array $y_value
- * @return Array
- * @access private
- */
- function _regularMultiply($x_value, $y_value)
- {
- $x_length = count($x_value);
- $y_length = count($y_value);
-
- if ( !$x_length || !$y_length ) { // a 0 is being multiplied
- return array();
- }
-
- if ( $x_length < $y_length ) {
- $temp = $x_value;
- $x_value = $y_value;
- $y_value = $temp;
-
- $x_length = count($x_value);
- $y_length = count($y_value);
- }
-
- $product_value = $this->_array_repeat(0, $x_length + $y_length);
-
- // the following for loop could be removed if the for loop following it
- // (the one with nested for loops) initially set $i to 0, but
- // doing so would also make the result in one set of unnecessary adds,
- // since on the outermost loops first pass, $product->value[$k] is going
- // to always be 0
-
- $carry = 0;
-
- for ($j = 0; $j < $x_length; ++$j) { // ie. $i = 0
- $temp = $x_value[$j] * $y_value[0] + $carry; // $product_value[$k] == 0
- $carry = (int) ($temp / 0x4000000);
- $product_value[$j] = (int) ($temp - 0x4000000 * $carry);
- }
-
- $product_value[$j] = $carry;
-
- // the above for loop is what the previous comment was talking about. the
- // following for loop is the "one with nested for loops"
- for ($i = 1; $i < $y_length; ++$i) {
- $carry = 0;
-
- for ($j = 0, $k = $i; $j < $x_length; ++$j, ++$k) {
- $temp = $product_value[$k] + $x_value[$j] * $y_value[$i] + $carry;
- $carry = (int) ($temp / 0x4000000);
- $product_value[$k] = (int) ($temp - 0x4000000 * $carry);
- }
-
- $product_value[$k] = $carry;
- }
-
- return $product_value;
- }
-
- /**
- * Performs Karatsuba multiplication on two BigIntegers
- *
- * See {@link http://en.wikipedia.org/wiki/Karatsuba_algorithm Karatsuba algorithm} and
- * {@link http://math.libtomcrypt.com/files/tommath.pdf#page=120 MPM 5.2.3}.
- *
- * @param Array $x_value
- * @param Array $y_value
- * @return Array
- * @access private
- */
- function _karatsuba($x_value, $y_value)
- {
- $m = min(count($x_value) >> 1, count($y_value) >> 1);
-
- if ($m < MATH_BIGINTEGER_KARATSUBA_CUTOFF) {
- return $this->_regularMultiply($x_value, $y_value);
- }
-
- $x1 = array_slice($x_value, $m);
- $x0 = array_slice($x_value, 0, $m);
- $y1 = array_slice($y_value, $m);
- $y0 = array_slice($y_value, 0, $m);
-
- $z2 = $this->_karatsuba($x1, $y1);
- $z0 = $this->_karatsuba($x0, $y0);
-
- $z1 = $this->_add($x1, false, $x0, false);
- $temp = $this->_add($y1, false, $y0, false);
- $z1 = $this->_karatsuba($z1[MATH_BIGINTEGER_VALUE], $temp[MATH_BIGINTEGER_VALUE]);
- $temp = $this->_add($z2, false, $z0, false);
- $z1 = $this->_subtract($z1, false, $temp[MATH_BIGINTEGER_VALUE], false);
-
- $z2 = array_merge(array_fill(0, 2 * $m, 0), $z2);
- $z1[MATH_BIGINTEGER_VALUE] = array_merge(array_fill(0, $m, 0), $z1[MATH_BIGINTEGER_VALUE]);
-
- $xy = $this->_add($z2, false, $z1[MATH_BIGINTEGER_VALUE], $z1[MATH_BIGINTEGER_SIGN]);
- $xy = $this->_add($xy[MATH_BIGINTEGER_VALUE], $xy[MATH_BIGINTEGER_SIGN], $z0, false);
-
- return $xy[MATH_BIGINTEGER_VALUE];
- }
-
- /**
- * Performs squaring
- *
- * @param Array $x
- * @return Array
- * @access private
- */
- function _square($x = false)
- {
- return count($x) < 2 * MATH_BIGINTEGER_KARATSUBA_CUTOFF ?
- $this->_trim($this->_baseSquare($x)) :
- $this->_trim($this->_karatsubaSquare($x));
- }
-
- /**
- * Performs traditional squaring on two BigIntegers
- *
- * Squaring can be done faster than multiplying a number by itself can be. See
- * {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf#page=7 HAC 14.2.4} /
- * {@link http://math.libtomcrypt.com/files/tommath.pdf#page=141 MPM 5.3} for more information.
- *
- * @param Array $value
- * @return Array
- * @access private
- */
- function _baseSquare($value)
- {
- if ( empty($value) ) {
- return array();
- }
- $square_value = $this->_array_repeat(0, 2 * count($value));
-
- for ($i = 0, $max_index = count($value) - 1; $i <= $max_index; ++$i) {
- $i2 = $i << 1;
-
- $temp = $square_value[$i2] + $value[$i] * $value[$i];
- $carry = (int) ($temp / 0x4000000);
- $square_value[$i2] = (int) ($temp - 0x4000000 * $carry);
-
- // note how we start from $i+1 instead of 0 as we do in multiplication.
- for ($j = $i + 1, $k = $i2 + 1; $j <= $max_index; ++$j, ++$k) {
- $temp = $square_value[$k] + 2 * $value[$j] * $value[$i] + $carry;
- $carry = (int) ($temp / 0x4000000);
- $square_value[$k] = (int) ($temp - 0x4000000 * $carry);
- }
-
- // the following line can yield values larger 2**15. at this point, PHP should switch
- // over to floats.
- $square_value[$i + $max_index + 1] = $carry;
- }
-
- return $square_value;
- }
-
- /**
- * Performs Karatsuba "squaring" on two BigIntegers
- *
- * See {@link http://en.wikipedia.org/wiki/Karatsuba_algorithm Karatsuba algorithm} and
- * {@link http://math.libtomcrypt.com/files/tommath.pdf#page=151 MPM 5.3.4}.
- *
- * @param Array $value
- * @return Array
- * @access private
- */
- function _karatsubaSquare($value)
- {
- $m = count($value) >> 1;
-
- if ($m < MATH_BIGINTEGER_KARATSUBA_CUTOFF) {
- return $this->_baseSquare($value);
- }
-
- $x1 = array_slice($value, $m);
- $x0 = array_slice($value, 0, $m);
-
- $z2 = $this->_karatsubaSquare($x1);
- $z0 = $this->_karatsubaSquare($x0);
-
- $z1 = $this->_add($x1, false, $x0, false);
- $z1 = $this->_karatsubaSquare($z1[MATH_BIGINTEGER_VALUE]);
- $temp = $this->_add($z2, false, $z0, false);
- $z1 = $this->_subtract($z1, false, $temp[MATH_BIGINTEGER_VALUE], false);
-
- $z2 = array_merge(array_fill(0, 2 * $m, 0), $z2);
- $z1[MATH_BIGINTEGER_VALUE] = array_merge(array_fill(0, $m, 0), $z1[MATH_BIGINTEGER_VALUE]);
-
- $xx = $this->_add($z2, false, $z1[MATH_BIGINTEGER_VALUE], $z1[MATH_BIGINTEGER_SIGN]);
- $xx = $this->_add($xx[MATH_BIGINTEGER_VALUE], $xx[MATH_BIGINTEGER_SIGN], $z0, false);
-
- return $xx[MATH_BIGINTEGER_VALUE];
- }
-
- /**
- * Divides two BigIntegers.
- *
- * Returns an array whose first element contains the quotient and whose second element contains the
- * "common residue". If the remainder would be positive, the "common residue" and the remainder are the
- * same. If the remainder would be negative, the "common residue" is equal to the sum of the remainder
- * and the divisor (basically, the "common residue" is the first positive modulo).
- *
- * Here's an example:
- *
- * divide($b);
- *
- * echo $quotient->toString(); // outputs 0
- * echo "\r\n";
- * echo $remainder->toString(); // outputs 10
- * ?>
- *
- *
- * @param Math_BigInteger $y
- * @return Array
- * @access public
- * @internal This function is based off of {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf#page=9 HAC 14.20}.
- */
- function divide($y)
- {
- switch ( MATH_BIGINTEGER_MODE ) {
- case MATH_BIGINTEGER_MODE_GMP:
- $quotient = new Math_BigInteger();
- $remainder = new Math_BigInteger();
-
- list($quotient->value, $remainder->value) = gmp_div_qr($this->value, $y->value);
-
- if (gmp_sign($remainder->value) < 0) {
- $remainder->value = gmp_add($remainder->value, gmp_abs($y->value));
- }
-
- return array($this->_normalize($quotient), $this->_normalize($remainder));
- case MATH_BIGINTEGER_MODE_BCMATH:
- $quotient = new Math_BigInteger();
- $remainder = new Math_BigInteger();
-
- $quotient->value = bcdiv($this->value, $y->value, 0);
- $remainder->value = bcmod($this->value, $y->value);
-
- if ($remainder->value[0] == '-') {
- $remainder->value = bcadd($remainder->value, $y->value[0] == '-' ? substr($y->value, 1) : $y->value, 0);
- }
-
- return array($this->_normalize($quotient), $this->_normalize($remainder));
- }
-
- if (count($y->value) == 1) {
- list($q, $r) = $this->_divide_digit($this->value, $y->value[0]);
- $quotient = new Math_BigInteger();
- $remainder = new Math_BigInteger();
- $quotient->value = $q;
- $remainder->value = array($r);
- $quotient->is_negative = $this->is_negative != $y->is_negative;
- return array($this->_normalize($quotient), $this->_normalize($remainder));
- }
-
- static $zero;
- if ( !isset($zero) ) {
- $zero = new Math_BigInteger();
- }
-
- $x = $this->copy();
- $y = $y->copy();
-
- $x_sign = $x->is_negative;
- $y_sign = $y->is_negative;
-
- $x->is_negative = $y->is_negative = false;
-
- $diff = $x->compare($y);
-
- if ( !$diff ) {
- $temp = new Math_BigInteger();
- $temp->value = array(1);
- $temp->is_negative = $x_sign != $y_sign;
- return array($this->_normalize($temp), $this->_normalize(new Math_BigInteger()));
- }
-
- if ( $diff < 0 ) {
- // if $x is negative, "add" $y.
- if ( $x_sign ) {
- $x = $y->subtract($x);
- }
- return array($this->_normalize(new Math_BigInteger()), $this->_normalize($x));
- }
-
- // normalize $x and $y as described in HAC 14.23 / 14.24
- $msb = $y->value[count($y->value) - 1];
- for ($shift = 0; !($msb & 0x2000000); ++$shift) {
- $msb <<= 1;
- }
- $x->_lshift($shift);
- $y->_lshift($shift);
- $y_value = &$y->value;
-
- $x_max = count($x->value) - 1;
- $y_max = count($y->value) - 1;
-
- $quotient = new Math_BigInteger();
- $quotient_value = &$quotient->value;
- $quotient_value = $this->_array_repeat(0, $x_max - $y_max + 1);
-
- static $temp, $lhs, $rhs;
- if (!isset($temp)) {
- $temp = new Math_BigInteger();
- $lhs = new Math_BigInteger();
- $rhs = new Math_BigInteger();
- }
- $temp_value = &$temp->value;
- $rhs_value = &$rhs->value;
-
- // $temp = $y << ($x_max - $y_max-1) in base 2**26
- $temp_value = array_merge($this->_array_repeat(0, $x_max - $y_max), $y_value);
-
- while ( $x->compare($temp) >= 0 ) {
- // calculate the "common residue"
- ++$quotient_value[$x_max - $y_max];
- $x = $x->subtract($temp);
- $x_max = count($x->value) - 1;
- }
-
- for ($i = $x_max; $i >= $y_max + 1; --$i) {
- $x_value = &$x->value;
- $x_window = array(
- isset($x_value[$i]) ? $x_value[$i] : 0,
- isset($x_value[$i - 1]) ? $x_value[$i - 1] : 0,
- isset($x_value[$i - 2]) ? $x_value[$i - 2] : 0
- );
- $y_window = array(
- $y_value[$y_max],
- ( $y_max > 0 ) ? $y_value[$y_max - 1] : 0
- );
-
- $q_index = $i - $y_max - 1;
- if ($x_window[0] == $y_window[0]) {
- $quotient_value[$q_index] = 0x3FFFFFF;
- } else {
- $quotient_value[$q_index] = (int) (
- ($x_window[0] * 0x4000000 + $x_window[1])
- /
- $y_window[0]
- );
- }
-
- $temp_value = array($y_window[1], $y_window[0]);
-
- $lhs->value = array($quotient_value[$q_index]);
- $lhs = $lhs->multiply($temp);
-
- $rhs_value = array($x_window[2], $x_window[1], $x_window[0]);
-
- while ( $lhs->compare($rhs) > 0 ) {
- --$quotient_value[$q_index];
-
- $lhs->value = array($quotient_value[$q_index]);
- $lhs = $lhs->multiply($temp);
- }
-
- $adjust = $this->_array_repeat(0, $q_index);
- $temp_value = array($quotient_value[$q_index]);
- $temp = $temp->multiply($y);
- $temp_value = &$temp->value;
- $temp_value = array_merge($adjust, $temp_value);
-
- $x = $x->subtract($temp);
-
- if ($x->compare($zero) < 0) {
- $temp_value = array_merge($adjust, $y_value);
- $x = $x->add($temp);
-
- --$quotient_value[$q_index];
- }
-
- $x_max = count($x_value) - 1;
- }
-
- // unnormalize the remainder
- $x->_rshift($shift);
-
- $quotient->is_negative = $x_sign != $y_sign;
-
- // calculate the "common residue", if appropriate
- if ( $x_sign ) {
- $y->_rshift($shift);
- $x = $y->subtract($x);
- }
-
- return array($this->_normalize($quotient), $this->_normalize($x));
- }
-
- /**
- * Divides a BigInteger by a regular integer
- *
- * abc / x = a00 / x + b0 / x + c / x
- *
- * @param Array $dividend
- * @param Array $divisor
- * @return Array
- * @access private
- */
- function _divide_digit($dividend, $divisor)
- {
- $carry = 0;
- $result = array();
-
- for ($i = count($dividend) - 1; $i >= 0; --$i) {
- $temp = 0x4000000 * $carry + $dividend[$i];
- $result[$i] = (int) ($temp / $divisor);
- $carry = (int) ($temp - $divisor * $result[$i]);
- }
-
- return array($result, $carry);
- }
-
- /**
- * Performs modular exponentiation.
- *
- * Here's an example:
- *
- * modPow($b, $c);
- *
- * echo $c->toString(); // outputs 10
- * ?>
- *
- *
- * @param Math_BigInteger $e
- * @param Math_BigInteger $n
- * @return Math_BigInteger
- * @access public
- * @internal The most naive approach to modular exponentiation has very unreasonable requirements, and
- * and although the approach involving repeated squaring does vastly better, it, too, is impractical
- * for our purposes. The reason being that division - by far the most complicated and time-consuming
- * of the basic operations (eg. +,-,*,/) - occurs multiple times within it.
- *
- * Modular reductions resolve this issue. Although an individual modular reduction takes more time
- * then an individual division, when performed in succession (with the same modulo), they're a lot faster.
- *
- * The two most commonly used modular reductions are Barrett and Montgomery reduction. Montgomery reduction,
- * although faster, only works when the gcd of the modulo and of the base being used is 1. In RSA, when the
- * base is a power of two, the modulo - a product of two primes - is always going to have a gcd of 1 (because
- * the product of two odd numbers is odd), but what about when RSA isn't used?
- *
- * In contrast, Barrett reduction has no such constraint. As such, some bigint implementations perform a
- * Barrett reduction after every operation in the modpow function. Others perform Barrett reductions when the
- * modulo is even and Montgomery reductions when the modulo is odd. BigInteger.java's modPow method, however,
- * uses a trick involving the Chinese Remainder Theorem to factor the even modulo into two numbers - one odd and
- * the other, a power of two - and recombine them, later. This is the method that this modPow function uses.
- * {@link http://islab.oregonstate.edu/papers/j34monex.pdf Montgomery Reduction with Even Modulus} elaborates.
- */
- function modPow($e, $n)
- {
- $n = $this->bitmask !== false && $this->bitmask->compare($n) < 0 ? $this->bitmask : $n->abs();
-
- if ($e->compare(new Math_BigInteger()) < 0) {
- $e = $e->abs();
-
- $temp = $this->modInverse($n);
- if ($temp === false) {
- return false;
- }
-
- return $this->_normalize($temp->modPow($e, $n));
- }
-
- switch ( MATH_BIGINTEGER_MODE ) {
- case MATH_BIGINTEGER_MODE_GMP:
- $temp = new Math_BigInteger();
- $temp->value = gmp_powm($this->value, $e->value, $n->value);
-
- return $this->_normalize($temp);
- case MATH_BIGINTEGER_MODE_BCMATH:
- $temp = new Math_BigInteger();
- $temp->value = bcpowmod($this->value, $e->value, $n->value, 0);
-
- return $this->_normalize($temp);
- }
-
- if ( empty($e->value) ) {
- $temp = new Math_BigInteger();
- $temp->value = array(1);
- return $this->_normalize($temp);
- }
-
- if ( $e->value == array(1) ) {
- list(, $temp) = $this->divide($n);
- return $this->_normalize($temp);
- }
-
- if ( $e->value == array(2) ) {
- $temp = new Math_BigInteger();
- $temp->value = $this->_square($this->value);
- list(, $temp) = $temp->divide($n);
- return $this->_normalize($temp);
- }
-
- return $this->_normalize($this->_slidingWindow($e, $n, MATH_BIGINTEGER_BARRETT));
-
- // is the modulo odd?
- if ( $n->value[0] & 1 ) {
- return $this->_normalize($this->_slidingWindow($e, $n, MATH_BIGINTEGER_MONTGOMERY));
- }
- // if it's not, it's even
-
- // find the lowest set bit (eg. the max pow of 2 that divides $n)
- for ($i = 0; $i < count($n->value); ++$i) {
- if ( $n->value[$i] ) {
- $temp = decbin($n->value[$i]);
- $j = strlen($temp) - strrpos($temp, '1') - 1;
- $j+= 26 * $i;
- break;
- }
- }
- // at this point, 2^$j * $n/(2^$j) == $n
-
- $mod1 = $n->copy();
- $mod1->_rshift($j);
- $mod2 = new Math_BigInteger();
- $mod2->value = array(1);
- $mod2->_lshift($j);
-
- $part1 = ( $mod1->value != array(1) ) ? $this->_slidingWindow($e, $mod1, MATH_BIGINTEGER_MONTGOMERY) : new Math_BigInteger();
- $part2 = $this->_slidingWindow($e, $mod2, MATH_BIGINTEGER_POWEROF2);
-
- $y1 = $mod2->modInverse($mod1);
- $y2 = $mod1->modInverse($mod2);
-
- $result = $part1->multiply($mod2);
- $result = $result->multiply($y1);
-
- $temp = $part2->multiply($mod1);
- $temp = $temp->multiply($y2);
-
- $result = $result->add($temp);
- list(, $result) = $result->divide($n);
-
- return $this->_normalize($result);
- }
-
- /**
- * Performs modular exponentiation.
- *
- * Alias for Math_BigInteger::modPow()
- *
- * @param Math_BigInteger $e
- * @param Math_BigInteger $n
- * @return Math_BigInteger
- * @access public
- */
- function powMod($e, $n)
- {
- return $this->modPow($e, $n);
- }
-
- /**
- * Sliding Window k-ary Modular Exponentiation
- *
- * Based on {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf#page=27 HAC 14.85} /
- * {@link http://math.libtomcrypt.com/files/tommath.pdf#page=210 MPM 7.7}. In a departure from those algorithims,
- * however, this function performs a modular reduction after every multiplication and squaring operation.
- * As such, this function has the same preconditions that the reductions being used do.
- *
- * @param Math_BigInteger $e
- * @param Math_BigInteger $n
- * @param Integer $mode
- * @return Math_BigInteger
- * @access private
- */
- function _slidingWindow($e, $n, $mode)
- {
- static $window_ranges = array(7, 25, 81, 241, 673, 1793); // from BigInteger.java's oddModPow function
- //static $window_ranges = array(0, 7, 36, 140, 450, 1303, 3529); // from MPM 7.3.1
-
- $e_value = $e->value;
- $e_length = count($e_value) - 1;
- $e_bits = decbin($e_value[$e_length]);
- for ($i = $e_length - 1; $i >= 0; --$i) {
- $e_bits.= str_pad(decbin($e_value[$i]), 26, '0', STR_PAD_LEFT);
- }
-
- $e_length = strlen($e_bits);
-
- // calculate the appropriate window size.
- // $window_size == 3 if $window_ranges is between 25 and 81, for example.
- for ($i = 0, $window_size = 1; $e_length > $window_ranges[$i] && $i < count($window_ranges); ++$window_size, ++$i);
-
- $n_value = $n->value;
-
- // precompute $this^0 through $this^$window_size
- $powers = array();
- $powers[1] = $this->_prepareReduce($this->value, $n_value, $mode);
- $powers[2] = $this->_squareReduce($powers[1], $n_value, $mode);
-
- // we do every other number since substr($e_bits, $i, $j+1) (see below) is supposed to end
- // in a 1. ie. it's supposed to be odd.
- $temp = 1 << ($window_size - 1);
- for ($i = 1; $i < $temp; ++$i) {
- $i2 = $i << 1;
- $powers[$i2 + 1] = $this->_multiplyReduce($powers[$i2 - 1], $powers[2], $n_value, $mode);
- }
-
- $result = array(1);
- $result = $this->_prepareReduce($result, $n_value, $mode);
-
- for ($i = 0; $i < $e_length; ) {
- if ( !$e_bits[$i] ) {
- $result = $this->_squareReduce($result, $n_value, $mode);
- ++$i;
- } else {
- for ($j = $window_size - 1; $j > 0; --$j) {
- if ( !empty($e_bits[$i + $j]) ) {
- break;
- }
- }
-
- for ($k = 0; $k <= $j; ++$k) {// eg. the length of substr($e_bits, $i, $j+1)
- $result = $this->_squareReduce($result, $n_value, $mode);
- }
-
- $result = $this->_multiplyReduce($result, $powers[bindec(substr($e_bits, $i, $j + 1))], $n_value, $mode);
-
- $i+=$j + 1;
- }
- }
-
- $temp = new Math_BigInteger();
- $temp->value = $this->_reduce($result, $n_value, $mode);
-
- return $temp;
- }
-
- /**
- * Modular reduction
- *
- * For most $modes this will return the remainder.
- *
- * @see _slidingWindow()
- * @access private
- * @param Array $x
- * @param Array $n
- * @param Integer $mode
- * @return Array
- */
- function _reduce($x, $n, $mode)
- {
- switch ($mode) {
- case MATH_BIGINTEGER_MONTGOMERY:
- return $this->_montgomery($x, $n);
- case MATH_BIGINTEGER_BARRETT:
- return $this->_barrett($x, $n);
- case MATH_BIGINTEGER_POWEROF2:
- $lhs = new Math_BigInteger();
- $lhs->value = $x;
- $rhs = new Math_BigInteger();
- $rhs->value = $n;
- return $x->_mod2($n);
- case MATH_BIGINTEGER_CLASSIC:
- $lhs = new Math_BigInteger();
- $lhs->value = $x;
- $rhs = new Math_BigInteger();
- $rhs->value = $n;
- list(, $temp) = $lhs->divide($rhs);
- return $temp->value;
- case MATH_BIGINTEGER_NONE:
- return $x;
- default:
- // an invalid $mode was provided
- }
- }
-
- /**
- * Modular reduction preperation
- *
- * @see _slidingWindow()
- * @access private
- * @param Array $x
- * @param Array $n
- * @param Integer $mode
- * @return Array
- */
- function _prepareReduce($x, $n, $mode)
- {
- if ($mode == MATH_BIGINTEGER_MONTGOMERY) {
- return $this->_prepMontgomery($x, $n);
- }
- return $this->_reduce($x, $n, $mode);
- }
-
- /**
- * Modular multiply
- *
- * @see _slidingWindow()
- * @access private
- * @param Array $x
- * @param Array $y
- * @param Array $n
- * @param Integer $mode
- * @return Array
- */
- function _multiplyReduce($x, $y, $n, $mode)
- {
- if ($mode == MATH_BIGINTEGER_MONTGOMERY) {
- return $this->_montgomeryMultiply($x, $y, $n);
- }
- $temp = $this->_multiply($x, false, $y, false);
- return $this->_reduce($temp[MATH_BIGINTEGER_VALUE], $n, $mode);
- }
-
- /**
- * Modular square
- *
- * @see _slidingWindow()
- * @access private
- * @param Array $x
- * @param Array $n
- * @param Integer $mode
- * @return Array
- */
- function _squareReduce($x, $n, $mode)
- {
- if ($mode == MATH_BIGINTEGER_MONTGOMERY) {
- return $this->_montgomeryMultiply($x, $x, $n);
- }
- return $this->_reduce($this->_square($x), $n, $mode);
- }
-
- /**
- * Modulos for Powers of Two
- *
- * Calculates $x%$n, where $n = 2**$e, for some $e. Since this is basically the same as doing $x & ($n-1),
- * we'll just use this function as a wrapper for doing that.
- *
- * @see _slidingWindow()
- * @access private
- * @param Math_BigInteger
- * @return Math_BigInteger
- */
- function _mod2($n)
- {
- $temp = new Math_BigInteger();
- $temp->value = array(1);
- return $this->bitwise_and($n->subtract($temp));
- }
-
- /**
- * Barrett Modular Reduction
- *
- * See {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf#page=14 HAC 14.3.3} /
- * {@link http://math.libtomcrypt.com/files/tommath.pdf#page=165 MPM 6.2.5} for more information. Modified slightly,
- * so as not to require negative numbers (initially, this script didn't support negative numbers).
- *
- * Employs "folding", as described at
- * {@link http://www.cosic.esat.kuleuven.be/publications/thesis-149.pdf#page=66 thesis-149.pdf#page=66}. To quote from
- * it, "the idea [behind folding] is to find a value x' such that x (mod m) = x' (mod m), with x' being smaller than x."
- *
- * Unfortunately, the "Barrett Reduction with Folding" algorithm described in thesis-149.pdf is not, as written, all that
- * usable on account of (1) its not using reasonable radix points as discussed in
- * {@link http://math.libtomcrypt.com/files/tommath.pdf#page=162 MPM 6.2.2} and (2) the fact that, even with reasonable
- * radix points, it only works when there are an even number of digits in the denominator. The reason for (2) is that
- * (x >> 1) + (x >> 1) != x / 2 + x / 2. If x is even, they're the same, but if x is odd, they're not. See the in-line
- * comments for details.
- *
- * @see _slidingWindow()
- * @access private
- * @param Array $n
- * @param Array $m
- * @return Array
- */
- function _barrett($n, $m)
- {
- static $cache = array(
- MATH_BIGINTEGER_VARIABLE => array(),
- MATH_BIGINTEGER_DATA => array()
- );
-
- $m_length = count($m);
-
- // if ($this->_compare($n, $this->_square($m)) >= 0) {
- if (count($n) > 2 * $m_length) {
- $lhs = new Math_BigInteger();
- $rhs = new Math_BigInteger();
- $lhs->value = $n;
- $rhs->value = $m;
- list(, $temp) = $lhs->divide($rhs);
- return $temp->value;
- }
-
- // if (m.length >> 1) + 2 <= m.length then m is too small and n can't be reduced
- if ($m_length < 5) {
- return $this->_regularBarrett($n, $m);
- }
-
- // n = 2 * m.length
-
- if ( ($key = array_search($m, $cache[MATH_BIGINTEGER_VARIABLE])) === false ) {
- $key = count($cache[MATH_BIGINTEGER_VARIABLE]);
- $cache[MATH_BIGINTEGER_VARIABLE][] = $m;
-
- $lhs = new Math_BigInteger();
- $lhs_value = &$lhs->value;
- $lhs_value = $this->_array_repeat(0, $m_length + ($m_length >> 1));
- $lhs_value[] = 1;
- $rhs = new Math_BigInteger();
- $rhs->value = $m;
-
- list($u, $m1) = $lhs->divide($rhs);
- $u = $u->value;
- $m1 = $m1->value;
-
- $cache[MATH_BIGINTEGER_DATA][] = array(
- 'u' => $u, // m.length >> 1 (technically (m.length >> 1) + 1)
- 'm1'=> $m1 // m.length
- );
- } else {
- extract($cache[MATH_BIGINTEGER_DATA][$key]);
- }
-
- $cutoff = $m_length + ($m_length >> 1);
- $lsd = array_slice($n, 0, $cutoff); // m.length + (m.length >> 1)
- $msd = array_slice($n, $cutoff); // m.length >> 1
- $lsd = $this->_trim($lsd);
- $temp = $this->_multiply($msd, false, $m1, false);
- $n = $this->_add($lsd, false, $temp[MATH_BIGINTEGER_VALUE], false); // m.length + (m.length >> 1) + 1
-
- if ($m_length & 1) {
- return $this->_regularBarrett($n[MATH_BIGINTEGER_VALUE], $m);
- }
-
- // (m.length + (m.length >> 1) + 1) - (m.length - 1) == (m.length >> 1) + 2
- $temp = array_slice($n[MATH_BIGINTEGER_VALUE], $m_length - 1);
- // if even: ((m.length >> 1) + 2) + (m.length >> 1) == m.length + 2
- // if odd: ((m.length >> 1) + 2) + (m.length >> 1) == (m.length - 1) + 2 == m.length + 1
- $temp = $this->_multiply($temp, false, $u, false);
- // if even: (m.length + 2) - ((m.length >> 1) + 1) = m.length - (m.length >> 1) + 1
- // if odd: (m.length + 1) - ((m.length >> 1) + 1) = m.length - (m.length >> 1)
- $temp = array_slice($temp[MATH_BIGINTEGER_VALUE], ($m_length >> 1) + 1);
- // if even: (m.length - (m.length >> 1) + 1) + m.length = 2 * m.length - (m.length >> 1) + 1
- // if odd: (m.length - (m.length >> 1)) + m.length = 2 * m.length - (m.length >> 1)
- $temp = $this->_multiply($temp, false, $m, false);
-
- // at this point, if m had an odd number of digits, we'd be subtracting a 2 * m.length - (m.length >> 1) digit
- // number from a m.length + (m.length >> 1) + 1 digit number. ie. there'd be an extra digit and the while loop
- // following this comment would loop a lot (hence our calling _regularBarrett() in that situation).
-
- $result = $this->_subtract($n[MATH_BIGINTEGER_VALUE], false, $temp[MATH_BIGINTEGER_VALUE], false);
-
- while ($this->_compare($result[MATH_BIGINTEGER_VALUE], $result[MATH_BIGINTEGER_SIGN], $m, false) >= 0) {
- $result = $this->_subtract($result[MATH_BIGINTEGER_VALUE], $result[MATH_BIGINTEGER_SIGN], $m, false);
- }
-
- return $result[MATH_BIGINTEGER_VALUE];
- }
-
- /**
- * (Regular) Barrett Modular Reduction
- *
- * For numbers with more than four digits Math_BigInteger::_barrett() is faster. The difference between that and this
- * is that this function does not fold the denominator into a smaller form.
- *
- * @see _slidingWindow()
- * @access private
- * @param Array $x
- * @param Array $n
- * @return Array
- */
- function _regularBarrett($x, $n)
- {
- static $cache = array(
- MATH_BIGINTEGER_VARIABLE => array(),
- MATH_BIGINTEGER_DATA => array()
- );
-
- $n_length = count($n);
-
- if (count($x) > 2 * $n_length) {
- $lhs = new Math_BigInteger();
- $rhs = new Math_BigInteger();
- $lhs->value = $x;
- $rhs->value = $n;
- list(, $temp) = $lhs->divide($rhs);
- return $temp->value;
- }
-
- if ( ($key = array_search($n, $cache[MATH_BIGINTEGER_VARIABLE])) === false ) {
- $key = count($cache[MATH_BIGINTEGER_VARIABLE]);
- $cache[MATH_BIGINTEGER_VARIABLE][] = $n;
- $lhs = new Math_BigInteger();
- $lhs_value = &$lhs->value;
- $lhs_value = $this->_array_repeat(0, 2 * $n_length);
- $lhs_value[] = 1;
- $rhs = new Math_BigInteger();
- $rhs->value = $n;
- list($temp, ) = $lhs->divide($rhs); // m.length
- $cache[MATH_BIGINTEGER_DATA][] = $temp->value;
- }
-
- // 2 * m.length - (m.length - 1) = m.length + 1
- $temp = array_slice($x, $n_length - 1);
- // (m.length + 1) + m.length = 2 * m.length + 1
- $temp = $this->_multiply($temp, false, $cache[MATH_BIGINTEGER_DATA][$key], false);
- // (2 * m.length + 1) - (m.length - 1) = m.length + 2
- $temp = array_slice($temp[MATH_BIGINTEGER_VALUE], $n_length + 1);
-
- // m.length + 1
- $result = array_slice($x, 0, $n_length + 1);
- // m.length + 1
- $temp = $this->_multiplyLower($temp, false, $n, false, $n_length + 1);
- // $temp == array_slice($temp->_multiply($temp, false, $n, false)->value, 0, $n_length + 1)
-
- if ($this->_compare($result, false, $temp[MATH_BIGINTEGER_VALUE], $temp[MATH_BIGINTEGER_SIGN]) < 0) {
- $corrector_value = $this->_array_repeat(0, $n_length + 1);
- $corrector_value[] = 1;
- $result = $this->_add($result, false, $corrector, false);
- $result = $result[MATH_BIGINTEGER_VALUE];
- }
-
- // at this point, we're subtracting a number with m.length + 1 digits from another number with m.length + 1 digits
- $result = $this->_subtract($result, false, $temp[MATH_BIGINTEGER_VALUE], $temp[MATH_BIGINTEGER_SIGN]);
- while ($this->_compare($result[MATH_BIGINTEGER_VALUE], $result[MATH_BIGINTEGER_SIGN], $n, false) > 0) {
- $result = $this->_subtract($result[MATH_BIGINTEGER_VALUE], $result[MATH_BIGINTEGER_SIGN], $n, false);
- }
-
- return $result[MATH_BIGINTEGER_VALUE];
- }
-
- /**
- * Performs long multiplication up to $stop digits
- *
- * If you're going to be doing array_slice($product->value, 0, $stop), some cycles can be saved.
- *
- * @see _regularBarrett()
- * @param Array $x_value
- * @param Boolean $x_negative
- * @param Array $y_value
- * @param Boolean $y_negative
- * @return Array
- * @access private
- */
- function _multiplyLower($x_value, $x_negative, $y_value, $y_negative, $stop)
- {
- $x_length = count($x_value);
- $y_length = count($y_value);
-
- if ( !$x_length || !$y_length ) { // a 0 is being multiplied
- return array(
- MATH_BIGINTEGER_VALUE => array(),
- MATH_BIGINTEGER_SIGN => false
- );
- }
-
- if ( $x_length < $y_length ) {
- $temp = $x_value;
- $x_value = $y_value;
- $y_value = $temp;
-
- $x_length = count($x_value);
- $y_length = count($y_value);
- }
-
- $product_value = $this->_array_repeat(0, $x_length + $y_length);
-
- // the following for loop could be removed if the for loop following it
- // (the one with nested for loops) initially set $i to 0, but
- // doing so would also make the result in one set of unnecessary adds,
- // since on the outermost loops first pass, $product->value[$k] is going
- // to always be 0
-
- $carry = 0;
-
- for ($j = 0; $j < $x_length; ++$j) { // ie. $i = 0, $k = $i
- $temp = $x_value[$j] * $y_value[0] + $carry; // $product_value[$k] == 0
- $carry = (int) ($temp / 0x4000000);
- $product_value[$j] = (int) ($temp - 0x4000000 * $carry);
- }
-
- if ($j < $stop) {
- $product_value[$j] = $carry;
- }
-
- // the above for loop is what the previous comment was talking about. the
- // following for loop is the "one with nested for loops"
-
- for ($i = 1; $i < $y_length; ++$i) {
- $carry = 0;
-
- for ($j = 0, $k = $i; $j < $x_length && $k < $stop; ++$j, ++$k) {
- $temp = $product_value[$k] + $x_value[$j] * $y_value[$i] + $carry;
- $carry = (int) ($temp / 0x4000000);
- $product_value[$k] = (int) ($temp - 0x4000000 * $carry);
- }
-
- if ($k < $stop) {
- $product_value[$k] = $carry;
- }
- }
-
- return array(
- MATH_BIGINTEGER_VALUE => $this->_trim($product_value),
- MATH_BIGINTEGER_SIGN => $x_negative != $y_negative
- );
- }
-
- /**
- * Montgomery Modular Reduction
- *
- * ($x->_prepMontgomery($n))->_montgomery($n) yields $x % $n.
- * {@link http://math.libtomcrypt.com/files/tommath.pdf#page=170 MPM 6.3} provides insights on how this can be
- * improved upon (basically, by using the comba method). gcd($n, 2) must be equal to one for this function
- * to work correctly.
- *
- * @see _prepMontgomery()
- * @see _slidingWindow()
- * @access private
- * @param Array $x
- * @param Array $n
- * @return Array
- */
- function _montgomery($x, $n)
- {
- static $cache = array(
- MATH_BIGINTEGER_VARIABLE => array(),
- MATH_BIGINTEGER_DATA => array()
- );
-
- if ( ($key = array_search($n, $cache[MATH_BIGINTEGER_VARIABLE])) === false ) {
- $key = count($cache[MATH_BIGINTEGER_VARIABLE]);
- $cache[MATH_BIGINTEGER_VARIABLE][] = $x;
- $cache[MATH_BIGINTEGER_DATA][] = $this->_modInverse67108864($n);
- }
-
- $k = count($n);
-
- $result = array(MATH_BIGINTEGER_VALUE => $x);
-
- for ($i = 0; $i < $k; ++$i) {
- $temp = $result[MATH_BIGINTEGER_VALUE][$i] * $cache[MATH_BIGINTEGER_DATA][$key];
- $temp = (int) ($temp - 0x4000000 * ((int) ($temp / 0x4000000)));
- $temp = $this->_regularMultiply(array($temp), $n);
- $temp = array_merge($this->_array_repeat(0, $i), $temp);
- $result = $this->_add($result[MATH_BIGINTEGER_VALUE], false, $temp, false);
- }
-
- $result[MATH_BIGINTEGER_VALUE] = array_slice($result[MATH_BIGINTEGER_VALUE], $k);
-
- if ($this->_compare($result, false, $n, false) >= 0) {
- $result = $this->_subtract($result[MATH_BIGINTEGER_VALUE], false, $n, false);
- }
-
- return $result[MATH_BIGINTEGER_VALUE];
- }
-
- /**
- * Montgomery Multiply
- *
- * Interleaves the montgomery reduction and long multiplication algorithms together as described in
- * {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf#page=13 HAC 14.36}
- *
- * @see _prepMontgomery()
- * @see _montgomery()
- * @access private
- * @param Array $x
- * @param Array $y
- * @param Array $m
- * @return Array
- */
- function _montgomeryMultiply($x, $y, $m)
- {
- $temp = $this->_multiply($x, false, $y, false);
- return $this->_montgomery($temp[MATH_BIGINTEGER_VALUE], $m);
-
- static $cache = array(
- MATH_BIGINTEGER_VARIABLE => array(),
- MATH_BIGINTEGER_DATA => array()
- );
-
- if ( ($key = array_search($m, $cache[MATH_BIGINTEGER_VARIABLE])) === false ) {
- $key = count($cache[MATH_BIGINTEGER_VARIABLE]);
- $cache[MATH_BIGINTEGER_VARIABLE][] = $m;
- $cache[MATH_BIGINTEGER_DATA][] = $this->_modInverse67108864($m);
- }
-
- $n = max(count($x), count($y), count($m));
- $x = array_pad($x, $n, 0);
- $y = array_pad($y, $n, 0);
- $m = array_pad($m, $n, 0);
- $a = array(MATH_BIGINTEGER_VALUE => $this->_array_repeat(0, $n + 1));
- for ($i = 0; $i < $n; ++$i) {
- $temp = $a[MATH_BIGINTEGER_VALUE][0] + $x[$i] * $y[0];
- $temp = (int) ($temp - 0x4000000 * ((int) ($temp / 0x4000000)));
- $temp = $temp * $cache[MATH_BIGINTEGER_DATA][$key];
- $temp = (int) ($temp - 0x4000000 * ((int) ($temp / 0x4000000)));
- $temp = $this->_add($this->_regularMultiply(array($x[$i]), $y), false, $this->_regularMultiply(array($temp), $m), false);
- $a = $this->_add($a[MATH_BIGINTEGER_VALUE], false, $temp[MATH_BIGINTEGER_VALUE], false);
- $a[MATH_BIGINTEGER_VALUE] = array_slice($a[MATH_BIGINTEGER_VALUE], 1);
- }
- if ($this->_compare($a[MATH_BIGINTEGER_VALUE], false, $m, false) >= 0) {
- $a = $this->_subtract($a[MATH_BIGINTEGER_VALUE], false, $m, false);
- }
- return $a[MATH_BIGINTEGER_VALUE];
- }
-
- /**
- * Prepare a number for use in Montgomery Modular Reductions
- *
- * @see _montgomery()
- * @see _slidingWindow()
- * @access private
- * @param Array $x
- * @param Array $n
- * @return Array
- */
- function _prepMontgomery($x, $n)
- {
- $lhs = new Math_BigInteger();
- $lhs->value = array_merge($this->_array_repeat(0, count($n)), $x);
- $rhs = new Math_BigInteger();
- $rhs->value = $n;
-
- list(, $temp) = $lhs->divide($rhs);
- return $temp->value;
- }
-
- /**
- * Modular Inverse of a number mod 2**26 (eg. 67108864)
- *
- * Based off of the bnpInvDigit function implemented and justified in the following URL:
- *
- * {@link http://www-cs-students.stanford.edu/~tjw/jsbn/jsbn.js}
- *
- * The following URL provides more info:
- *
- * {@link http://groups.google.com/group/sci.crypt/msg/7a137205c1be7d85}
- *
- * As for why we do all the bitmasking... strange things can happen when converting from floats to ints. For
- * instance, on some computers, var_dump((int) -4294967297) yields int(-1) and on others, it yields
- * int(-2147483648). To avoid problems stemming from this, we use bitmasks to guarantee that ints aren't
- * auto-converted to floats. The outermost bitmask is present because without it, there's no guarantee that
- * the "residue" returned would be the so-called "common residue". We use fmod, in the last step, because the
- * maximum possible $x is 26 bits and the maximum $result is 16 bits. Thus, we have to be able to handle up to
- * 40 bits, which only 64-bit floating points will support.
- *
- * Thanks to Pedro Gimeno Fortea for input!
- *
- * @see _montgomery()
- * @access private
- * @param Array $x
- * @return Integer
- */
- function _modInverse67108864($x) // 2**26 == 67108864
- {
- $x = -$x[0];
- $result = $x & 0x3; // x**-1 mod 2**2
- $result = ($result * (2 - $x * $result)) & 0xF; // x**-1 mod 2**4
- $result = ($result * (2 - ($x & 0xFF) * $result)) & 0xFF; // x**-1 mod 2**8
- $result = ($result * ((2 - ($x & 0xFFFF) * $result) & 0xFFFF)) & 0xFFFF; // x**-1 mod 2**16
- $result = fmod($result * (2 - fmod($x * $result, 0x4000000)), 0x4000000); // x**-1 mod 2**26
- return $result & 0x3FFFFFF;
- }
-
- /**
- * Calculates modular inverses.
- *
- * Say you have (30 mod 17 * x mod 17) mod 17 == 1. x can be found using modular inverses.
- *
- * Here's an example:
- *
- * modInverse($b);
- * echo $c->toString(); // outputs 4
- *
- * echo "\r\n";
- *
- * $d = $a->multiply($c);
- * list(, $d) = $d->divide($b);
- * echo $d; // outputs 1 (as per the definition of modular inverse)
- * ?>
- *
- *
- * @param Math_BigInteger $n
- * @return mixed false, if no modular inverse exists, Math_BigInteger, otherwise.
- * @access public
- * @internal See {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf#page=21 HAC 14.64} for more information.
- */
- function modInverse($n)
- {
- switch ( MATH_BIGINTEGER_MODE ) {
- case MATH_BIGINTEGER_MODE_GMP:
- $temp = new Math_BigInteger();
- $temp->value = gmp_invert($this->value, $n->value);
-
- return ( $temp->value === false ) ? false : $this->_normalize($temp);
- }
-
- static $zero, $one;
- if (!isset($zero)) {
- $zero = new Math_BigInteger();
- $one = new Math_BigInteger(1);
- }
-
- // $x mod $n == $x mod -$n.
- $n = $n->abs();
-
- if ($this->compare($zero) < 0) {
- $temp = $this->abs();
- $temp = $temp->modInverse($n);
- return $negated === false ? false : $this->_normalize($n->subtract($temp));
- }
-
- extract($this->extendedGCD($n));
-
- if (!$gcd->equals($one)) {
- return false;
- }
-
- $x = $x->compare($zero) < 0 ? $x->add($n) : $x;
-
- return $this->compare($zero) < 0 ? $this->_normalize($n->subtract($x)) : $this->_normalize($x);
- }
-
- /**
- * Calculates the greatest common divisor and Bézout's identity.
- *
- * Say you have 693 and 609. The GCD is 21. Bézout's identity states that there exist integers x and y such that
- * 693*x + 609*y == 21. In point of fact, there are actually an infinite number of x and y combinations and which
- * combination is returned is dependant upon which mode is in use. See
- * {@link http://en.wikipedia.org/wiki/B%C3%A9zout%27s_identity Bézout's identity - Wikipedia} for more information.
- *
- * Here's an example:
- *
- * extendedGCD($b));
- *
- * echo $gcd->toString() . "\r\n"; // outputs 21
- * echo $a->toString() * $x->toString() + $b->toString() * $y->toString(); // outputs 21
- * ?>
- *
- *
- * @param Math_BigInteger $n
- * @return Math_BigInteger
- * @access public
- * @internal Calculates the GCD using the binary xGCD algorithim described in
- * {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf#page=19 HAC 14.61}. As the text above 14.61 notes,
- * the more traditional algorithim requires "relatively costly multiple-precision divisions".
- */
- function extendedGCD($n)
- {
- switch ( MATH_BIGINTEGER_MODE ) {
- case MATH_BIGINTEGER_MODE_GMP:
- extract(gmp_gcdext($this->value, $n->value));
-
- return array(
- 'gcd' => $this->_normalize(new Math_BigInteger($g)),
- 'x' => $this->_normalize(new Math_BigInteger($s)),
- 'y' => $this->_normalize(new Math_BigInteger($t))
- );
- case MATH_BIGINTEGER_MODE_BCMATH:
- // it might be faster to use the binary xGCD algorithim here, as well, but (1) that algorithim works
- // best when the base is a power of 2 and (2) i don't think it'd make much difference, anyway. as is,
- // the basic extended euclidean algorithim is what we're using.
-
- $u = $this->value;
- $v = $n->value;
-
- $a = '1';
- $b = '0';
- $c = '0';
- $d = '1';
-
- while (bccomp($v, '0', 0) != 0) {
- $q = bcdiv($u, $v, 0);
-
- $temp = $u;
- $u = $v;
- $v = bcsub($temp, bcmul($v, $q, 0), 0);
-
- $temp = $a;
- $a = $c;
- $c = bcsub($temp, bcmul($a, $q, 0), 0);
-
- $temp = $b;
- $b = $d;
- $d = bcsub($temp, bcmul($b, $q, 0), 0);
- }
-
- return array(
- 'gcd' => $this->_normalize(new Math_BigInteger($u)),
- 'x' => $this->_normalize(new Math_BigInteger($a)),
- 'y' => $this->_normalize(new Math_BigInteger($b))
- );
- }
-
- $y = $n->copy();
- $x = $this->copy();
- $g = new Math_BigInteger();
- $g->value = array(1);
-
- while ( !(($x->value[0] & 1)|| ($y->value[0] & 1)) ) {
- $x->_rshift(1);
- $y->_rshift(1);
- $g->_lshift(1);
- }
-
- $u = $x->copy();
- $v = $y->copy();
-
- $a = new Math_BigInteger();
- $b = new Math_BigInteger();
- $c = new Math_BigInteger();
- $d = new Math_BigInteger();
-
- $a->value = $d->value = $g->value = array(1);
- $b->value = $c->value = array();
-
- while ( !empty($u->value) ) {
- while ( !($u->value[0] & 1) ) {
- $u->_rshift(1);
- if ( (!empty($a->value) && ($a->value[0] & 1)) || (!empty($b->value) && ($b->value[0] & 1)) ) {
- $a = $a->add($y);
- $b = $b->subtract($x);
- }
- $a->_rshift(1);
- $b->_rshift(1);
- }
-
- while ( !($v->value[0] & 1) ) {
- $v->_rshift(1);
- if ( (!empty($d->value) && ($d->value[0] & 1)) || (!empty($c->value) && ($c->value[0] & 1)) ) {
- $c = $c->add($y);
- $d = $d->subtract($x);
- }
- $c->_rshift(1);
- $d->_rshift(1);
- }
-
- if ($u->compare($v) >= 0) {
- $u = $u->subtract($v);
- $a = $a->subtract($c);
- $b = $b->subtract($d);
- } else {
- $v = $v->subtract($u);
- $c = $c->subtract($a);
- $d = $d->subtract($b);
- }
- }
-
- return array(
- 'gcd' => $this->_normalize($g->multiply($v)),
- 'x' => $this->_normalize($c),
- 'y' => $this->_normalize($d)
- );
- }
-
- /**
- * Calculates the greatest common divisor
- *
- * Say you have 693 and 609. The GCD is 21.
- *
- * Here's an example:
- *
- * extendedGCD($b);
- *
- * echo $gcd->toString() . "\r\n"; // outputs 21
- * ?>
- *
- *
- * @param Math_BigInteger $n
- * @return Math_BigInteger
- * @access public
- */
- function gcd($n)
- {
- extract($this->extendedGCD($n));
- return $gcd;
- }
-
- /**
- * Absolute value.
- *
- * @return Math_BigInteger
- * @access public
- */
- function abs()
- {
- $temp = new Math_BigInteger();
-
- switch ( MATH_BIGINTEGER_MODE ) {
- case MATH_BIGINTEGER_MODE_GMP:
- $temp->value = gmp_abs($this->value);
- break;
- case MATH_BIGINTEGER_MODE_BCMATH:
- $temp->value = (bccomp($this->value, '0', 0) < 0) ? substr($this->value, 1) : $this->value;
- break;
- default:
- $temp->value = $this->value;
- }
-
- return $temp;
- }
-
- /**
- * Compares two numbers.
- *
- * Although one might think !$x->compare($y) means $x != $y, it, in fact, means the opposite. The reason for this is
- * demonstrated thusly:
- *
- * $x > $y: $x->compare($y) > 0
- * $x < $y: $x->compare($y) < 0
- * $x == $y: $x->compare($y) == 0
- *
- * Note how the same comparison operator is used. If you want to test for equality, use $x->equals($y).
- *
- * @param Math_BigInteger $x
- * @return Integer < 0 if $this is less than $x; > 0 if $this is greater than $x, and 0 if they are equal.
- * @access public
- * @see equals()
- * @internal Could return $this->subtract($x), but that's not as fast as what we do do.
- */
- function compare($y)
- {
- switch ( MATH_BIGINTEGER_MODE ) {
- case MATH_BIGINTEGER_MODE_GMP:
- return gmp_cmp($this->value, $y->value);
- case MATH_BIGINTEGER_MODE_BCMATH:
- return bccomp($this->value, $y->value, 0);
- }
-
- return $this->_compare($this->value, $this->is_negative, $y->value, $y->is_negative);
- }
-
- /**
- * Compares two numbers.
- *
- * @param Array $x_value
- * @param Boolean $x_negative
- * @param Array $y_value
- * @param Boolean $y_negative
- * @return Integer
- * @see compare()
- * @access private
- */
- function _compare($x_value, $x_negative, $y_value, $y_negative)
- {
- if ( $x_negative != $y_negative ) {
- return ( !$x_negative && $y_negative ) ? 1 : -1;
- }
-
- $result = $x_negative ? -1 : 1;
-
- if ( count($x_value) != count($y_value) ) {
- return ( count($x_value) > count($y_value) ) ? $result : -$result;
- }
- $size = max(count($x_value), count($y_value));
-
- $x_value = array_pad($x_value, $size, 0);
- $y_value = array_pad($y_value, $size, 0);
-
- for ($i = count($x_value) - 1; $i >= 0; --$i) {
- if ($x_value[$i] != $y_value[$i]) {
- return ( $x_value[$i] > $y_value[$i] ) ? $result : -$result;
- }
- }
-
- return 0;
- }
-
- /**
- * Tests the equality of two numbers.
- *
- * If you need to see if one number is greater than or less than another number, use Math_BigInteger::compare()
- *
- * @param Math_BigInteger $x
- * @return Boolean
- * @access public
- * @see compare()
- */
- function equals($x)
- {
- switch ( MATH_BIGINTEGER_MODE ) {
- case MATH_BIGINTEGER_MODE_GMP:
- return gmp_cmp($this->value, $x->value) == 0;
- default:
- return $this->value === $x->value && $this->is_negative == $x->is_negative;
- }
- }
-
- /**
- * Set Precision
- *
- * Some bitwise operations give different results depending on the precision being used. Examples include left
- * shift, not, and rotates.
- *
- * @param Math_BigInteger $x
- * @access public
- * @return Math_BigInteger
- */
- function setPrecision($bits)
- {
- $this->precision = $bits;
- if ( MATH_BIGINTEGER_MODE != MATH_BIGINTEGER_MODE_BCMATH ) {
- $this->bitmask = new Math_BigInteger(chr((1 << ($bits & 0x7)) - 1) . str_repeat(chr(0xFF), $bits >> 3), 256);
- } else {
- $this->bitmask = new Math_BigInteger(bcpow('2', $bits, 0));
- }
-
- $temp = $this->_normalize($this);
- $this->value = $temp->value;
- }
-
- /**
- * Logical And
- *
- * @param Math_BigInteger $x
- * @access public
- * @internal Implemented per a request by Lluis Pamies i Juarez
- * login('username', 'password')) {
- * exit('Login Failed');
- * }
- *
- * echo $ssh->exec('ls -la');
- * ?>
- *
- *
- * More information on the SSHv1 specification can be found by reading
- * {@link http://www.snailbook.com/docs/protocol-1.5.txt protocol-1.5.txt}.
- *
- * LICENSE: This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
- * MA 02111-1307 USA
- *
- * @category Net
- * @package Net_SSH1
- * @author Jim Wigginton
- * setPassword('whatever');
- * $key->loadKey(file_get_contents('privatekey'));
- *
- * $ssh = new Net_SSH2('www.domain.tld');
- * if (!$ssh->login('username', $key)) {
- * exit('Login Failed');
- * }
- *
- * echo $ssh->exec('pwd');
- * echo $ssh->exec('ls -la');
- * ?>
- *
- *
- * LICENSE: This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
- * MA 02111-1307 USA
- *
- * @category Net
- * @package Net_SSH2
- * @author Jim Wigginton Table of Contents
- All of the cryptographic libraries included in phpseclib use mcrypt, if available, and an internal implementation
- if it's not. The libraries all use a common interface although some functions, for some algorithms, carry with
- with them certain caveats. Those that do not have caveats attached (or have relatively few attached) are
- described below. If you don't know which one to use, try Crypt_TripleDES
.
-
- The Crypt_* functions require, minimally, PHP 4.0.0. Crypt_TripleDES additionally requires Crypt/DES.php. -
- Sets the key and the initialization vector, respectively. If neither are set, each assumed to be equal to - some amount of null bytes. The initialization vector is only used in block ciphers and even then only - in CBC mode. If the key or the initialization vector are larger then the block size, they're truncated. - If they're smaller, they're padded with null bytes. -
- See php.net's entry on mcrypt_module_open.
- The first parameter is equal to $algorithm_directory
and the second, to $mode_directory
.
-
- Self-explanatory. Encrypts or decrypts messages. See the examples in the subsequent sections. -
- Say you have a 16-byte plaintext $plaintext and that you're using Crypt_DES
. Using the default behavior, the two following code snippets
- will yield different outputs:
-
echo $des->encrypt(substr($plaintext, 0, 8)); - echo $des->encrypt(substr($plaintext, 8, 8));
echo $des->encrypt($plaintext);
- The solution is to enable the continuous buffer. Although this will resolve the above discrepancy, it creates - another, as demonstrated with the following: -
$des->encrypt(substr($plaintext, 0, 8)); - echo $des->decrypt($des->encrypt(substr($plaintext, 8, 8)));
echo $des->decrypt($des->encrypt(substr($plaintext, 8, 8)));
- With the continuous buffer disabled, these would yield the same output. With it enabled, they yield different
- outputs. The reason is due to the fact that the initialization vector's change after every encryption /
- decryption round when the continuous buffer is enabled. When it's disabled, they remain constant.
-
- Put another way, when the continuous buffer is enabled, the state of the Crypt_DES()
object changes after each
- encryption / decryption round, whereas otherwise, it'd remain constant. For this reason, it's recommended that
- continuous buffers not be used. They do offer better security and are, in fact, sometimes required (SSH uses them),
- however, they are also less intuitive and more likely to cause you problems.
-
- Implements DES (a block cipher). Here's an example of how to use it: -
<?php - include('Crypt/DES.php'); - - $des = new Crypt_DES(); - - $des->setKey('abcdefgh'); - - $size = 10 * 1024; - $plaintext = ''; - for ($i = 0; $i < $size; $i++) { - $plaintext.= 'a'; - } - - echo $des->decrypt($des->encrypt($plaintext)); -?>
- The constructor takes one optional parameter - $mode. $mode can be equal to CRYPT_DES_MODE_ECB
- or CRYPT_DES_MODE_CBC
. CRYPT_DES_MODE_CBC
is generally considered more secure
- and is what Crypt_DES
uses by default. If you don't know the difference between ECB or CBC,
- just use the default settings.
-
- Implements TripleDES (a block cipher). Here's an example of how to use it: -
<?php - include('Crypt/TripleDES.php'); - - $des = new Crypt_TripleDES(); - - $des->setKey('abcdefghijklmnopqrstuvwx'); - - $size = 10 * 1024; - $plaintext = ''; - for ($i = 0; $i < $size; $i++) { - $plaintext.= 'a'; - } - - echo $des->decrypt($des->encrypt($plaintext)); -?>
- The constructor takes one optional parameter - $mode. $mode can be equal to CRYPT_DES_MODE_ECB
,
- CRYPT_DES_MODE_CBC
, CRYPT_DES_MODE_3CBC
, or CRYPT_DES_MODE_CBC3
.
- CRYPT_DES_MODE_CBC3
is an alias CRYPT_DES_MODE_CBC
. It's defined to distinguish
- it from CRYPT_DES_MODE_3CBC
, which uses inner chaining to propogate the initialization vector.
- SSH-1 uses this and it is generally considered to be less secure then CRYPT_DES_MODE_CBC3
,
- which uses outer chaining (and is what SSH-2 uses).
-
- Implements RC4 (a stream cipher). Here's an example of how to use it: -
<?php - include('Crypt/RC4.php'); - - $rc4 = new Crypt_RC4(); - - $rc4->setKey('abcdefghijklmnopqrstuvwx'); - - $size = 10 * 1024; - $plaintext = ''; - for ($i = 0; $i < $size; $i++) { - $plaintext.= 'a'; - } - - echo $rc4->decrypt($rc4->encrypt($plaintext)); -?>
- Implements Rijndael / AES. Here's an example of how to use Crypt_AES: -
<?php - include('Crypt/AES.php'); - - $aes = new Crypt_AES(); - - $aes->setKey('abcdefghijklmnop'); - - $size = 10 * 1024; - $plaintext = ''; - for ($i = 0; $i < $size; $i++) { - $plaintext.= 'a'; - } - - echo $aes->decrypt($aes->encrypt($plaintext)); -?>
- Crypt_AES
's constructor takes CRYPT_AES_MODE_ECB
and CRYPT_AES_MODE_CBC
as parameters. Crypt_Rijndael
, CRYPT_RIJNDAEL_MODE_ECB
and CRYPT_RIJNDAEL_MODE_CBC
. In both cases, if no valid mode is defined, CBC will be used.
-
- AES is a subset of Rijndael. Both have variable key sizes, however, AES's block size is fixed at 128 bytes, whereas Rijndael's is variable. Also, Rijndael supports, by means of an extension to the specification, two key sizes that AES does not - 160 bits and 224 bits. -
- Valid key lengths for AES are 128 bits, 192 bits, and 256 bits. If the key that is assigned is invalid and less than 256 bits, they key length is rounded up to the next closest valid size and the key will be null padded to that amount. If the key length is greater than 256 bits, it will be truncated to 256 bits. -
- As an example, if the key is 136 bits, it will be null padded to 192 bits (or 160 bits if Rijndael is being used). -
- If setKeyLength()
has been called, this behavior changes somewhat. Say you've set the key length, via this function, to 256 bits. Then, instead of an invalid key being null padded to 192 or 160 bits, it will be null padded to 256 bits.
-
- setBlockLength()
operates in a manner similar to setKeyLength()
, with one exception. setBlockLength()
only works on Rijndael. Although Crypt_AES
inherits setBlockLength()
as a function, the function doesn't do anything in AES.
-
- The following table compares the speed of five different pure-PHP implementations of AES (one of which is Crypt_Rijndael and one of which is Crypt_AES) when ran on 150KB of text on a 1.8GHz Pentium 4-M. The numbers listed are averaged from five different trials and are measured in seconds. phpseclib's two implementations are highlighted. All implementations can be viewed by clicking on their names. -
Table 3.1. AES Speed Comparisons
movable-type.phps | phpaes.phps | phpclasses1.phps | phpclasses2.phps | phpseclib-aes.phps | phpseclib-rijndael.phps |
---|---|---|---|---|---|
15.6844158172 | 39.9537248135 | 15.0100150108 | 62.591713190079 | 3.5728311081 | 5.24388728142 |
- As can be seen, phpseclib's implementations are the fastest. phpseclib-aes.phps is faster than phpseclib-rijndael.phps because phpseclib-rijndael.phps has to contend with multiple block sizes whereas phpseclib-aes.phps does not. -
Copyright © 2007 - 2010 TerraFrost (Jim Wigginton)
Abstract
- The PHP Secure Communications Library contains LGPL-licensed pure-PHP implementations of arbitrary-precision integers, - fully PKCS#1 (v2.1) compliant RSA, DES, 3DES, RC4, Rijndael, AES, SSH-1, SSH-2, and SFTP. This book discusses how to use them.
Table of Contents
List of Tables
Table of Contents
- Although many of the features this library implements are implemented in PHP via optional extensions, what are - you, as a developer, going to do when a user tries to run your software on a host which, coincidentally, doesn't - happen to have that optional extension installed? You could, flat-out, tell that user to look for another - software package that does work on their server (or to get another host, or whatever), which is liable to leave - a bad impression on the user, or you could use a library like this - a library that uses those optional - extensions if they're available and falls back on an internal PHP implementation if they're not. -
- Another advantage of using this library over optional PHP extensions is that you, as a developer, may find this - libraries API easier to use then extensions API. -
- This library is written using the same conventions that libraries in the PHP Extension and Application Repository (PEAR)
- have been written in. In particular, this library expects to be in your include_path
:
-
<?php -set_include_path(get_include_path() . PATH_SEPARATOR . 'phpseclib'); - -include('Net/SSH2.php'); -?>
Table of Contents
- Implements an arbitrary precision integer arithmetic library. Uses gmp or bcmath, if available, and an - internal implementation, otherwise. Here's an example: -
<?php - include('Math/BigInteger.php'); - - $a = new Math_BigInteger(2); - $b = new Math_BigInteger(3); - - $c = $a->add($b); - - echo $c->toString(); // outputs 5 -?>
- If you're running PHP 5, Math_BigInteger's only dependancy is the PCRE extension (which is enabled by default). Math_BigInteger also works on PHP 4 if PHP/Compat/Function/array_fill.php and PHP/Compat/Function/bcpowmod.php are included. -
- The constructor takes two parameters. The first is the number and the second represents the base. Both - are optional (if they're not provided, the Math_BigInteger object will assume a value of 0). -
- The supported bases are base-2, base-10 (default), base-16, and base-256. To set $a, in the
- above example, to 2, using base-2, we'd do new Math_BigInteger('10', 2)
. To do it using
- base-16, you could do new Math_BigInteger('2', 16)
or new Math_BigInteger('0x2', 16)
.
- To set it to 2 using base-256, you'd do new Math_BigInteger(chr(2), 256)
.
-
- If the base is negative (eg. -256), two's compliment will be used. Thus, new Math_BigInteger(chr(0xFF), -256)
- is equal to -1, as is new Math_BigInteger('0xFFFFFFFF', -16)
and new Math_BigInteger('11', -2)
.
- Basically, if the leading bit is 1, the number is assumed to be negative.
-
- toString()
returns the base-10 form of a number. toBytes()
returns the base-256
- form of a number, toHex()
returns the base-16 form, and toBits()
the base-2 form.
- toBytes()
, toHex()
, and toBits()
also take an optional parameter which,
- if set, will return the two's compliment of a number. So if, for example, $a is equal to -1,
- toBytes(true)
will return chr(0xFF)
.
-
- On PHP 5, toString()
is called automatically when used in a string context via the
- __toString() magic method.
-
- subtract()
and multiply()
operate similarly to add()
. divide()
,
- however, does not. Namely, it returns an array whose first element contains the quotient and whose
- second element contains the "common residue". If the remainder would be positive, the "common residue"
- and the remainder are the same. If the remainder would be negative, the "common residue" is equal to
- the sum of the remainder and the divisor (basically, the "common residue" is the first positive modulo).
- Here's an example:
-
<?php - include('Math/BigInteger.php'); - - $a = new Math_BigInteger('10'); - $b = new Math_BigInteger('20'); - - list($quotient, $remainder) = $a->divide($b); - - echo $quotient->toString(); // outputs 0 - echo "\r\n"; - echo $remainder->toString(); // outputs 10 -?>
- Examples of each follow: -
<?php - include('Math/BigInteger.php'); - - $a = new Math_BigInteger('10'); - $b = new Math_BigInteger('20'); - $c = new Math_BigInteger('30'); - - $c = $a->powMod($b, $c); - - echo $c->toString(); // outputs 10 -?>
<?php - include('Math/BigInteger.php'); - - $a = new Math_BigInteger(30); - $b = new Math_BigInteger(17); - - $c = $a->modInverse($b); - - echo $c->toString(); // outputs 4 -?>
- extendedGCD()
returns an array containing three Math_BigInteger values indexed with x, y,
- and gcd. x and y represent Bézout's identity. gcd()
returns a Math_BigInteger value
- equal to the gcd. An example of each follows:
-
<?php -include('Math/BigInteger.php'); - -$a = new Math_BigInteger(693); -$b = new Math_BigInteger(609); - -extract($a->extendedGCD($b)); -$c = $a->gcd($b); - -echo $gcd->toString() . "\r\n"; // outputs 21 -echo $c->toString() . "\r\n"; // outputs 21 -echo $a->toString() * $x->toString() + $b->toString() * $y->toString(); // outputs 21 -?>
- $x->equals($y)
returns true or false depending on whether or not $x
and
- $y
are equal.
-
- $x->compare($y)
returns 1 if $x > $y, 0 if $x == $y, and -1 if $x < $y. The reason for this
- is demonstrated thusly:
-
$x > $y: $x->compare($y) > 0 -$x < $y: $x->compare($y) < 0 -$x == $y: $x->compare($y) == 0 -$x >= $y: $x->compare($y) >= 0 -$x <= $y: $x->compare($y) <= 0
- As a consequence of this, !$x->compare($y)
does not mean $x != $y
but rather
- $x == $y
.
-
- Some bitwise operations give different results depending on the precision being used. Examples include - left shift, not, and rotates, as discussed for bitwise_not(). - This function lets you control the precision. -
- Whenever a new Math_BigInteger object is created it's precision is set to the same precision as the
- calling object. In other words, if you do $b = $a->bitwise_not()
then $b
will
- have the same precision as $a
.
-
- bitwise_and()
, bitwise_or()
and bitwise_xor()
operate similar to
- add()
. bitwise_not()
is a bit more complicated. To elaborate, if the
- precision (see setPrecision) is arbitrary,
- $x->bitwise_not()
will always yield a smaller value since the most significant bit is
- assumed to have a value of one. With fixed precision, however, the leading bit can be anything.
-
- $a->bitwise_rightShift($shift)
shifts $a by $shift bits, effectively dividing by 2**$shift.
- $a->bitwise_leftShift($shift)
shifts $a by $shift bits, effectively multiplying by 2**$shift.
-
- $a->bitwise_rightRotate($shift)
and $a->bitwise_leftRotate($shift)
are
- demonstrated thusly:
-
<?php -include('Math/BigInteger.php'); - -$a = new Math_BigInteger('00111000', 2); -$a->setPrecision(8); -$b = $a->bitwise_leftRotate(2); -echo $b->toBits(); // returns 11100000 - -echo "\r\n"; - -$a = new Math_BigInteger('00111000', 2); -$b = $a->bitwise_leftRotate(2); -echo $b->toBits(); // returns 100011 -?>
- Just as with bitwise_not(), these operations are - precision dependant. -
- Sets the random generator. To set it to mt_rand()
(which is what it is by default), call
- $x->setRandomGenerator('mt_rand')
.
-
- random($min, $max)
generates a random number between $min
and $max
.
- randomPrime($min, $max)
generates a random prime number between $min
and $max
.
- If no prime number exists between $min
and $max
false is returned.
-
- randomPrime()
has an optional third parameter, as well - $timeout. Generating prime numbers
- is a particurarly expensive operation and although in certain environments even 512-bit primes can be
- generated in a less than a second it can take other environments upwards of around a minute if not more.
-
Table of Contents
The following algorithms are supported:
md2, md5, md5-96, sha1, sha1-96, sha256, sha384, and sha512
- Crypt_Hash requires, minimally, PHP 4.3.0 (due to its use of - sha1()). If sha384 or sha512 are being used and - you're not running PHP 5.1.2 or greater then Math/BigInteger.php is also required. -
- Crypt_Hash uses the hash extension if it's available (> 5.1.2), mhash if it's not, and it's own - internal implementation if not even mhash is available. -
Here's an example of how to encrypt / decrypt with Crypt_RSA:
<?php -include('Crypt/RSA.php'); - -$rsa = new Crypt_RSA(); -extract($rsa->createKey()); - -$plaintext = 'terrafrost'; - -$rsa->loadKey($privatekey); -$ciphertext = $rsa->encrypt($plaintext); - -$rsa->loadKey($publickey); -echo $rsa->decrypt($ciphertext); -?>
Here's an example of how to create / verify a signature with Crypt_RSA:
<?php -include('Crypt/RSA.php'); - -$rsa = new Crypt_RSA(); -extract($rsa->createKey()); - -$plaintext = 'terrafrost'; - -$rsa->loadKey($privatekey); -$signature = $rsa->sign($plaintext); - -$rsa->loadKey($publickey); -echo $rsa->verify($plaintext, $signature) ? 'verified' : 'unverified'; ->
- createKey()
takes three parameters - $bits
, $timeout
,
- and $primes
. $timeout
is present since creating a key has the potential to be
- fairly time consuming and will guarantee that createKey()
does not run for more than
- $timeout
seconds. $primes
lets provide pre-computed prime numbers to speed
- things up.
-
- extract($rsa->createKey())
creates three variables - $publickey
,
- $privatekey
, and $partialkey
. If createKey
hit the timeout then
- it'll return all the primes that it had managed to compute so that you might pass them back to
- createKey()
on a subsequent call.
-
- The exponent can be set by defining CRYPT_RSA_EXPONENT
and multi-prime RSA can be utilized
- by adjusting CRYPT_RSA_SMALLEST_PRIME
. Note that these must be done before a Crypt_RSA()
- object is initialized.
-
- Smaller values for CRYPT_RSA_SMALLEST_PRIME
result in increased speed at the cost of security.
-
Crypt_RSA supports the following formats:
CRYPT_RSA_PRIVATE_FORMAT_PKCS1:
-----BEGIN RSA PRIVATE KEY----- -MIICWgIBAAKBgHx5XHa3LjiugtNq2xkd0oFf2SdsJ04hQYLoeRR3bqAei3Gc+PSy -AvynCIh/03JCvBsUHaCe8BwjwaTYrpq5QunGo/wvIzvx2d3G9dlrpOIFLiatZYOf -h07+CkSfaRXhBUKkul/gU87WPhKEcbnPDJS10uD1HqLsHfSKLNitGOf7AgElAoGA -ENIhQHmedlzFkjEI2eFveURNxw6dhxlANEjtxH7XmRjiaUyQWGsVKQ+nNQpa2Bbb -JkD9FbSc/OI8wz/gPmwP9eJN29CriebhaV3ebM1L1gbb5r7Vf/D/6rxB0BG/h2lA -jyZWEZrV/Gi9ZCaw/J+IUu1pAskKid84yHphvszywCUCQQDigrtr+cVkwkUsxOGd -B378yQCroXmybAD7FQHwVslafuFfTHkaMQSU/ZZLVY1ioMs1VVzzq/vOu0RstZOY -AfHFAkEAjK3mIWdG4JOM44/SrDkACNatsMtXKOi4K3SlXu9ie6ikXPD+GSZ+bWCX -GstFaXr9cHRvZPF3qYtK+j2N9UXOvwJBALeoRO/DmSFDkgifoixLRF5CHDgiD6Vs -U9J/vGIBLaNSHoSe3rtKVr3+CyhTNF3Oe0AABi1bA4UGioGn+yFNr0UCQBbQF3sJ -1CRq9ECT3PlVWfOYbzFtFQ2NhaYul1uAw9yzkEZsROF73SZ+XbFRZTOzFFds08su -E2eaDCiUXDWcnhECQQCRUQn2huHlssj8kt35NAVwiHCNfaeSQ5tiDcwfOywA4YXl -Q+kpuWq5U3V8j/9/n7pE/DL0nXEG/3QpKHJEYV5T ------END RSA PRIVATE KEY-----
CRYPT_RSA_PRIVATE_FORMAT_PKCS1 (with password):
-----BEGIN RSA PRIVATE KEY----- -Proc-Type: 4,ENCRYPTED -DEK-Info: DES-EDE3-CBC,0AE1DB47E71463BE - -pI2Kk5ceURbMYNo1xQqqA5rm2/QP4hgj/HuvrACtPSz/aesbG+h4lYXGpQ9os6Ha -AyFW+iX2UWS6BRwJj1ztO20sKT6ckg7eINSfiSSAeOOiG5aHLxOYayO9aQ5UrrJX -r0QmwRJRiHTW/82PLBNzfFHYskslNI9EWA5L/Gg4NAXDWwDooGvGkDq3ex7WkWLr -k7DN2JoZuWsUZxwpgTDouRQMsygrsdSjwRDSgbnTn6luEBrL9fc5/oAWf0xoTk5h -XMiOOHPBNPiZ1883ayq91HL/6895g8U9oIR1wQmdl0USViYYp5jI19ueowCyblzP -xD3Bfpb6RPaZ/yqECOysPk6PDz257SGDMNk/QrQJ/eZkeniNXHJ8d+nJGuajZeBu -6A/bglvKGNNNWe8UJMb5P2OAliD7y7F9wXrkV5FnQ/Q49tGxdBl7WXNuGp4x2d9s -ZEnv3mOtrr1lM+2QE0Zg8mjqSem5b6Dp0LxOj5j45j5IbBrrd3MKu87jJVzp8yHy -sBC6NMYYtO03qxV/j1kJR+MmAcCF1+4GGRWdFcoc0sXGVqmEOmK4QfYx3T0Vb6Hk -oLdlh6ofZogezzJ8A1BvV382sTsJ90eqbgz3E+fDl8iR86+EV9bUujFE4IaBgZJP -gxikVItdTcq1frNKTCSH/RPeRwk+oKWTpCYGgNA+bl641onW1DCLYcd14N6TDKmY -77cOTf2ZDGOYNPycAF/FnNJJyLO3IYpU63aKBshB4dYeVrfH0FvG6g5Xt0geIkiD -5W9El4ks7/3r97x443SagDRt6Mceo5TtzzFfAo7cZeA= ------END RSA PRIVATE KEY-----
CRYPT_RSA_PUBLIC_FORMAT_PKCS1:
-----BEGIN PUBLIC KEY----- -MIGGAoGAfHlcdrcuOK6C02rbGR3SgV/ZJ2wnTiFBguh5FHduoB6LcZz49LIC/KcIiH/TckK8GxQd -oJ7wHCPBpNiumrlC6caj/C8jO/HZ3cb12Wuk4gUuJq1lg5+HTv4KRJ9pFeEFQqS6X+BTztY+EoRx -uc8MlLXS4PUeouwd9Ios2K0Y5/sCASU= ------END PUBLIC KEY-----
CRYPT_RSA_PUBLIC_FORMAT_OPENSSH:
ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIB8eVx2ty44roLTatsZHdKBX9knbCdOIUGC6HkUd26gHotx -nPj0sgL8pwiIf9NyQrwbFB2gnvAcI8Gk2K6auULpxqP8LyM78dndxvXZa6TiBS4mrWWDn4dO/gpEn2kV -4QVCpLpf4FPO1j4ShHG5zwyUtdLg9R6i7B30iizYrRjn+w== phpseclib-generated-key
- Passwords can be set via setPassword()
and are only supported on private keys.
- CRYPT_RSA_PUBLIC_FORMAT_OPENSSH generates keys that are intended to go in $HOME/.ssh/authorized_keys
- for use with OpenSSH. Another format - CRYPT_RSA_PUBLIC_FORMAT_RAW - is stored as an array with two
- indexes - one for the modulus and one for the exponent. Indexes accepted by loadkey()
- are as follows:
-
- e, exponent, publicExponent, modulus, modulo, n -
- loadKey()
has two parameters - $key
and the optional $type
.
- The default type, if $type
is not explicitely set, is CRYPT_RSA_PRIVATE_FORMAT_PKCS1.
- It should, at this point, be noted that Crypt_RSA treats public and private keys largelly identically.
- A key can be formatted as a CRYPT_RSA_PUBLIC_FORMAT_PKCS1 and still conform to the
- CRYPT_RSA_PRIVATE_FORMAT_PKCS1 format and vice versa. The only real difference between private keys and
- public keys is that private keys *can* contain their public key counterparts whereas public keys cannot.
- That said, this distinction is, for the most part, irrelevant and academic. For a more thorough
- discussion of this see setPublicKey() and getPublicKey().
-
- As noted in setPrivateKeyFormat(), setPublicKeyFormat(), loadKey() and setPassword(),
- Crypt_RSA treats public and private keys largely identically. The only real difference is that some
- private key formats contain the public key within them whereas no public key format does. The reason
- you'd want to do this is for indexing purposes. For example, in SSH-2, RSA authentication works by
- sending your public key along with a signature created by your private key. The SSH-2 server then looks
- the public key up in an index of public keys to see if it's an allowed key and then verifies the signature.
- To that end, setPublicKey()
defines the public key if it hasn't already been defined and
- getPublicKey()
returns it. getPublicKey()
has an optional parameter - $type -
- that sets the format.
-
- Crypt_RSA supports two encryption modes - CRYPT_RSA_ENCRYPTION_OAEP
and
- CRYPT_RSA_ENCRYPTION_PKCS1
. CRYPT_RSA_ENCRYPTION_OAEP
uses
- Optimal Asymmetric Encryption Padding
- and provides more security than CRYPT_RSA_ENCRYPTION_PKCS1
.
-
- Both CRYPT_RSA_ENCRYPTION_OAEP
and CRYPT_RSA_ENCRYPTION_PKCS1
impose limits
- on how large the plaintext can be. If the plaintext exceeds these limits the plaintext will be split
- up such that each block falls within those limits.
-
- Crypt_RSA supports two signature modes - CRYPT_RSA_SIGNATURE_PSS
and
- CRYPT_RSA_SIGNATURE_PKCS1
. The former is assumed to provide more security than the latter.
- See Examples for examples.
-
- In all likelihood, calling these functions will be unnecessary as the default values should be sufficient. - None-the-less a discussion of them follows. -
- setHash()
is used with signature production / verification and (if the encryption mode is
- CRYPT_RSA_ENCRYPTION_OAEP) encryption and decryption. If the specified hash isn't supported sha1 will
- be used.
-
- setMGFHash()
determines which hashing function should be used for the mask generation
- function as utilized in CRYPT_RSA_ENCRYPTION_OAEP and CRYPT_RSA_SIGNATURE_PSS. PKCS#1 recommends
- but does not require that the MGFHash and the Hash be set to the same thing.
-
- setSaltLength()
is only utilized with CRYPT_RSA_SIGNATURE_PSS. PKCS#1 recommends this
- value either be 0 (which is what it is by default) or the length of the output of the hash function as
- set via setHash()
-
Table of Contents
- The Net_SSH1 and Net_SSH2 libraries have, for the most part, an identical API. Some functions, however, do behave differently. -
- Net_SSH1/2 require, minimally, Math/BigInteger.php, Crypt/*.php, and PHP/Compat/Function/*.php. Net_SSH1 requires PHP 4.0.0 unless you're using the interactive functions, which require PHP 4.3.0. Net_SSH2 requires PHP 4.3.0 due to it's use of sha1(). -
<?php - include('Net/SSH1.php'); - - $ssh = new Net_SSH1('www.domain.tld'); - if (!$ssh->login('username', 'password')) { - exit('Login Failed'); - } - - while (true) { - echo $ssh->interactiveRead(); - - $read = array(STDIN); - $write = $except = NULL; - if (stream_select($read, $write, $except, 0)) { - $ssh->interactiveWrite(fread(STDIN, 1)); - } - } -?>
<?php - include('Net/SSH1.php'); - - $ssh = new Net_SSH1('www.domain.tld'); - if (!$ssh->login('username', 'password')) { - exit('Login Failed'); - } - - echo $ssh->exec('ls -la'); -?>
<?php - include('Net/SSH2.php'); - - $ssh = new Net_SSH2('www.domain.tld'); - if (!$ssh->login('username', 'password')) { - exit('Login Failed'); - } - - echo $ssh->exec('pwd'); - echo $ssh->exec('ls -la'); -?>
<?php - include('Crypt/RSA.php'); - include('Net/SSH2.php'); - - $key = new Crypt_RSA(); - //$key->setPassword('whatever'); - $key->loadKey(file_get_contents('privatekey')); - - $ssh = new Net_SSH2('www.domain.tld'); - if (!$ssh->login('username', $key)) { - exit('Login Failed'); - } - - echo $ssh->exec('pwd'); - echo $ssh->exec('ls -la'); -?<
- SSH protects itself against active eavesdroppers by providing a host key. The first time you connect the host key is supposed to be cached in some manner. On subsequent connections, the host key being used for this connection should be checked against the cached host key. If they match, it's the same server. If not, it's a different one. -
- In SSH-1, getHostKeyPublicModulus()
and getHostKeyPublicExponent()
will provide you with the host key. In SSH-2, getServerPublicHostKey()
gets you the key.
-
- The Net_SSH1 and Net_SSH2 examples omit the key verification stage for brevity. Also, depending on the context in which this library is used, it may even be unnecessary. For example, if you're connecting to www.example.com:22 from www.example.com:80, eavesdroppers are not something you need to worry about. -
- Say you wanted to use SSH to get the contents of a directory. If you used interactiveWrite('ls')
to do this, and then interactiveRead()
to get the output, you, in all likelihood, wouldn't get the whole output. You'd have to call interactiveRead()
multiple times - you'd have to call it as many times as it took for you to get the complete output, which, in turn, begs the question... how do you know when you have the complete output?
- You could assume that whenever the prompt (eg. root@desktop:/root#
) showed up, that that'd mean you had the complete output, but that's not fool proof. And what about messages of the day? The first interactiveRead()
you do is liable to include a part of that rather than the directory listing. So, not only do you have to make some sort of guestimate as to when the output ends - you often may have to guestimate as to when it begins.
-
- To top it all off, you may also get ANSI escape codes interspersed amongst the output, which would need to be removed. -
- Using exec('ls')
resolves all of these issues. If you're implementing an interactive client, the interactive functions are the ones you'll want to use. Otherwise, exec()
is likely what you'll want to use.
-
- interactiveRead() / interactiveWrite() are not implemented in Net_SSH2. The SSH-2 protocol supports them, however, phpseclib does not. The reasons are discussed in the SSH-1's exec() vs. SSH-2's exec() section. -
- exec()
works by creating a channel, issuing a command, and then subsequently destroying that channel. Since SSH-1 only allows one channel, exec() can only be called once. SSH-2, in contrast, allows an unlimited number of channels, and as such, you can perform as many exec()
's as you see fit.
-
- As a consequence of this difference, Net_SSH2 does not implement interactiveRead() / interactiveWrite(), even though the SSH-2 specifications provide for those functions. Simply put, in SSH-1, those functions are necessary to do multiple commands. In SSH-2, they're not, and so they're not implemented. -
- Successive calls to SSH-2's exec() may not work as expected. Consider the following: -
<?php - include('Net/SSH2.php'); - - $ssh = new Net_SSH2('www.domain.tld'); - if (!$ssh->login('username', 'password')) { - exit('Login Failed'); - } - - echo $ssh->exec('pwd'); - echo $ssh->exec('cd /'); - echo $ssh->exec('pwd'); -?>
- If done on an interactive shell, the output you'd receive for the first pwd
would (depending on how your system is setup) be different than the output of the second pwd
. The above code snippet, however, will yield two identical lines. The reason for this is that any "state changes" you make to the one-time shell are gone once the exec()
has been ran and the channel has been deleted.
- As such, if you want to support cd
in your program, it'd be best to just handle that internally and rewrite all commands, before they're passed to exec()
such that the relative paths are expanded to the absolute paths.
- Alternatively, one could always run a shell script, however, that may not always be an option.
-
- To log output, the NET_SSH2_LOGGING constant will need to be defined. If you want full logs, you'll need to do define('NET_SSH2_LOGGING', NET_SSH2_LOG_COMPLEX)
. $ssh->getLog()
will then return a string containing the unencrypted packets in hex and ASCII. If you want to just record the packet types that are being sent to and fro, you'll need to do define('NET_SSH2_LOGGING', NET_SSH2_LOG_SIMPLE)
. $ssh->getLog()
will then return an array. Both log types include the amount of time it took to send the packet in question. The former is useful for general diagnostics and the latter is more useful for profiling. An example follows:
-
<?php - include('Net/SSH2.php'); - define('NET_SSH2_LOGGING', NET_SSH2_LOG_COMPLEX); - - $ssh = new Net_SSH2('www.domain.tld'); - if (!$ssh->login('username', 'password')) { - exit('Login Failed'); - } - - echo $ssh->exec('pwd'); - echo $ssh->getLog(); -?>
- Depending on the problem, it may be more effective to just look at the output of $ssh->getLastError()
(which returns a string) and $ssh->getErrors()
(which returns an array) than to sift through the logs.
-
- Net_SFTP currently only supports SFTPv3, which, according to wikipedia.org, "is the most widely used - version, implemented by the popular OpenSSH SFTP server". -
- Net_SFTP requires, minimally, PHP 4.3.0 and Net/SSH2.php, Math/BigInteger.php, Crypt/*.php, and PHP/Compat/Function/*.php. -
<?php -include('Net/SFTP.php'); - -$sftp = new Net_SFTP('www.domain.tld'); -if (!$sftp->login('username', 'password')) { - exit('Login Failed'); -} - -echo $sftp->pwd() . "\r\n"; -$sftp->put('filename.ext', 'hello, world!'); -print_r($sftp->nlist()); -?>
- By default, put() does not read from the local filesystem. $data is dumped directly into $remote_file. - So, for example, if you set $data to 'filename.ext' and then do get(), you will get a file, twelve bytes - long, containing 'filename.ext' as its contents. -
- Setting $mode to NET_SFTP_LOCAL_FILE will change the above behavior. With NET_SFTP_LOCAL_FILE, $remote_file will - contain as many bytes as filename.ext does on your local filesystem. If your filename.ext is 1MB then that is how - large $remote_file will be, as well. -
- Currently, only binary mode is supported. As such, if the line endings need to be adjusted, you will need to take - care of that, yourself. -
- Returns a string containing the contents of $remote_file if $local_file is left undefined or a boolean false if - the operation was unsuccessful. If $local_file is defined, returns true or false depending on the success of the - operation -
- pwd() returns the current directory, chdir() changes directories, mkdir() creates direcotires, and rmdir() removes directories. - In the event of failure, they all return false. chdir(), mkdir(), and rmdir() return true on successful completion of the operation. -
- chmod() sets the permissions on a file and returns the new file permissions on success or false on error. Permissions are expected to be in octal so to set a file to 777 do $sftp->chmod(0777, $filename)
-
- size() returns the size, in bytes, of an arbitrary file. -
- nlist($dir = '.') returns the contents of the current directory as a numerically indexed array and rawlist() returns an associate array where the filenames are the array keys and the array values are, themselves, arrays containing the file attributes. The directory can be changed with the first parameter. -
- The purpose of both functions should be easy enough to glean - delete() deletes files or directories and rename() renames them. Both return true on success and false on failure. -
- Debbuging SFTP connections in phpseclib works in a manner similar to debugging SSH-2 Instead of the constant being NET_SSH2_LOGGING, however, it's NET_SFTP_LOGGING
. And instead of NET_SSH2_LOG_COMPLEX or NET_SSH2_LOG_SIMPLE it's NET_SFTP_LOG_COMPLEX or NET_SFTP_LOG_SIMPLE respectively. And instead of calling $sftp->getLog() you call $sftp->getSFTPLog()
or $sftp->getLastSFTPError()
or whatever.
-
Table of Contents
- All of the cryptographic libraries included in phpseclib use mcrypt, if available, and an internal implementation
- if it's not. The libraries all use a common interface although some functions, for some algorithms, carry with
- with them certain caveats. Those that do not have caveats attached (or have relatively few attached) are
- described below. If you don't know which one to use, try Crypt_TripleDES
.
-
- The Crypt_* functions require, minimally, PHP 4.0.0. Crypt_TripleDES additionally requires Crypt/DES.php. -
- Sets the key and the initialization vector, respectively. If neither are set, each assumed to be equal to - some amount of null bytes. The initialization vector is only used in block ciphers and even then only - in CBC mode. If the key or the initialization vector are larger then the block size, they're truncated. - If they're smaller, they're padded with null bytes. -
- Self-explanatory. Encrypts or decrypts messages. See the examples in the subsequent sections. -
- If the continuous buffer is enabled and you're using a stream cipher or a block cipher mode other than ECB then encrypting the same string twice will yield different ciphertexts. - The reason being that the IV doesn't reset after each encryption / decryption round when the continuous buffer is used. - This provides better security but it may also make for less intuitive behavior. - For this reason, the continuous buffer is disabled by default. -
- Enables / disables PKCS padding on block ciphers. Stream ciphers (Crypt_RC4
is the only stream
- cipher currently included) ignore this.
-
- Most stream ciphers (and block ciphers operating in a mode - like CTR - that turns them into stream ciphers) work by generating a stream of pseudorandom characters called a keystream and then XOR'ing that with the plaintext.
- This *effectively* makes them one-time pads which, in theory, can provide perfect secrecy. The problem with one-time pads is that they're not as versatile as one might desire.
- Among other things, a keystream must never be reset, lest it be possible for an attacker to recover the keystream via a known-plaintext attack. ie. $ciphertext ^ $plaintext = $key
. If $key
is constant (because the keystream's being reset or something) than an attacker can recover any $plaintext
, but if not - if it's dynamic - then the only key that an attacker could recover is their own.
-
- Implements DES (a block cipher). Here's an example of how to use it: -
<?php - include('Crypt/DES.php'); - - $des = new Crypt_DES(); - - $des->setKey('abcdefgh'); - - $size = 10 * 1024; - $plaintext = ''; - for ($i = 0; $i < $size; $i++) { - $plaintext.= 'a'; - } - - echo $des->decrypt($des->encrypt($plaintext)); -?>
- Implements TripleDES (a block cipher). Here's an example of how to use it: -
<?php - include('Crypt/TripleDES.php'); - - $des = new Crypt_TripleDES(); - - $des->setKey('abcdefghijklmnopqrstuvwx'); - - $size = 10 * 1024; - $plaintext = ''; - for ($i = 0; $i < $size; $i++) { - $plaintext.= 'a'; - } - - echo $des->decrypt($des->encrypt($plaintext)); -?>
- The constructor takes one optional parameter - $mode. Valid values for $mode are as follows: -
CRYPT_DES_MODE_ECB
CRYPT_DES_MODE_CBC3
: Employs outer chaining to propogate the initialization vector. Used by SSH-2 and generally considered more secure than inner chaining.CRYPT_DES_MODE_3CBC
: Employs inner chaining to propogate the initialization vector. Used by SSH-1.CRYPT_DES_MODE_CBC
: The default value. An alias for CRYPT_DES_MODE_CBC3
.CRYPT_DES_MODE_CTR
- Implements RC4 (a stream cipher). Here's an example of how to use it: -
<?php - include('Crypt/RC4.php'); - - $rc4 = new Crypt_RC4(); - - $rc4->setKey('abcdefghijklmnopqrstuvwx'); - - $size = 10 * 1024; - $plaintext = ''; - for ($i = 0; $i < $size; $i++) { - $plaintext.= 'a'; - } - - echo $rc4->decrypt($rc4->encrypt($plaintext)); -?>
- Implements Rijndael / AES. Here's an example of how to use Crypt_AES: -
<?php - include('Crypt/AES.php'); - - $aes = new Crypt_AES(); - - $aes->setKey('abcdefghijklmnop'); - - $size = 10 * 1024; - $plaintext = ''; - for ($i = 0; $i < $size; $i++) { - $plaintext.= 'a'; - } - - echo $aes->decrypt($aes->encrypt($plaintext)); -?>
- Crypt_AES
's constructor's optional parameter can take the following values:
-
CRYPT_AES_MODE_ECB
CRYPT_AES_MODE_CBC
: The default value.CRYPT_AES_MODE_CTR
- Crypt_Rijndael
takes the following:
-
CRYPT_RIJNDAEL_MODE_ECB
CRYPT_RIJNDAEL_MODE_CBC
: The default value.CRYPT_RIJNDAEL_MODE_CTR
- AES is a subset of Rijndael. Both have variable key sizes, however, AES's block size is fixed at 128 bits, whereas Rijndael's is variable. Also, Rijndael supports, by means of an extension to the specification, two key sizes that AES does not - 160 bits and 224 bits. -
- Valid key lengths for AES are 128 bits, 192 bits, and 256 bits. If the key that is assigned is invalid and less than 256 bits, they key length is rounded up to the next closest valid size and the key will be null padded to that amount. If the key length is greater than 256 bits, it will be truncated to 256 bits. -
- As an example, if the key is 136 bits, it will be null padded to 192 bits (or 160 bits if Rijndael is being used). -
- If setKeyLength()
has been called, this behavior changes somewhat. Say you've set the key length, via this function, to 256 bits. Then, instead of an invalid key being null padded to 192 or 160 bits, it will be null padded to 256 bits.
-
- setBlockLength()
operates in a manner similar to setKeyLength()
, with one exception. setBlockLength()
only works on Rijndael. Although Crypt_AES
inherits setBlockLength()
as a function, the function doesn't do anything in AES.
-
- The following table compares the speed of five different pure-PHP implementations of AES (one of which is Crypt_Rijndael and one of which is Crypt_AES) when ran on 150KB of text on a 1.8GHz Pentium 4-M. The numbers listed are averaged from five different trials and are measured in seconds. phpseclib's two implementations are highlighted. All implementations can be viewed by clicking on their names. -
Table 3.1. AES Speed Comparisons
movable-type.phps | phpaes.phps | phpclasses1.phps | phpclasses2.phps | phpseclib-aes.phps | phpseclib-rijndael.phps |
---|---|---|---|---|---|
15.6844158172 | 39.9537248135 | 15.0100150108 | 62.591713190079 | 2.03581542968752 | 2.62501101493836 |
- As can be seen, phpseclib's implementations are the fastest. phpseclib-aes.phps is faster than phpseclib-rijndael.phps because phpseclib-rijndael.phps has to contend with multiple block sizes whereas phpseclib-aes.phps does not. Note that if mcrypt weren't explicitily disabled phpseclib would have been even faster. -
$fillwith
$fillext
-$invite_desc