private_key, $this->public_key) = $this->generateNewKeypair($numbits); list($this->public_exponent, $this->modulus) = $this->getModulusAndPublicExponentFromPublicKey($this->public_key); } // new function that parses through the public key and returns the modulus and public exponent // doesn't work with every irregular RSA key size, but should work 100% of the time for this plugin function getModulusAndPublicExponentFromPublicKey($pubkey) { $e = 0; $n = ''; if (preg_match('/^-----BEGIN PUBLIC KEY-----([^-]+)-----END PUBLIC KEY-----$/s', $pubkey, $matches)) { $key = str_replace("\n", "", $matches[1]); $key = str_replace("\r", "", $key); $key = bin2hex(base64_decode($key)); list($bytes, $key) = $this->readBytes($key, 2); if ($bytes == '3081') { list($bytes, $key) = $this->readBytes($key, 1); } else if ($bytes == '3082') { list($bytes, $key) = $this->readBytes($key, 2); } else { // when dealing with some smaller values, we run into this 'else' situation if (substr($bytes, 0, 2) == '30') { // nothing to do } else { return array($e, trim($n)); } } list($bytes, $key) = $this->readBytes($key, 15); if (strtolower($bytes) != '300d06092a864886f70d0101010500') { return array($e, trim($n)); } list($bytes, $key) = $this->readBytes($key, 2); if ($bytes == '0381') { list($bytes, $key) = $this->readBytes($key, 1); } else if ($bytes == '0382') { list($bytes, $key) = $this->readBytes($key, 2); } else { // when dealing with some smaller values, we run into this 'else' situation if (substr($bytes, 0, 2) == '03') { // nothing to do } else { return array($e, trim($n)); } } list($bytes, $key) = $this->readBytes($key, 1); if ($bytes != '00') { return array($e, trim($n)); } list($bytes, $key) = $this->readBytes($key, 2); if ($bytes == '3081') { list($bytes, $key) = $this->readBytes($key, 1); } else if ($bytes == '3082') { list($bytes, $key) = $this->readBytes($key, 2); } else { // when dealing with some smaller values, we run into this 'else' situation if (substr($bytes, 0, 2) == '30') { // nothing to do } else { return array($e, trim($n)); } } list($bytes, $key) = $this->readBytes($key, 2); if ($bytes == '0281') { list($bytes, $key) = $this->readBytes($key, 1); $modulusLength = hexdec($bytes); } else if ($bytes == '0282') { list($bytes, $key) = $this->readBytes($key, 2); $modulusLength = hexdec($bytes); } else { // when dealing with some smaller values, we run into this 'else' situation if (substr($bytes, 0, 2) == '02') { $modulusLength = hexdec(substr($bytes, 2)); } else { return array($e, trim($n)); } } list($bytes, $key) = $this->readBytes($key, 1, true); if ($bytes == '00') { $modulusLength -= 1; list($bytes, $key) = $this->readBytes($key, 1); } list($bytes, $key) = $this->readBytes($key, $modulusLength); $n = ltrim($bytes, '0'); list($bytes, $key) = $this->readBytes($key, 1); if ($bytes != '02') { return array($e, trim($n)); } list($bytes, $key) = $this->readBytes($key, 1); $exponentLength = hexdec($bytes); list($bytes, $key) = $this->readBytes($key, $exponentLength); $e = (int)$bytes; //ltrim($bytes, '0'); //hexdec($bytes); } return array($e, trim($n)); } // reads the number of bytes (every 2 characters) from the string // returns the byte string and the rest of the passed in string // also lets you peak at the bytes without modifying the returned string function readBytes($string, $num = 1, $peak = false) { $num *= 2; $bytes = substr($string, 0, $num); if ($peak) { $newString = $string; } else { $newString = substr($string, $num); } return array($bytes, $newString); } /* // this function doesn't fully parse out the values, it cheats // we only check for a public exponent of F4 or 3 // PHP seems to only generate keypairs with F4 as the public exponent function getModulusAndPublicExponentFromPublicKey_OldVersion($pubkey, $numbits) { $e = 0; $n = ''; if (preg_match('/^-----BEGIN PUBLIC KEY-----([^-]+)-----END PUBLIC KEY-----$/s', $pubkey, $matches)) { $key = str_replace("\n", "", $matches[1]); $key = str_replace("\r", "", $key); $key = bin2hex(base64_decode($key)); $length = ceil($numbits / 8 * 2); if (substr($key, -10) == '0203010001') { $e = 10001; // F4 $start = ($length + 10) * (-1); $n = substr($key, $start, $length); } else if(substr($key, -6) == '020103') { $e = 3; $start = ($length + 6) * (-1); $n = substr($key, $start, $length); } } return array($e, trim($n)); } // while the above function keys off of the public-exponent (either F4 or 3) // this function keys off of the number of bits (512, 1024, 2048, or 3072) // this function also cheats to grab the modulus and public exponent function getModulusAndPublicExponentFromPublicKeyRedux_OldVersion($pubkey, $numbits) { $e = 0; $n = ''; if (preg_match('/^-----BEGIN PUBLIC KEY-----([^-]+)-----END PUBLIC KEY-----$/s', $pubkey, $matches)) { $key = str_replace("\n", "", $matches[1]); $key = str_replace("\r", "", $key); $key = bin2hex(base64_decode($key)); $length = ceil($numbits / 8 * 2); if ($numbits == 512) { $n = substr($key, 50, $length); $e = substr($key, 50 + $length + 4); //$e = ltrim($e, "0"); $e = (int)$e; } else if ($numbits == 1024) { $n = substr($key, 58, $length); $e = substr($key, 58 + $length + 4); //$e = ltrim($e, "0"); $e = (int)$e; } else if ($numbits == 2048) { $n = substr($key, 66, $length); $e = substr($key, 66 + $length + 4); //$e = ltrim($e, "0"); $e = (int)$e; } else if ($numbits == 3072) { $n = substr($key, 66, $length); $e = substr($key, 66 + $length + 4); //$e = ltrim($e, "0"); $e = (int)$e; } } return array($e, trim($n)); } */ // generate new public/private PEM keys via built-in PHP functions function generateNewKeypair($numbits = 1024) { $numbits = (int)$numbits; switch($numbits) { case 512: case 1024: case 2048: case 3072: $nbits = $numbits; break; default: $nbits = 1024; break; } $this->num_bits = $nbits; $configargs = array( "private_key_bits" => $nbits, "private_key_type" => OPENSSL_KEYTYPE_RSA ); $res = @openssl_pkey_new($configargs); if (is_resource($res)) { @openssl_pkey_export($res, $priv_key); if (version_compare(PHP_VERSION, '5.2.0', '>=') && function_exists('openssl_pkey_get_details')) { $pub_key_array = @openssl_pkey_get_details($res); $pub_key = $pub_key_array['key']; //$this->num_bits = $pub_key_array['bits']; } @openssl_pkey_free($res); return array( trim($priv_key), trim($pub_key) ); } return array('', ''); } } } ?>