function powmod($base, $exponent, $modulus) { if (function_exists('gmp_powm')) { // fast return gmp_strval(gmp_powm($base, $exponent, $modulus)); } if (function_exists('bi_powmod')) { // not tested return bi_sto_str(bi_powmod($base, $exponent, $modulus)); } if (function_exists('bcpowmod')) { // slow return bcpowmod($base, $exponent, $modulus); } // emulation, slow $square = bcmod($base, $modulus); $result = 1; while (bccomp($exponent, 0) > 0) { if (bcmod($exponent, 2)) { $result = bcmod(bcmul($result, $square), $modulus); } $square = bcmod(bcmul($square, $square), $modulus); $exponent = bcdiv($exponent, 2); } return $result; }
public function xrecover($y) { $xx = gmp_mul(gmp_sub(gmp_mul($y, $y), 1), $this->inv(gmp_add(gmp_mul(gmp_mul($this->params['d'], $y), $y), 1))); $x = gmp_powm($xx, gmp_div_q(gmp_add($this->params['q'], 3), 8), $this->params['q']); $t = gmp_mod(gmp_sub(gmp_mul($x, $x), $xx), $this->params['q']); if (gmp_cmp($t, 0)) { $x = gmp_mod(gmp_mul($x, $this->params['I']), $this->params['q']); } if (gmp_cmp(gmp_mod($x, 2), 0)) { $x = gmp_sub($this->params['q'], $x); } return $x; }
/** * Construct a new SSH_MSG_KEXDH_REPLY message. * * \param fpoirotte::Pssht::Messages::KEXDH::INIT $kexDHInit * Client's contribution to the Diffie-Hellman Key Exchange. * * \param fpoirotte::Pssht::PublicKeyInterface $key * Server's public key. * * \param fpoirotte::Pssht::EncryptionInterface $encryptionAlgo * Encryption algorithm in use. * * \param fpoirotte::Pssht::KEXInterface $kexAlgo * Key exchange algorithm to use. * * \param fpoirotte::Pssht::Messages::KEXINIT $serverKEX * Algorithms supported by the server. * * \param fpoirotte::Pssht::Messages::KEXINIT $clientKEX * Algorithms supported by the client. * * \param string $serverIdent * Server's identification string * * \param string $clientIdent * Client's identification string */ public function __construct(\fpoirotte\Pssht\Messages\KEXDH\INIT $kexDHInit, \fpoirotte\Pssht\PublicKeyInterface $key, \fpoirotte\Pssht\EncryptionInterface $encryptionAlgo, \fpoirotte\Pssht\KEXInterface $kexAlgo, \fpoirotte\Pssht\Messages\KEXINIT $serverKEX, \fpoirotte\Pssht\Messages\KEXINIT $clientKEX, $serverIdent, $clientIdent) { if (!is_string($serverIdent)) { throw new \InvalidArgumentException(); } if (!is_string($clientIdent)) { throw new \InvalidArgumentException(); } $keyLength = min(20, max($encryptionAlgo->getKeySize(), 16)); $randBytes = openssl_random_pseudo_bytes(2 * $keyLength); $y = gmp_init(bin2hex($randBytes), 16); $prime = gmp_init($kexAlgo::getPrime(), 16); $this->f = gmp_powm($kexAlgo::getGenerator(), $y, $prime); $this->K = gmp_powm($kexDHInit->getE(), $y, $prime); $this->K_S = $key; $this->kexDHInit = $kexDHInit; $this->kexAlgo = $kexAlgo; $this->serverKEX = $serverKEX; $this->clientKEX = $clientKEX; $this->serverIdent = $serverIdent; $this->clientIdent = $clientIdent; $msgId = chr(\fpoirotte\Pssht\Messages\KEXINIT::getMessageId()); // $sub is used to create the structure for the hashing function. $sub = new \fpoirotte\Pssht\Wire\Encoder(new \fpoirotte\Pssht\Buffer()); $this->K_S->serialize($sub); $K_S = $sub->getBuffer()->get(0); $sub->encodeString($this->clientIdent); $sub->encodeString($this->serverIdent); // $sub2 is used to compute the value // of various fields inside the structure. $sub2 = new \fpoirotte\Pssht\Wire\Encoder(new \fpoirotte\Pssht\Buffer()); $sub2->encodeBytes($msgId); // Add message identifier. $this->clientKEX->serialize($sub2); $sub->encodeString($sub2->getBuffer()->get(0)); $sub2->encodeBytes($msgId); // Add message identifier. $this->serverKEX->serialize($sub2); $sub->encodeString($sub2->getBuffer()->get(0)); $sub->encodeString($K_S); $sub->encodeMpint($this->kexDHInit->getE()); $sub->encodeMpint($this->f); $sub->encodeMpint($this->K); $logging = \Plop\Plop::getInstance(); $origData = $sub->getBuffer()->get(0); $data = wordwrap(bin2hex($origData), 4, ' ', true); $data = wordwrap($data, 32 + 7, PHP_EOL, true); $logging->debug("Signature payload:\r\n%s", array($data)); $this->H = $this->kexAlgo->hash($origData); }
public static function calculateV($s, $sha_pass_hash) { $s = self::hexDecode($s); $sha_pass_hash = self::hexDecode($sha_pass_hash); if (strlen($s) != 32 || strlen($sha_pass_hash) != 20) { throw new exception("calculateV: invalid argument"); } $x = self::hexEncode(strrev(sha1(strrev($s) . $sha_pass_hash, true))); $v = gmp_powm(self::$g, gmp_init($x, 16), self::$N); $strval = gmp_strval($v, 16); // append leading zeros while (strlen($strval) < 64) { $strval = "0" . $strval; } return $strval; }
public function checkAuth($nick, $passwd) { if (substr($this->pwdHash, 0, 3) === '#1#') { // 1st case: new, SHA256 SRP logins // https://tools.ietf.org/html/rfc2945#section-3 $pwdArr = explode('#', $this->pwdHash); $x = gmp_import(hash("sha256", base64_decode($pwdArr[2]) . hash("sha256", strtolower($nick) . ':' . $passwd, true), true), 1, GMP_MSW_FIRST | GMP_BIG_ENDIAN); $N = gmp_init("AC6BDB41324A9A9BF166DE5E1389582FAF72B6651987EE07FC3192943DB56050A37329CBB4" . "A099ED8193E0757767A13DD52312AB4B03310DCD7F48A9DA04FD50E8083969EDB767B0CF60" . "95179A163AB3661A05FBD5FAAAE82918A9962F0B93B855F97993EC975EEAA80D740ADBF4FF" . "747359D041D5C33EA71D281E446B14773BCA97B43A23FB801676BD207A436C6481F1D2B907" . "8717461A5B9D32E688F87748544523B524B0D57D5EA77A2775D2ECFA032CFBDBF52FB37861" . "60279004E57AE6AF874E7303CE53299CCC041C7BC308D82A5698F3A8D0C38271AE35F8E9DB" . "FBB694B5C803D89F7AE435DE236D525F54759B65E372FCD68EF20FA7111F9E4AFF73", 16); $g = gmp_init(2); $v = gmp_powm($g, $x, $N); // strpos to check if the saved has is the same as our hash, minus the possible base64 padding return strpos(base64_encode(gmp_export($v, 1, GMP_MSW_FIRST | GMP_BIG_ENDIAN)), $pwdArr[3]) === 0; } else { // 2nd case: old, pre-SRP logins using salted SHA1 // src/util/auth.cpp#34 at rev 0bf1984d2c9fb3a9dc73303551c18906c3c9482b // https://github.com/minetest/minetest/blob/0bf1984d2c9fb3a9dc73303551c18906c3c9482b/src/util/auth.cpp#L34 return strpos(base64_encode(hash("sha1", $nick . $passwd, true)), $this->pwdHash) === 0; } return false; }
public static function modular_exp($base, $exponent, $modulus) { if (extension_loaded('gmp') && USE_EXT == 'GMP') { if ($exponent < 0) { return new ErrorException("Negative exponents (" . $exponent . ") not allowed"); } else { $p = gmp_strval(gmp_powm($base, $exponent, $modulus)); return $p; } } elseif (extension_loaded('bcmath') && USE_EXT == 'BCMATH') { if ($exponent < 0) { return new ErrorException("Negative exponents (" . $exponent . ") not allowed"); } else { $p = bcpowmod($base, $exponent, $modulus); return $p; } } else { throw new ErrorException("Please install BCMATH or GMP"); } }
/** * verify using gmp extendsions */ function _verifyByGmp($message, $sig, $sigKeys) { $p = $sigKeys['p']; $q = $sigKeys['q']; $g = $sigKeys['g']; $pubKey = $sigKeys['pub_key']; list($r_sig, $s_sig) = explode(":", $sig); $r_sig = base64_decode($r_sig); $s_sig = base64_decode($s_sig); $p = gmp_init($p); $q = gmp_init($q); $g = gmp_init($g); $pubKey = gmp_init($pubKey); $s1 = Security_DSA::_bindecGmp($r_sig); $s2 = Security_DSA::_bindecGmp($s_sig); $w = gmp_invert($s2, $q); $hash_m = gmp_init('0x' . sha1($message)); $u1 = gmp_mod(gmp_mul($hash_m, $w), $q); $u2 = gmp_mod(gmp_mul($s1, $w), $q); $v = gmp_mod(gmp_mod(gmp_mul(gmp_powm($g, $u1, $p), gmp_powm($pubKey, $u2, $p)), $p), $q); return gmp_cmp($v, $s1) == 0; }
/** * @param string $left_operand * @param string $right_operand * @return string */ public function powmod($left_operand, $right_operand, $modulus) { $result = gmp_powm($left_operand, $right_operand, $modulus); return gmp_strval($result); }
/** * @param ssh\PacketProtocol * @param Side * @param Side * @param mixed array of Key-s if local side is SERVER, string with expected public * key if local side is CLIENT */ function kex(ssh\PacketProtocol $protocol, Side $local, Side $remote, $keys) { $send = $local->type . '_to_' . $remote->type; $receive = $remote->type . '_to_' . $local->type; if ($local->type === Side::CLIENT) { $local_pk_algorithms = array('ssh-dss', 'ssh-rsa'); } else { $local_pk_algorithms = array_keys($keys); } $local->kexinit_packet = ssh\format('brnnnnnnnnnnbu', ssh\SSH_MSG_KEXINIT, ssh\random(16), $local_kex_algorithms = array('diffie-hellman-group1-sha1', 'diffie-hellman-group14-sha1'), $local_pk_algorithms = array('ssh-dss', 'ssh-rsa'), $protocol->getEncryptionAlgorithms(), $protocol->getEncryptionAlgorithms(), $protocol->getMacAlgorithms(), $protocol->getMacAlgorithms(), $protocol->getCompressionAlgorithms(), $protocol->getCompressionAlgorithms(), array(), array(), 0, 0); $protocol->send('r', $local->kexinit_packet); $remote->kexinit_packet = $remote_kexinit = $protocol->receive(); $remote_kexinit = substr($remote_kexinit, 17); list($remote_kex_algorithms, $remote_pk_algorithms, $encryption_algorithms_client_to_server, $encryption_algorithms_server_to_client, $mac_algorithms_client_to_server, $mac_algorithms_server_to_client, $compression_algorithms_client_to_server, $compression_algorithms_server_to_client, $languages_client_to_server, $languages_server_to_client, $first_kex_packet_follows, $reserved) = ssh\parse('nnnnnnnnnnbu', $remote_kexinit); $mistakes = 0; $mistakes += select_algorithm($kex_algorithm, $local_kex_algorithms, $remote_kex_algorithms, $local, $remote, 'kex'); $mistakes += select_algorithm($pk_algorithm, $local_pk_algorithms, $remote_pk_algorithms, $local, $remote, 'public key'); select_algorithm($decryption_algorithm, $protocol->getEncryptionAlgorithms(), ${'encryption_algorithms_' . $remote->type . '_to_' . $local->type}, $local, $remote, 'decryption'); select_algorithm($encryption_algorithm, $protocol->getEncryptionAlgorithms(), ${'encryption_algorithms_' . $local->type . '_to_' . $remote->type}, $local, $remote, 'encryption'); select_algorithm($receive_mac_algorithm, $protocol->getMacAlgorithms(), ${'mac_algorithms_' . $remote->type . '_to_' . $local->type}, $local, $remote, 'receive mac'); select_algorithm($send_mac_algorithm, $protocol->getMacAlgorithms(), ${'mac_algorithms_' . $local->type . '_to_' . $remote->type}, $local, $remote, 'send mac'); select_algorithm($uncompression_algorithm, $protocol->getCompressionAlgorithms(), ${'compression_algorithms_' . $remote->type . '_to_' . $local->type}, $local, $remote, 'uncompression'); select_algorithm($compression_algorithm, $protocol->getCompressionAlgorithms(), ${'compression_algorithms_' . $local->type . '_to_' . $remote->type}, $local, $remote, 'compression'); if ($mistakes > 0 && $first_kex_packet_follows) { for (;;) { $packet = $protocol->receive(); list($packet_type) = ssh\parse('b', $packet); if ($packet_type === ssh\SSH_MSG_DISCONNECT) { list($reason, $description) = ssh\parse('us'); throw new Disconnected($description, $reason); } if ($packet_type === ssh\SSH_MSG_KEXDH_INIT) { break; } } } switch ($kex_algorithm) { // http://tools.ietf.org/html/rfc2409#section-6.2 // http://tools.ietf.org/html/rfc2412#appendix-E.2 case 'diffie-hellman-group1-sha1': $pbin = pack('H*', 'FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74' . '020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F1437' . '4FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED' . 'EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381FFFFFFFFFFFFFFFF'); $random_length = 64; break; // http://tools.ietf.org/html/rfc3526#section-3 // http://tools.ietf.org/html/rfc3526#section-3 case 'diffie-hellman-group14-sha1': $pbin = pack('H*', 'FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74' . '020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F1437' . '4FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED' . 'EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF05' . '98DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB' . '9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B' . 'E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF695581718' . '3995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF'); $random_length = 128; break; } if (!extension_loaded('gmp') && !extension_loaded('bcmath')) { throw new ssh\Error('No extension for mpint calculations.'); } if (extension_loaded('gmp')) { $p = gmp_init(bin2hex($pbin), 16); } else { if (extension_loaded('bcmath')) { $p = bcdebin($pbin); } } if ($local->type === Side::SERVER) { $ybin = ssh\random($random_length); list($packet_type, $ebin) = ssh\parse('bm', $protocol->receive()); if ($packet_type !== ssh\SSH_MSG_KEXDH_INIT) { throw new ssh\Error('Expected SSH_MSG_KEXDH_INIT, got #' . $packet_type . '.'); } if (extension_loaded('gmp')) { $y = gmp_init(bin2hex($ybin), 16); $e = gmp_init(bin2hex($ebin), 16); $f = gmp_powm(2, $y, $p); $K = gmp_powm($e, $y, $p); $fbin = gmp_binval($f); $Kbin = gmp_binval($K); } else { if (extension_loaded('bcmath')) { $y = bcdebin($ybin); $e = bcdebin($ebin); $f = bcpowmod(2, $y, $p); $K = bcpowmod($e, $y, $p); $fbin = bcbin($f); $Kbin = bcbin($K); } } if (!isset($keys[$pk_algorithm])) { throw new ssh\Error('I do not have needed ' . $pk_algorithm . ' key.'); } $key = $keys[$pk_algorithm]; $H = sha1(ssh\format('sssssmmm', $remote->identification_string, $local->identification_string, $remote->kexinit_packet, $local->kexinit_packet, $key->public, $ebin, $fbin, $Kbin), TRUE); if ($protocol->getSessionId() === NULL) { $protocol->setSessionId($H); } $signature = ssh\sign($key->private, $H); $protocol->send('bsms', ssh\SSH_MSG_KEXDH_REPLY, $key->public, $fbin, $signature); } else { asset($local->type === Side::CLIENT); for (;;) { $xbin = ssh\random($random_length); if (extension_loaded('gmp')) { $x = gmp_init(bin2hex($xbin), 16); $cmp = gmp_cmp($x, 0); } else { if (extension_loaded('bcmath')) { $x = bcdebin($xbin); $cmp = bccomp($x, 0); } } if ($cmp > 0) { // if is x > 0 break; } } if (extension_loaded('gmp')) { $e = gmp_powm(2, $x, $p); $ebin = gmp_binval($e); } else { if (extension_loaded('bcmath')) { $e = bcpowmod(2, $x, $p); $ebin = bcbin($e); } } $protocol->send('bm', ssh\SSH_MSG_KEXDH_INIT, $e); list($packet_type) = ssh\parse('b', $packet = $protocol->receive()); if ($packet_type !== ssh\SSH_MSG_KEXDH_REPLY) { throw new ssh\Error('Expected SSH_MSG_KEXDH_REPLY, got #' . $packet_type . '.'); } list($server_key, $fbin, $signature) = ssh\parse('sms', $packet); if ($server_key !== $keys) { throw new ssh\Error('Server keys do not match.'); } if (extension_loaded('gmp')) { $f = gmp_init(bin2hex($fbin), 16); $K = gmp_powm($f, $x, $p); $Kbin = gmp_binval($K); } else { if (extension_loaded('bcmath')) { $f = bcdebin($fbin); $K = bcpowmod($f, $x, $p); $Kbin = bcbin($K); } } $H = sha1(ssh\format('sssssmmm', $local->identification_string, $remote->identification_string, $local->kexinit_packet, $remote->kexinit_packet, $server_key, $ebin, $fbin, $Kbin), TRUE); if (!ssh\verify($server_key, $H, $signature)) { throw new ssh\Error('Server reply cannot be verified.'); } if ($protocol->getSessionId() === NULL) { $protocol->setSessionId($H); } } $iv_client_to_server = sha1(ssh\format('mrbr', $Kbin, $H, ord('A'), $protocol->getSessionId()), TRUE); $iv_server_to_client = sha1(ssh\format('mrbr', $Kbin, $H, ord('B'), $protocol->getSessionId()), TRUE); $key_client_to_server = sha1(ssh\format('mrbr', $Kbin, $H, ord('C'), $protocol->getSessionId()), TRUE); $key_server_to_client = sha1(ssh\format('mrbr', $Kbin, $H, ord('D'), $protocol->getSessionId()), TRUE); $mac_key_client_to_server = sha1(ssh\format('mrbr', $Kbin, $H, ord('E'), $protocol->getSessionId()), TRUE); $mac_key_server_to_client = sha1(ssh\format('mrbr', $Kbin, $H, ord('F'), $protocol->getSessionId()), TRUE); lengthen(${'iv_' . $send}, $protocol->getEncryptionIVLength($encryption_algorithm), $Kbin, $H); lengthen(${'iv_' . $receive}, $protocol->getEncryptionIVLength($decryption_algorithm), $Kbin, $H); lengthen(${'key_' . $send}, $protocol->getEncryptionKeyLength($encryption_algorithm), $Kbin, $H); lengthen(${'key_' . $receive}, $protocol->getEncryptionKeyLength($decryption_algorithm), $Kbin, $H); lengthen(${'mac_key' . $send}, $protocol->getMacKeyLength($send_mac_algorithm), $Kbin, $H); lengthen(${'mac_key' . $receive}, $protocol->getMacKeyLength($receive_mac_algorithm), $Kbin, $H); if ($local->type === Side::SERVER) { list($packet_type) = ssh\parse('b', $protocol->receive()); if ($packet_type !== ssh\SSH_MSG_NEWKEYS) { throw new ssh\Error('Expected SSH_MSG_NEWKEYS, got #' . $packet_type . '.'); } $protocol->initDecryption($decryption_algorithm, ${'key_' . $receive}, ${'iv_' . $receive}); $protocol->initUncompression($uncompression_algorithm); $protocol->initReceiveMac($receive_mac_algorithm, ${'mac_key_' . $receive}); $protocol->send('b', ssh\SSH_MSG_NEWKEYS); $protocol->initEncryption($encryption_algorithm, ${'key_' . $send}, ${'iv_' . $send}); $protocol->initCompression($compression_algorithm); $protocol->initSendMac($send_mac_algorithm, ${'mac_key_' . $send}); } else { asset($local->type === Side::CLIENT); $protocol->send('b', ssh\SSH_MSG_NEWKEYS); $protocol->initEncryption($encryption_algorithm, ${'key_' . $send}, ${'iv_' . $send}); $protocol->initCompression($compression_algorithm); $protocol->initSendMac($send_mac_algorithm, ${'mac_key_' . $send}); list($packet_type) = ssh\parse('b', $protocol->receive()); if ($packet_type !== ssh\SSH_MSG_NEWKEYS) { throw new ssh\Error('Expected SSH_MSG_NEWKEYS, got #' . $packet_type . '.'); } $protocol->initDecryption($decryption_algorithm, ${'key_' . $receive}, ${'iv_' . $receive}); $protocol->initUncompression($uncompression_algorithm); $protocol->initReceiveMac($receive_mac_algorithm, ${'mac_key_' . $receive}); } }
/** * Performs modular exponentiation. * * Here's a quick 'n dirty example: * <code> * <?php * include('Math/BigInteger.php'); * * $a = new Math_BigInteger('10'); * $b = new Math_BigInteger('20'); * $c = new Math_BigInteger('30'); * * $c = $a->modPow($b, $c); * * echo $c->toString(); // outputs 10 * ?> * </code> * * @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 = $n->abs(); if ($e->compare(new Math_BigInteger()) < 0) { $e = $e->abs(); $temp = $this->modInverse($n); if ($temp === false) { return false; } return $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 $temp; case MATH_BIGINTEGER_MODE_BCMATH: // even though the last parameter is optional, according to php.net, it's not optional in // PHP_Compat 1.5.0 when running PHP 4. $temp = new Math_BigInteger(); $temp->value = bcpowmod($this->value, $e->value, $n->value, 0); return $temp; } if (empty($e->value)) { $temp = new Math_BigInteger(); $temp->value = array(1); return $temp; } if ($e->value == array(1)) { list(, $temp) = $this->divide($n); return $temp; } if ($e->value == array(2)) { $temp = $this->_square(); list(, $temp) = $temp->divide($n); return $temp; } // is the modulo odd? if ($n->value[0] & 1) { return $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 $result; }
public static function powmod($x, $y, $m) { switch (BigInt::support()) { case 'gmp': return gmp_powm($x, $y, $m); case 'big_int': return bi_powmod($x, $y, $m); case 'bcmath': return bcpowmod($x, $y, $m); case '': default: return BigInt::_powmod($x, $y, $m); } }
function generate_login_key($servkey, $username, $password) { $dhY = "0x9c32cc23d559ca90fc31be72df817d0e124769e809f936bc14360ff4bed758f260a0d596584eacbbc2b88bdd410416163e11dbf62173393fbc0c6fefb2d855f1a03dec8e9f105bbad91b3437d8eb73fe2f44159597aa4053cf788d2f9d7012fb8d7c4ce3876f7d6cd5d0c31754f4cd96166708641958de54a6def5657b9f2e92"; $dhN = "0xeca2e8c85d863dcdc26a429a71a9815ad052f6139669dd659f98ae159d313d13c6bf2838e10a69b6478b64a24bd054ba8248e8fa778703b418408249440b2c1edd28853e240d8a7e49540b76d120d3b1ad2878b1b99490eb4a2a5e84caa8a91cecbdb1aa7c816e8be343246f80c637abc653b893fd91686cf8d32d6cfe5f2a6f"; $dhG = "0x5"; $dhx = "0x" . $this->get_random_hex_key(256); if (extension_loaded("gmp")) { $dhN = gmp_init($dhN); $dhX = gmp_strval(gmp_powm($dhG, $dhx, $dhN), 16); $dhK = gmp_strval(gmp_powm($dhY, $dhx, $dhN), 16); } else { if (extension_loaded("bcmath")) { $dhX = $this->bcmath_powm($dhG, $dhx, $dhN); $dhK = $this->bcmath_powm($dhY, $dhx, $dhN); } else { $this->logger->log('error', "generate_login_key(): no idea how to powm..."); die; } } $str = sprintf("%s|%s|%s", $username, $servkey, $password); if (strlen($dhK) < 32) { $dhK = str_repeat("0", 32 - strlen($dhK)) . $dhK; } else { $dhK = substr($dhK, 0, 32); } $prefix = pack("H16", $this->get_random_hex_key(64)); $length = 8 + 4 + strlen($str); /* prefix, int, ... */ $pad = str_repeat(" ", (8 - $length % 8) % 8); $strlen = pack("N", strlen($str)); $plain = $prefix . $strlen . $str . $pad; $crypted = $this->aochat_crypt($dhK, $plain); return $dhX . "-" . $crypted; }
#echo "New dIC : $deviceID\n"; $changed = $dbHandle->exec("UPDATE {$dbTable} SET {$dbIDCol} = " . $dbHandle->quote($deviceID) . " WHERE {$dbEmailCol} = " . $email . " AND {$dbKeyCol} = " . $cdkey); #echo "Changed rows : $changed\n"; $cdKeyResponse = $cdKeyPositive; } else { $cdKeyResponse = $cdKeyNegative; } } } if (!file_exists($client_pub_file)) { exit("Decoder : client keys are missing!"); } $cpb = explode(" ", file_get_contents($client_pub_file)); $cp = gmp_init($cpb[0]); $cg = gmp_init($cpb[1]); $cy = gmp_init($cpb[2]); $cdKeyResponse = mb_convert_encoding($cdKeyResponse, "UTF-8"); $cdKeyCode = ""; for ($i = 0; $i < strlen($cdKeyResponse); $i++) { $charCode = unpack("N", mb_convert_encoding($cdKeyResponse[$i], "UCS-4BE", "UTF-8")); $cc = decbin(reset($charCode)); while (strlen($cc) < 8) { $cc = "0" . $cc; } $cdKeyCode = $cdKeyCode . $cc; } $cdKeyCode = gmp_init($cdKeyCode, 2); $cdKeyCodeK = gmp_add(gmp_random(31), "2"); $cdKeyCodeA = gmp_powm($cg, $cdKeyCodeK, $cp); $cdKeyCodeB = gmp_mod(gmp_mul(gmp_powm($cy, $cdKeyCodeK, $cp), $cdKeyCode), $cp); echo gmp_strval($cdKeyCodeA) . " " . gmp_strval($cdKeyCodeB);
/** * @param string $left_operand * @param string $right_operand * @return string */ public function powmod($left_operand, $right_operand, $modulus) { return gmp_strval(gmp_powm($left_operand, $right_operand, $modulus)); }
function srp_test() { $test_phase = 0; //$I = "alice"; //$P = "password123"; $I = "aliceasd"; $P = "passasd98173"; if ($test_phase == 0) { $_GET = array("protocol" => "SRP-6a", "type" => "request", "phase" => 0, "I" => $I, "P" => $P, "hash" => "SHA256", "N_size" => 1024, "enc_client_state" => ""); $json0 = json_encode(srp()); echo "Rep0=", $json0, "\n\n"; $json0 = json_decode($json0, true); } else { $_GET = array("protocol" => "SRP-6a", "type" => "request", "phase" => 1, "I" => $I, "hash" => "SHA256", "N_size" => 1024, "enc_server_state" => "", "enc_client_state" => ""); echo "Req1=", json_encode($_GET), "\n\n"; $json = json_encode(srp()); echo "Rep1=", $json, "\n\n"; $json = json_decode($json, true); if (strlen($json["N_base36"]) < 100) { crit("client: N to small"); } if (strlen($json["s_hex"]) < 32) { crit("client: s_hex to small"); } $Ng_ok = false; if ($json["g_base36"] == "2" && $json["N_base36"] == "16xa82om033wnlk70asiomztdukuffhyjzvfan3p2mx73a3d7m9hws9a6bzc2ln42n93rmtrxi2p22g3xgxrvyryv9petn2256pdt281msxh9e812rhddxq4oo1f35sp7leese5d02obbwmiui7r2ddwfyqu31ctl4959pckt6lbolnlblhf4znrola2vk3wfto3e8z") { $Ng_ok = true; } if ($Ng_ok != true) { crit("client: Ng not whitelisted"); } $N_gmp = gmp_init($json["N_base36"], 36); $N_bin = gmp_bytes($N_gmp); $g_gmp = gmp_init($json["g_base36"], 36); $g_bin = gmp_bytes($g_gmp); // check if N,g are secure: large, N is prime and g is primitive root, and discrate logarithm is hard // because chacking is hard to do in real-time, they should be whitelisted $k_hex = H($N_bin . pad($g_bin)); $k_gmp = gmp_init($k_hex, 16); $s_hex = $json["s_hex"]; $s_bin = hex2bin($s_hex); // client oblicza x = H(s~H(I~P)) $x_bin = H($s_bin . H($I . ":" . $P)); $x_hex = bin2hex($x_bin); $x_gmp = gmp_init($x_hex, 16); // secret $v_gmp = gmp_powm($g_gmp, $x_gmp, $N_gmp); // secret // timing attack // client generuje randomowe a $a_bin = get_random_bytes(128); // rfc 5054: at least 256 bit $a_hex = bin2hex($a_bin); $a_gmp = gmp_init($a_hex, 16); // secret // client oblicza A=g^a, i nam wysyla $A_gmp = gmp_powm($g_gmp, $a_gmp, $N_gmp); // public // timing attack $A_hex = gmp_strval($A_gmp, 16); // debug $A_bin = gmp_bytes($A_gmp); // ponieważ dostalismy B, możemy obliczyc juz S $B_gmp = gmp_init($json["B_base36"], 36); $B_hex = gmp_strval($B_gmp, 16); // debug $B_bin = gmp_bytes($B_gmp); // klient oblicza u = H(A~B) $u_bin = H(pad($A_bin) . pad($B_bin)); $u_hex = bin2hex($u_bin); $u_gmp = gmp_init($u_hex, 16); // klient oblicza S = (B - k*g^x)^(a+u*x) //$S_gmp = gmp_powm(gmp_sub($B_gmp, gmp_mul($k_gmp, gmp_powm($g_gmp, $v_gmp, $N_gmp))), gmp_add($a_gmp, gmp_mul($u_gmp, $x_gmp)), $N_gmp); $S_gmp = gmp_powm(gmp_mod(gmp_sub($B_gmp, gmp_mod(gmp_mul($k_gmp, $v_gmp), $N_gmp)), $N_gmp), gmp_add($a_gmp, gmp_mul($u_gmp, $x_gmp)), $N_gmp); // timing attack $S_bin = gmp_bytes($S_gmp); $S_hex = gmp_strval($S_gmp, 16); // secret // klient oblicza M1 = H(A~B~S) i wysyla do serwera $M1_bin = H($A_bin . $B_bin . $S_bin); $M1_hex = bin2hex($M1_bin); $_GET = array("protocol" => "SRP-6a", "type" => "request", "phase" => 2, "A_base36" => gmp_strval($A_gmp, 36), "M1_hex" => $M1_hex, "enc_server_state" => $json["enc_server_state"], "enc_client_state" => ""); echo "Req2=", json_encode($_GET), "\n\n"; $json2 = json_encode(srp()); echo "Rep2=", $json2, "\n\n"; $json2 = json_decode($json2, true); // klient oblicza M2 = H(A~M1~S) // klient potwierdza poprawnosc otrzymanego M2 // klient oblicza K = H(S) // klient oblicza M = H( (H(N) xor H(g))~H(I)~s~A~B~K ) $M2_bin = H($A_bin . $M1_bin . $S_bin); $M2_hex = bin2hex($M2_bin); if ($M2_hex != $json2["M2_hex"]) { crit("client: M2 are different, don't trust server!"); } $K_bin = H($S_bin); $K_hex = bin2hex($K_bin); // secret $M_bin = HM((H($N_bin) ^ H($g_bin)) . H($I) . $s_bin . $A_bin . $B_bin, $K_bin); $M_hex = bin2hex($M_bin); $_GET = array("protocol" => "SRP-6a", "type" => "request", "phase" => 3, "M_hex" => $M_hex, "enc_server_state" => $json2["enc_server_state"], "enc_client_state" => ""); echo "Req3=", json_encode($_GET), "\n\n"; $json3 = json_encode(srp()); echo "Rep3=", $json3, "\n\n"; $json3 = json_decode($json3, true); $Z_bin = HM($A_bin . $M_bin, $K_bin); $Z_hex = bin2hex($Z_bin); if ($Z_hex != $json3["Z_hex"]) { crit("Z_hex different"); } echo "Logged\n"; } }
private function DoPublic($x) { if ($this->canEncrypt) { return gmp_powm($x, $this->e, $this->n); } return 0; }
public static function gmp_squareRootModP($prime, $verbose = false) { $start_time = microtime(true); if ($verbose) { echo "Testing primes for modulus " . $prime . "<br />"; } $squares = array(); for ($root = 0; gmp_cmp($root, gmp_add(1, gmp_div($prime, 2))) < 0; $root = gmp_add($root, 1)) { $sq = gmp_strval(gmp_powm($root, 2, $prime)); $calculated = NumberTheory::square_root_mod_prime($sq, $prime); $calc_sq = gmp_strval(gmp_powm($calculated, 2, $prime)); if (gmp_cmp($calculated, $root) != 0 && gmp_cmp(gmp_sub($prime, $calculated), $root) != 0) { $error_tally++; echo "FAILED TO FIND " . gmp_strval($root) . " AS sqrt(" . gmp_strval($sq) . ") mod {$prime} . Said {$calculated} (" . ($prime - $calculated) . ") <br />\n"; flush(); } else { if ($verbose) { echo "SUCCESS TO FIND " . gmp_strval($root) . " AS sqrt(" . gmp_strval($sq) . ") mod {$prime} . Said {$calculated} (" . ($prime - $calculated) . ") <br />\n"; } flush(); } } $end_time = microtime(true); $time_res = $end_time - $start_time; echo "<br />Square roots mod " . $prime . " took: " . $time_res . " seconds. <br />"; }
function bigint_powmod($x, $y, $m) { return gmp_powm($x, $y, $m); }
/** * Performs modular exponentiation. * * Here's an example: * <code> * <?php * include('Math/BigInteger.php'); * * $a = new BigInteger('10'); * $b = new BigInteger('20'); * $c = new BigInteger('30'); * * $c = $a->modPow($b, $c); * * echo $c->toString(); // outputs 10 * ?> * </code> * * @param BigInteger $e * @param BigInteger $n * @return 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 BigInteger()) < 0) { $e = $e->abs(); $temp = $this->modInverse($n); if ($temp === false) { return false; } return $this->_normalize($temp->modPow($e, $n)); } switch (BigInteger_MODE) { case BigInteger_MODE_GMP: $temp = new BigInteger(); $temp->value = gmp_powm($this->value, $e->value, $n->value); return $this->_normalize($temp); case BigInteger_MODE_BCMATH: $temp = new BigInteger(); $temp->value = bcpowmod($this->value, $e->value, $n->value, 0); return $this->_normalize($temp); } if (empty($e->value)) { $temp = new 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 BigInteger(); $temp->value = $this->_square($this->value); list(, $temp) = $temp->divide($n); return $this->_normalize($temp); } return $this->_normalize($this->_slidingWindow($e, $n, BigInteger_BARRETT)); // is the modulo odd? if ($n->value[0] & 1) { return $this->_normalize($this->_slidingWindow($e, $n, 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 BigInteger(); $mod2->value = array(1); $mod2->_lshift($j); $part1 = $mod1->value != array(1) ? $this->_slidingWindow($e, $mod1, BigInteger_MONTGOMERY) : new BigInteger(); $part2 = $this->_slidingWindow($e, $mod2, 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); }
function powm($base, $exponent, $modulus) { if (function_exists('gmp_powm')) { return gmp_strval(gmp_powm($base, $exponent, $modulus)); } else { if (function_exists('bi_powmod')) { return bi_sto_str(bi_powmod($base, $exponent, $modulus)); } else { if (function_exists('bcpowmod')) { return bcpowmod($base, $exponent, $modulus); } else { if (preg_match("/^\\d+,\\d+,\\d+\$/", "{$base},{$exponent},{$modulus}")) { //@FIX: this is insecure - a bi-directional proc_open() is required if (is_executable("/usr/bin/python")) { $r = trim(`python -c "print pow({$base}, {$exponent}, {$modulus})"`); } else { $r = trim(`perl -e "use Math::BigInt; print Math::BigInt->new('{$base}')->bmodpow('{$exponent}', '{$modulus}')->bstr();"`); } if (preg_match("/^\\d+\$/", $r)) { return $r; } } } } } trigger_error("powmod: unsupported or non-integer argument", E_USER_ERROR); }
/** * Generates the secret key using the private key and prime * * @param string Public key passed in by the request * * @return string String containing the shared secret */ function fetch_shared_secret($foreignpubkey) { $this->secret = gmp_powm($foreignpubkey, $this->privatekey, $this->prime); return gmp_strval($this->secret); }
/** * Raise to a power and reduce by a modulus * * @param mixed $power * @param mixed $modulus * @access public * @return self */ public function powMod($power, $modulus) { $result = gmp_powm($this->getRawValue(), static::upgradeParam($power)->getRawValue(), static::upgradeParam($modulus)->getRawValue()); return static::factory($result); }
function powmod($base, $exponent, $modulus) { return gmp_powm($base, $exponent, $modulus); }
public function PowMod($left, $right, $modulus) { return $this->string(gmp_powm($left, $right, $modulus)); }
/** * Calculates pow($num, $pow) (mod $mod) * * @param gmp resource $num * @param gmp resource $pow * @param gmp resource $mod * @return gmp resource * @access public */ function powmod($num, $pow, $mod) { return gmp_powm($num, $pow, $mod); }
public function validatePoint($x, $y) { $a = $this->a; $b = $this->b; $p = $this->p; $x = gmp_init($x, 16); $y2 = gmp_mod(gmp_add(gmp_add(gmp_powm($x, gmp_init(3, 10), $p), gmp_mul($a, $x)), $b), $p); $y = gmp_mod(gmp_pow(gmp_init($y, 16), 2), $p); if (gmp_cmp($y2, $y) == 0) { return true; } else { return false; } }
/** * Performs modular exponentiation. * * Here's an example: * <code> * <?php * include 'Math/BigInteger.php'; * * $a = new Math_BigInteger('10'); * $b = new Math_BigInteger('20'); * $c = new Math_BigInteger('30'); * * $c = $a->modPow($b, $c); * * echo $c->toString(); // outputs 10 * ?> * </code> * * @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)); } if (MATH_BIGINTEGER_MODE == MATH_BIGINTEGER_MODE_GMP) { $temp = new Math_BigInteger(); $temp->value = gmp_powm($this->value, $e->value, $n->value); return $this->_normalize($temp); } if ($this->compare(new Math_BigInteger()) < 0 || $this->compare($n) > 0) { list(, $temp) = $this->divide($n); return $temp->modPow($e, $n); } if (defined('MATH_BIGINTEGER_OPENSSL_ENABLED')) { $components = array('modulus' => $n->toBytes(true), 'publicExponent' => $e->toBytes(true)); $components = array('modulus' => pack('Ca*a*', 2, $this->_encodeASN1Length(strlen($components['modulus'])), $components['modulus']), 'publicExponent' => pack('Ca*a*', 2, $this->_encodeASN1Length(strlen($components['publicExponent'])), $components['publicExponent'])); $RSAPublicKey = pack('Ca*a*a*', 48, $this->_encodeASN1Length(strlen($components['modulus']) + strlen($components['publicExponent'])), $components['modulus'], $components['publicExponent']); $rsaOID = pack('H*', '300d06092a864886f70d0101010500'); // hex version of MA0GCSqGSIb3DQEBAQUA $RSAPublicKey = chr(0) . $RSAPublicKey; $RSAPublicKey = chr(3) . $this->_encodeASN1Length(strlen($RSAPublicKey)) . $RSAPublicKey; $encapsulated = pack('Ca*a*', 48, $this->_encodeASN1Length(strlen($rsaOID . $RSAPublicKey)), $rsaOID . $RSAPublicKey); $RSAPublicKey = "-----BEGIN PUBLIC KEY-----\r\n" . chunk_split(base64_encode($encapsulated)) . '-----END PUBLIC KEY-----'; $plaintext = str_pad($this->toBytes(), strlen($n->toBytes(true)) - 1, "", STR_PAD_LEFT); if (openssl_public_encrypt($plaintext, $result, $RSAPublicKey, OPENSSL_NO_PADDING)) { return new Math_BigInteger($result, 256); } } if (MATH_BIGINTEGER_MODE == 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)); // the following code, although not callable, can be run independently of the above code // although the above code performed better in my benchmarks the following could might // perform better under different circumstances. in lieu of deleting it it's just been // made uncallable // 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); }
function bcpowmod($x, $y, $mod) { return gmp_strval(gmp_powm($x, $y, $mod)); }
/** * Computes the shared secret from the private DH value $dh and the other * party's public value in $pub_key * * @param string $pub_key other party's public value * @param mixed $dh Diffie-Hellman key * @return string * @throws Zend\OpenId\Exception */ public static function computeDhSecret($pub_key, $dh) { if (function_exists('openssl_dh_compute_key')) { $ret = openssl_dh_compute_key($pub_key, $dh); if (ord($ret[0]) > 127) { $ret = "" . $ret; } return $ret; } else { if (extension_loaded('gmp')) { $bn_pub_key = self::binToBigNum($pub_key); $bn_secret = gmp_powm($bn_pub_key, $dh['priv_key'], $dh['p']); return self::bigNumToBin($bn_secret); } else { if (extension_loaded('bcmath')) { $bn_pub_key = self::binToBigNum($pub_key); $bn_secret = bcpowmod($bn_pub_key, $dh['priv_key'], $dh['p']); return self::bigNumToBin($bn_secret); } } } throw new Exception('The system doesn\'t have proper big integer extension', Exception::UNSUPPORTED_LONG_MATH); }
$pop1 = gmp_init("10000101", 2); // 3 1's echo gmp_popcount($pop1) . "\n"; $pop2 = gmp_init("11111110", 2); // 7 1's echo gmp_popcount($pop2) . "\n"; // gmp_pow $pow1 = gmp_pow("2", 31); echo gmp_strval($pow1) . "\n"; $pow2 = gmp_pow("0", 0); echo gmp_strval($pow2) . "\n"; $pow3 = gmp_pow("2", -1); // Negative exp, generates warning echo gmp_strval($pow3) . "\n"; // gmp_powm $pow1 = gmp_powm("2", "31", "2147483649"); echo gmp_strval($pow1) . "\n"; // gmp_prob_prime echo gmp_prob_prime("6") . "\n"; // definitely not a prime echo gmp_prob_prime("1111111111111111111") . "\n"; // probably a prime echo gmp_prob_prime("11") . "\n"; // definitely a prime // gmp_random -- not implemented // gmp_scan0 // "0" bit is found at position 3. index starts at 0 $s1 = gmp_init("10111", 2); echo gmp_scan0($s1, 0) . "\n"; // "0" bit is found at position 7. index starts at 5 $s2 = gmp_init("101110000", 2);