/** * Crypt_RSA constructor. * * @param array $params * Optional associative array of parameters, such as: * enc_key, dec_key, private_key, public_key, hash_func. * See setParams() method for more detailed description of * these parameters. * * @param string $wrapper_name * Name of math wrapper, which will be used to * perform different operations with big integers. * See contents of Crypt/RSA/Math folder for examples of wrappers. * Read docs/Crypt_RSA/docs/math_wrappers.txt for details. * * @param string $error_handler name of error handler function * * @access public */ function Crypt_RSA($params = null, $wrapper_name = 'default', $error_handler = '') { // set error handler $this->setErrorHandler($error_handler); // try to load math wrapper $obj =& Crypt_RSA_MathLoader::loadWrapper($wrapper_name); if (PEAR::isError($obj)) { // error during loading of math wrapper // Crypt_RSA object is partially constructed. $this->pushError($obj); return; } $this->_math_obj =& $obj; if (!is_null($params)) { if (!$this->setParams($params)) { // error in Crypt_RSA::setParams() function return; } } }
public static function getPublicRSAKey() { $errorSettings = error_reporting(0); $pemString = file_get_contents('key.pem'); $keyPair = Crypt_RSA_KeyPair::fromPEMString($pemString); $math_obj =& Crypt_RSA_MathLoader::loadWrapper('default'); $publicKey = $keyPair->getPublicKey(); $keyArray = array('exponent' => $math_obj->bin2int($publicKey->getExponent()), 'modulus' => $math_obj->bin2int($publicKey->getModulus())); if ($math_obj->getWrapperName() == 'GMP') { $keyArray = array_map('gmp_strval', $keyArray); } error_reporting($errorSettings); return $keyArray; }
/** * Crypt_RSA_KeyPair constructor. * * Wrapper: name of math wrapper, which will be used to * perform different operations with big integers. * See contents of Crypt/RSA/Math folder for examples of wrappers. * Read docs/Crypt_RSA/docs/math_wrappers.txt for details. * * @param int $key_len bit length of key pair, which will be generated in constructor * @param string $wrapper_name wrapper name * @param string $error_handler name of error handler function * @param callback $random_generator function which will be used as random generator * * @access public */ function Crypt_RSA_KeyPair($key_len, $wrapper_name = 'default', $error_handler = '', $random_generator = null) { // set error handler $this->setErrorHandler($error_handler); // try to load math wrapper $obj =& Crypt_RSA_MathLoader::loadWrapper($wrapper_name); if ($this->isError($obj)) { // error during loading of math wrapper $this->pushError($obj); return; } $this->_math_obj =& $obj; // set random generator if (!$this->setRandomGenerator($random_generator)) { // error in setRandomGenerator() function return; } if (is_array($key_len)) { // ugly BC hack - it is possible to pass RSA private key attributes [version, n, e, d, p, q, dmp1, dmq1, iqmp] // as associative array instead of key length to Crypt_RSA_KeyPair constructor $rsa_attrs = $key_len; // convert attributes to big integers $attr_names = $this->_get_attr_names(); foreach ($attr_names as $attr) { if (!isset($rsa_attrs[$attr])) { $this->pushError("missing required RSA attribute [{$attr}]"); return; } ${$attr} = $this->_math_obj->bin2int($rsa_attrs[$attr]); } // check primality of p and q if (!$this->_math_obj->isPrime($p)) { $this->pushError("[p] must be prime"); return; } if (!$this->_math_obj->isPrime($q)) { $this->pushError("[q] must be prime"); return; } // check n = p * q $n1 = $this->_math_obj->mul($p, $q); if ($this->_math_obj->cmpAbs($n, $n1)) { $this->pushError("n != p * q"); return; } // check e * d = 1 mod (p-1) * (q-1) $p1 = $this->_math_obj->dec($p); $q1 = $this->_math_obj->dec($q); $p1q1 = $this->_math_obj->mul($p1, $q1); $ed = $this->_math_obj->mul($e, $d); $one = $this->_math_obj->mod($ed, $p1q1); if (!$this->_math_obj->isOne($one)) { $this->pushError("e * d != 1 mod (p-1)*(q-1)"); return; } // check dmp1 = d mod (p-1) $dmp = $this->_math_obj->mod($d, $p1); if ($this->_math_obj->cmpAbs($dmp, $dmp1)) { $this->pushError("dmp1 != d mod (p-1)"); return; } // check dmq1 = d mod (q-1) $dmq = $this->_math_obj->mod($d, $q1); if ($this->_math_obj->cmpAbs($dmq, $dmq1)) { $this->pushError("dmq1 != d mod (q-1)"); return; } // check iqmp = 1/q mod p $q1 = $this->_math_obj->invmod($iqmp, $p); if ($this->_math_obj->cmpAbs($q, $q1)) { $this->pushError("iqmp != 1/q mod p"); return; } // try to create public key object $public_key =& new Crypt_RSA_Key($rsa_attrs['n'], $rsa_attrs['e'], 'public', $wrapper_name, $error_handler); if ($public_key->isError()) { // error during creating public object $this->pushError($public_key->getLastError()); return; } // try to create private key object $private_key =& new Crypt_RSA_Key($rsa_attrs['n'], $rsa_attrs['d'], 'private', $wrapper_name, $error_handler); if ($private_key->isError()) { // error during creating private key object $this->pushError($private_key->getLastError()); return; } $this->_public_key = $public_key; $this->_private_key = $private_key; $this->_key_len = $public_key->getKeyLength(); $this->_attrs = $rsa_attrs; } else { // generate key pair if (!$this->generate($key_len)) { // error during generating key pair return; } } }
/** * Crypt_RSA_Key constructor. * * @param string $modulus key modulus * @param string $exp key exponent * @param string $key_type type of the key (public or private) * * @param string $wrapper_name * Name of math wrapper, which will be used to * perform different operations with big integers. * See contents of Crypt/RSA/Math folder for examples of wrappers. * Read docs/Crypt_RSA/docs/math_wrappers.txt for details. * * @param string $error_handler name of error handler function * * @access public */ function Crypt_RSA_Key($modulus, $exp, $key_type, $wrapper_name = 'default', $error_handler = '') { // set error handler $this->setErrorHandler($error_handler); // try to load math wrapper $wrapper_name $obj =& Crypt_RSA_MathLoader::loadWrapper($wrapper_name); if (PEAR::isError($obj)) { // error during loading of math wrapper $this->pushError($obj); // push error object into error list return; } $this->_math_obj =& $obj; $this->_modulus = $modulus; $this->_exp = $exp; if (!in_array($key_type, array('private', 'public'))) { $obj = PEAR::raiseError('invalid key type. It must be private or public', CRYPT_RSA_ERROR_WRONG_KEY_TYPE); $this->pushError($obj); // push error object into error list return; } $this->_key_type = $key_type; /* check length of modulus & exponent ( abs(modulus) > abs(exp) ) */ $mod_num = $this->_math_obj->bin2int($this->_modulus); $exp_num = $this->_math_obj->bin2int($this->_exp); if ($this->_math_obj->cmpAbs($mod_num, $exp_num) <= 0) { $obj = PEAR::raiseError('modulus must be greater than exponent', CRYPT_RSA_ERROR_EXP_GE_MOD); $this->pushError($obj); // push error object into error list return; } // determine key length $this->_key_len = $this->_math_obj->bitLen($mod_num); }
/** * Loads RSA math wrapper with name $wrapper_name. * Implemented wrappers can be found at Crypt/RSA/Math folder. * Read docs/Crypt_RSA/docs/math_wrappers.txt for details * * This is a static function: * // load BigInt wrapper * $big_int_wrapper = &Crypt_RSA_MathLoader::loadWrapper('BigInt'); * * // load BCMath wrapper * $bcmath_wrapper = &Crypt_RSA_MathLoader::loadWrapper('BCMath'); * * @param string $wrapper_name * @return object * Reference to object of wrapper with name $wrapper_name on success * or PEAR_Error object on error * * @access public */ function &loadWrapper($wrapper_name = 'default') { static $math_objects = array(); // ordered by performance. GMP is the fastest math library, BCMath - the slowest. static $math_wrappers = array('GMP', 'BigInt', 'BCMath', 'Math_BigInteger'); if (isset($math_objects[$wrapper_name])) { /* wrapper with name $wrapper_name is already loaded and created. Return reference to existing copy of wrapper */ return $math_objects[$wrapper_name]; } if ($wrapper_name === 'default') { // try to load the most suitable wrapper $n = sizeof($math_wrappers); for ($i = 0; $i < $n; $i++) { $obj =& Crypt_RSA_MathLoader::loadWrapper($math_wrappers[$i]); if (!PEAR::isError($obj)) { // wrapper for $math_wrappers[$i] successfully loaded // register it as default wrapper and return reference to it return $math_objects['default'] =& $obj; } } // can't load any wrapper return PEAR::raiseError("can't load any wrapper for existing math libraries", CRYPT_RSA_ERROR_NO_WRAPPERS); } $class_name = 'Crypt_RSA_Math_' . $wrapper_name; $class_filename = dirname(__FILE__) . '/Math/' . $wrapper_name . '.php'; if (!is_file($class_filename)) { return PEAR::raiseError("can't find file [{$class_filename}] for RSA math wrapper [{$wrapper_name}]", CRYPT_RSA_ERROR_NO_FILE); } require_once $class_filename; if (!class_exists($class_name)) { return PEAR::raiseError("can't find class [{$class_name}] in file [{$class_filename}]", CRYPT_RSA_ERROR_NO_CLASS); } // create and return wrapper object on success or PEAR_Error object on error $obj = new $class_name(); if ($obj->errstr) { // cannot load required extension for math wrapper $obj = PEAR::raiseError($obj->errstr, CRYPT_RSA_ERROR_NO_EXT); } return $math_objects[$wrapper_name] =& $obj; }
/** * Crypt_RSA_KeyPair constructor. * * @param int $key_len bit length of key pair, which will be generated in constructor * @param string $wrapper_name * Name of math wrapper, which will be used to * perform different operations with big integers. * See contents of Crypt/RSA/Math folder for examples of wrappers. * Read docs/Crypt_RSA/docs/math_wrappers.txt for details. * * @param string $error_handler name of error handler function * * @access public */ function Crypt_RSA_KeyPair($key_len, $wrapper_name = 'default', $error_handler = '') { // set error handler $this->setErrorHandler($error_handler); // try to load math wrapper $obj =& Crypt_RSA_MathLoader::loadWrapper($wrapper_name); if (PEAR::isError($obj)) { // error during loading of math wrapper $this->pushError($obj); return; } $this->_math_obj =& $obj; // set default random generator if (!$this->setRandomGenerator()) { // error in setRandomGenerator() function return; } // generate key pair if (!$this->generate($key_len)) { // error during generating key pair return; } }