protected function initAes($key, $iv, $keySize) { $this->aes = new \Crypt_AES(); $this->aes->setKeyLength($keySize); $this->aesKey = $key; $this->aesIV = $iv; $this->aes->setKey($this->aesKey); $this->aes->setIV($this->aesIV); }
public static function decrypt($secret, $password, ApiKeyEncryptionOptions $options) { $decodedSecret = self::base64url_decode($secret); $salt = self::base64url_decode($options->getEncryptionKeySalt()); $iterations = $options->getEncryptionKeyIterations(); $keyLengthBits = $options->getEncryptionKeySize(); $iv = substr($decodedSecret, 0, 16); $aes = new \Crypt_AES(); $aes->setPassword($password, 'pbkdf2', 'sha1', $salt, $iterations, $keyLengthBits / 8); $aes->setKeyLength($keyLengthBits); $aes->setIV($iv); return $aes->decrypt(substr($decodedSecret, 16)); }
/** * Checks whether a user has the right to enter on the platform or not * @param string The username, as provided in form * @param string The cleartext password, as provided in form * @param string The WS URL, as provided at the beginning of this script */ function loginWSAuthenticate($username, $password, $wsUrl) { // check params if (empty($username) or empty($password) or empty($wsUrl)) { return false; } // Create new SOAP client instance $client = new SoapClient($wsUrl); if (!$client) { return false; } // Include phpseclib methods, because of a bug with AES/CFB in mcrypt include_once api_get_path(LIBRARY_PATH) . 'phpseclib/Crypt/AES.php'; // Define all elements necessary to the encryption $key = '-+*%$({[]})$%*+-'; // Complete password con PKCS7-specific padding $blockSize = 16; $padding = $blockSize - strlen($password) % $blockSize; $password .= str_repeat(chr($padding), $padding); $cipher = new Crypt_AES(CRYPT_AES_MODE_CFB); $cipher->setKeyLength(128); $cipher->setKey($key); $cipher->setIV($key); $cipheredPass = $cipher->encrypt($password); // Mcrypt call left for documentation purposes - broken, see https://bugs.php.net/bug.php?id=51146 //$cipheredPass = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $password, MCRYPT_MODE_CFB, $key); // Following lines present for debug purposes only /* $arr = preg_split('//', $cipheredPass, -1, PREG_SPLIT_NO_EMPTY); foreach ($arr as $char) { error_log(ord($char)); } */ // Change to base64 to avoid communication alteration $passCrypted = base64_encode($cipheredPass); // The call to the webservice will change depending on your definition try { $response = $client->validateUser(array('user' => $username, 'pass' => $passCrypted, 'system' => 'chamilo')); } catch (SoapFault $fault) { error_log('Caught something'); if ($fault->faultstring != 'Could not connect to host') { error_log('Not a connection problem'); throw $fault; } else { error_log('Could not connect to WS host'); } return 0; } return $response->validateUserResult; }
/** * Initializes AES instance using either provided $options or session values * @param array $options Array of options, containing 'key' and 'iv' values * @return mixed|void * @throws Exception */ public function initSymmetric($options = array()) { if (empty($options) && Session::has('aes_key') && Session::has('aes_iv')) { $options = array('key' => Session::get('aes_key'), 'iv' => Session::get('aes_iv')); } if (!(isset($options['key']) && isset($options['iv']))) { \Log::error("Either key or iv not set"); throw new \Exception("Either key or iv not set"); } Session::put('aes_key', $options['key']); Session::put('aes_iv', $options['iv']); $aes = new \Crypt_AES(CRYPT_AES_MODE_CBC); $aes->setKeyLength(256); $aes->setKey(Base64::UrlDecode($options['key'])); $aes->setIV(Base64::UrlDecode($options['iv'])); $aes->enablePadding(); $this->aes = $aes; $this->isAesInitialized = true; }
} ### $return = 'boxgamefile.php?id=' . urlencode($boxid); require "../configuration.php"; require "./include.php"; require_once "../includes/func.ssh2.inc.php"; require_once "../libs/phpseclib/Crypt/AES.php"; require_once "../libs/gameinstaller/gameinstaller.php"; $title = T_('Box Game File Repositories'); if (query_numrows("SELECT `name` FROM `" . DBPREFIX . "box` WHERE `boxid` = '" . $boxid . "'") == 0) { exit('Error: BoxID is invalid.'); } $rows = query_fetch_assoc("SELECT * FROM `" . DBPREFIX . "box` WHERE `boxid` = '" . $boxid . "' LIMIT 1"); $games = mysql_query("SELECT * FROM `" . DBPREFIX . "game` ORDER BY `game`"); $aes = new Crypt_AES(); $aes->setKeyLength(256); $aes->setKey(CRYPT_KEY); // Get SSH2 Object OR ERROR String $ssh = newNetSSH2($rows['ip'], $rows['sshport'], $rows['login'], $aes->decrypt($rows['password'])); if (!is_object($ssh)) { $_SESSION['msg1'] = T_('Connection Error!'); $_SESSION['msg2'] = $ssh; $_SESSION['msg-type'] = 'error'; } $gameInstaller = new GameInstaller($ssh); include "./bootstrap/header.php"; /** * Notifications */ include "./bootstrap/notifications.php"; ?>
function getPassword($pwd = null, $iv_field = "iv") { if (is_null($pwd)) { $pwd = $this->password; if (!$this->password) { return ""; } } try { $master_key_filepath = CAppUI::conf("master_key_filepath"); $master_key_filepath = rtrim($master_key_filepath, "/"); if (CExchangeSource::checkMasterKeyFile($master_key_filepath)) { CAppUI::requireLibraryFile("phpseclib/phpseclib/Crypt/AES"); CAppUI::requireLibraryFile("phpseclib/phpseclib/Crypt/Random"); $cipher = new Crypt_AES(CRYPT_AES_MODE_CTR); $cipher->setKeyLength(256); $keyAB = file($master_key_filepath . "/.mediboard.key"); if (count($keyAB) == 2) { $cipher->setKey($keyAB[0] . $keyAB[1]); $ivToUse = $this->{$iv_field}; if (!$ivToUse) { $clear = $pwd; $this->store(); return $clear; } $cipher->setIV($ivToUse); $decrypted = rtrim(base64_decode($pwd), ""); $decrypted = $cipher->decrypt($decrypted); if ($decrypted) { return $decrypted; } } } } catch (Exception $e) { return $pwd; } return $pwd; }
/** * Decrypt Session Credentials * * @param none * @return array * @access private */ private function decryptSessionCredentials() { if (!empty($this->session) && array_key_exists('CREDENTIALS', $this->session)) { switch (CONF_SEC_SESSION_METHOD) { case 'aes256': default: $cipher = new Crypt_AES(CRYPT_AES_MODE_ECB); $cipher->setKeyLength(256); $cipher->setKey($this->session_key); $credentials = unserialize($cipher->decrypt($this->session['CREDENTIALS'])); break; } return $credentials; } return array(); }
public static function getCipher($algo) { $cipher = null; switch ($algo) { case 2: if (class_exists('Crypt_TripleDES')) { $cipher = new Crypt_TripleDES(CRYPT_DES_MODE_CFB); $key_bytes = 24; $key_block_bytes = 8; } break; case 3: if (defined('MCRYPT_CAST_128')) { $cipher = new MCryptWrapper(MCRYPT_CAST_128); } break; case 7: if (class_exists('Crypt_AES')) { $cipher = new Crypt_AES(CRYPT_AES_MODE_CFB); $cipher->setKeyLength(128); } break; case 8: if (class_exists('Crypt_AES')) { $cipher = new Crypt_AES(CRYPT_AES_MODE_CFB); $cipher->setKeyLength(192); } break; case 9: if (class_exists('Crypt_AES')) { $cipher = new Crypt_AES(CRYPT_AES_MODE_CFB); $cipher->setKeyLength(256); } break; } if (!$cipher) { return array(null, null, null); // Unsupported cipher } if (!isset($key_bytes)) { $key_bytes = $cipher->key_size; } if (!isset($key_block_bytes)) { $key_block_bytes = $cipher->block_size; } return array($cipher, $key_bytes, $key_block_bytes); }
/** * Validate the signature and date of the message, then * decrypt it. * * @param string $secret * @param string $body * @param string $signature * @return string * Plain text. * @throws InvalidMessageException */ public static function authenticateThenDecrypt($secret, $body, $signature) { $keys = self::deriveAesKeys($secret); $localHmac = hash_hmac('sha256', $body, $keys['auth']); if (!self::hash_compare($signature, $localHmac)) { throw new InvalidMessageException("Incorrect hash"); } list($jsonEnvelope, $jsonEncrypted) = explode(Constants::PROTOCOL_DELIM, $body, 2); if (strlen($jsonEnvelope) > Constants::MAX_ENVELOPE_BYTES) { throw new InvalidMessageException("Oversized envelope"); } $envelope = json_decode($jsonEnvelope, TRUE); if (!$envelope) { throw new InvalidMessageException("Malformed envelope"); } if (!is_numeric($envelope['ttl']) || Time::getTime() > $envelope['ttl']) { throw new InvalidMessageException("Invalid TTL"); } if (!is_string($envelope['iv']) || strlen($envelope['iv']) !== Constants::AES_BYTES * 2 || !preg_match('/^[a-f0-9]+$/', $envelope['iv'])) { // AES_BYTES (32) ==> bin2hex ==> 2 hex digits (4-bit) per byte (8-bit) throw new InvalidMessageException("Malformed initialization vector"); } $jsonPlaintext = UserError::adapt('Civi\\Cxn\\Rpc\\Exception\\InvalidMessageException', function () use($jsonEncrypted, $envelope, $keys) { $cipher = new \Crypt_AES(CRYPT_AES_MODE_CBC); $cipher->setKeyLength(Constants::AES_BYTES); $cipher->setKey($keys['enc']); $cipher->setIV(BinHex::hex2bin($envelope['iv'])); return $cipher->decrypt($jsonEncrypted); }); return $jsonPlaintext; }
function SendEncryptedResponse($message) { $aes = new Crypt_AES(CRYPT_AES_MODE_CBC); $aes->setKeyLength(256); $aes->setKey(Base64UrlDecode($_SESSION['key'])); $aes->setIV(Base64UrlDecode($_SESSION['iv'])); $aes->enablePadding(); // This is PKCS echo Base64UrlEncode($aes->encrypt($message)); exit; }
/** * Add a New Box To The Collection * * @http_method POST * @resource box/ * * @param string $name query * @param string $os query * @param string $ip query * @param string $port query * @param string $login query * @param string $password query * @param optional string $userPath * @param optional string $steamPath * @param optional string $notes * * @return application/json * * @author Nikita Rousseau */ function postBox($name, $os, $ip, $port, $login, $password, $userPath = '', $steamPath = '', $notes = '') { $args = array('name' => $name, 'os' => $os, 'ip' => $ip, 'port' => $port, 'login' => $login, 'password' => $password, 'userPath' => $userPath, 'steamPath' => $steamPath, 'notes' => $notes); $errors = array(); // array to hold validation errors $data = array(); // array to pass back data $dbh = Core_DBH::getDBH(); // Get Database Handle // validate the variables ====================================================== $v = new Valitron\Validator($args); $rules = ['required' => [['name'], ['os'], ['ip'], ['port'], ['login'], ['password']], 'regex' => [['name', "/^([-a-z0-9_ -])+\$/i"]], 'integer' => [['os'], ['port']], 'ip' => [['ip']], 'alphaNum' => [['login']]]; $labels = array('name' => T_('Remote Machine Name'), 'os' => T_('Operating System'), 'ip' => T_('IP Address'), 'port' => T_('Port'), 'login' => T_('Login'), 'password' => T_('Password')); $v->rules($rules); $v->labels($labels); $v->validate(); $errors = $v->errors(); // validate the variables phase 2 ============================================== if (empty($errors)) { // Verify OS ID try { $sth = $dbh->prepare("\n\t\t\t\t\tSELECT operating_system\n\t\t\t\t\tFROM " . DB_PREFIX . "os\n\t\t\t\t\tWHERE\n\t\t\t\t\t\tos_id = :os_id\n\t\t\t\t\t;"); $sth->bindParam(':os_id', $args['os']); $sth->execute(); $result = $sth->fetchAll(PDO::FETCH_ASSOC); } catch (PDOException $e) { echo $e->getMessage() . ' in ' . $e->getFile() . ' on line ' . $e->getLine(); die; } if (empty($result[0])) { $errors['os'] = 'Bad Identifier'; } // Verify Communication $socket = @fsockopen($args['ip'], $args['port'], $errno, $errstr, 3); if ($socket === FALSE) { $errors['com'] = "Unable to connect to " . $args['ip'] . " on port " . $args['port'] . ". " . utf8_encode($errstr) . " ( {$errno} )"; unset($socket); } else { unset($socket); $ssh = new Net_SSH2($args['ip'], $args['port']); if (!$ssh->login($args['login'], $args['password'])) { $errors['com'] = 'Login failed'; } else { // Verify Remote Paths if (!empty($args['userPath'])) { if (boolval(trim($ssh->exec('test -d ' . escapeshellcmd($args['userPath']) . " && echo '1' || echo '0'"))) === FALSE) { $errors['remoteUserHome'] = 'Invalid path. Must be an absolute or full path'; } } if (!empty($args['steamPath'])) { if (boolval(trim($ssh->exec('test -f ' . escapeshellcmd($args['steamPath']) . " && echo '1' || echo '0'"))) === FALSE) { $errors['steamcmd'] = 'SteamCMD not found. Must be an absolute or full path'; } } } $ssh->disconnect(); } } // Apply ======================================================================= if (empty($errors)) { // // Database update // // Vars Init if (empty($args['userPath'])) { $home = "~"; $args['userPath'] = $home; } else { $home = escapeshellcmd(normalizePath($args['userPath'])); $args['userPath'] = $home; } $config = parse_ini_file(CONF_SECRET_INI); // BOX try { $sth = $dbh->prepare("\n\t\t\t\t\tINSERT INTO " . DB_PREFIX . "box\n\t\t\t\t\tSET\n\t\t\t\t\t\tos_id \t\t\t= :os,\n\t\t\t\t\t\tname \t\t\t= :name,\n\t\t\t\t\t\tsteam_lib_path \t= :steamcmd,\n\t\t\t\t\t\tnotes \t\t\t= :notes\n\t\t\t\t\t;"); $sth->bindParam(':os', $args['os']); $sth->bindParam(':name', $args['name']); $sth->bindParam(':steamcmd', $args['steamPath']); $sth->bindParam(':notes', $args['notes']); $sth->execute(); $box_id = $dbh->lastInsertId(); } catch (PDOException $e) { echo $e->getMessage() . ' in ' . $e->getFile() . ' on line ' . $e->getLine(); die; } // IP try { $sth = $dbh->prepare("\n\t\t\t\t\tINSERT INTO " . DB_PREFIX . "box_ip\n\t\t\t\t\tSET\n\t\t\t\t\t\tbox_id = :box_id,\n\t\t\t\t\t\tip = :ip,\n\t\t\t\t\t\tis_default = 1\n\t\t\t\t\t;"); $sth->bindParam(':box_id', $box_id); $sth->bindParam(':ip', $args['ip']); $sth->execute(); } catch (PDOException $e) { echo $e->getMessage() . ' in ' . $e->getFile() . ' on line ' . $e->getLine(); die; } // CREDENTIALS // Phase 1 // Connect to the remote host // Try to append our public key to authorized_keys $ssh = new Net_SSH2($args['ip'], $args['port']); $ssh->login($args['login'], $args['password']); $remote_keys = $ssh->exec('cat ' . $home . '/.ssh/authorized_keys'); // Check if the public key already exists if (strpos($remote_keys, file_get_contents(RSA_PUBLIC_KEY_FILE)) === FALSE) { // Otherwise, append it $ssh->exec("echo '" . file_get_contents(RSA_PUBLIC_KEY_FILE) . "' >> " . $home . "/.ssh/authorized_keys"); } // Phase 2 // Verify that the public key is allowed on the remote host $isUsingSSHPubKey = TRUE; // By default, we use the SSH authentication keys method $remote_keys = $ssh->exec('cat ' . $home . '/.ssh/authorized_keys'); $ssh->disconnect(); if (strpos($remote_keys, file_get_contents(RSA_PUBLIC_KEY_FILE)) === FALSE) { // authorized_keys is not writable // Use compatibility mode // Store the password in DB $isUsingSSHPubKey = FALSE; } else { // Phase 3 // Try to connect with our private key on the remote host $ssh = new Net_SSH2($args['ip'], $args['port']); $key = new Crypt_RSA(); $key->loadKey(file_get_contents(RSA_PRIVATE_KEY_FILE)); if (!$ssh->login($args['login'], $key)) { // Authentication failed // Use compatibility mode // Store the password in DB $isUsingSSHPubKey = FALSE; } $ssh->disconnect(); } // SSH CREDENTIALS $cipher = new Crypt_AES(CRYPT_AES_MODE_ECB); $cipher->setKeyLength(256); $cipher->setKey($config['APP_SSH_KEY']); if ($isUsingSSHPubKey) { try { $sth = $dbh->prepare("\n\t\t\t\t\t\tINSERT INTO " . DB_PREFIX . "box_credential\n\t\t\t\t\t\tSET\n\t\t\t\t\t\t\tlogin = :login,\n\t\t\t\t\t\t\tremote_user_home = :home,\n\t\t\t\t\t\t\tcom_protocol = 'ssh2',\n\t\t\t\t\t\t\tcom_port = :com_port\n\t\t\t\t\t\t;"); $login = $cipher->encrypt($args['login']); $sth->bindParam(':login', $login); $sth->bindParam(':home', $args['userPath']); $sth->bindParam(':com_port', $args['port']); $sth->execute(); $credential_id = $dbh->lastInsertId(); } catch (PDOException $e) { echo $e->getMessage() . ' in ' . $e->getFile() . ' on line ' . $e->getLine(); die; } } else { try { $sth = $dbh->prepare("\n\t\t\t\t\t\tINSERT INTO " . DB_PREFIX . "box_credential\n\t\t\t\t\t\tSET\n\t\t\t\t\t\t\tlogin = :login,\n\t\t\t\t\t\t\tpassword = :password,\n\t\t\t\t\t\t\tremote_user_home = :home,\n\t\t\t\t\t\t\tcom_protocol = 'ssh2',\n\t\t\t\t\t\t\tcom_port = :port\n\t\t\t\t\t\t;"); $login = $cipher->encrypt($args['login']); $password = $cipher->encrypt($args['password']); $sth->bindParam(':login', $login); $sth->bindParam(':password', $password); $sth->bindParam(':home', $args['userPath']); $sth->bindParam(':com_port', $args['port']); $sth->execute(); $credential_id = $dbh->lastInsertId(); } catch (PDOException $e) { echo $e->getMessage() . ' in ' . $e->getFile() . ' on line ' . $e->getLine(); die; } } // UPDATE BOX try { $sth = $dbh->prepare("\n\t\t\t\t\tUPDATE " . DB_PREFIX . "box\n\t\t\t\t\tSET\n\t\t\t\t\t\tbox_credential_id = :box_credential_id\n\t\t\t\t\tWHERE box_id = :box_id\n\t\t\t\t\t;"); $sth->bindParam(':box_credential_id', $credential_id); $sth->bindParam(':box_id', $box_id); $sth->execute(); } catch (PDOException $e) { echo $e->getMessage() . ' in ' . $e->getFile() . ' on line ' . $e->getLine(); die; } } // return a response and log =================================================== $logger = self::getLogger(); $data['errors'] = $errors; if (!empty($data['errors'])) { $data['success'] = false; $logger->info('Failed to add box.'); } else { $data['success'] = true; $logger->info('Box added.'); } return array('response' => 'application/json', 'data' => json_encode($data)); }
public function onStartMagicEnvelopeToXML(MagicEnvelope $magic_env, XMLStringer $xs, $flavour = null, Profile $target = null) { // Since Diaspora doesn't use a separate namespace for their "extended" // salmon slap, we'll have to resort to this workaround hack. if ($flavour !== 'diaspora') { return true; } // WARNING: This changes the $magic_env contents! Be aware of it. /** * https://wiki.diasporafoundation.org/Federation_protocol_overview * http://www.rubydoc.info/github/Raven24/diaspora-federation/master/DiasporaFederation/Salmon/EncryptedSlap * * Constructing the encryption header */ // For some reason diaspora wants the salmon slap in a <diaspora> header. $xs->elementStart('diaspora', array('xmlns' => 'https://joindiaspora.com/protocol')); /** * Choose an AES key and initialization vector, suitable for the * aes-256-cbc cipher. I shall refer to this as the “inner key” * and the “inner initialization vector (iv)”. */ $inner_key = new Crypt_AES(CRYPT_AES_MODE_CBC); $inner_key->setKeyLength(256); // set length to 256 bits (could be calculated, but let's be sure) $inner_key->setKey(common_random_rawstr(32)); // 32 bytes from a (pseudo) random source $inner_key->setIV(common_random_rawstr(16)); // 16 bytes is the block length /** * Construct the following XML snippet: * <decrypted_header> * <iv>((base64-encoded inner iv))</iv> * <aes_key>((base64-encoded inner key))</aes_key> * <author> * <name>Alice Exampleman</name> * <uri>acct:user@sender.example</uri> * </author> * </decrypted_header> */ $decrypted_header = sprintf('<decrypted_header><iv>%1$s</iv><aes_key>%2$s</aes_key><author_id>%3$s</author_id></decrypted_header>', base64_encode($inner_key->iv), base64_encode($inner_key->key), $magic_env->getActor()->getAcctUri()); /** * Construct another AES key and initialization vector suitable * for the aes-256-cbc cipher. I shall refer to this as the * “outer key” and the “outer initialization vector (iv)”. */ $outer_key = new Crypt_AES(CRYPT_AES_MODE_CBC); $outer_key->setKeyLength(256); // set length to 256 bits (could be calculated, but let's be sure) $outer_key->setKey(common_random_rawstr(32)); // 32 bytes from a (pseudo) random source $outer_key->setIV(common_random_rawstr(16)); // 16 bytes is the block length /** * Encrypt your <decrypted_header> XML snippet using the “outer key” * and “outer iv” (using the aes-256-cbc cipher). This encrypted * blob shall be referred to as “the ciphertext”. */ $ciphertext = $outer_key->encrypt($decrypted_header); /** * Construct the following JSON object, which shall be referred to * as “the outer aes key bundle”: * { * "iv": ((base64-encoded AES outer iv)), * "key": ((base64-encoded AES outer key)) * } */ $outer_bundle = json_encode(array('iv' => base64_encode($outer_key->iv), 'key' => base64_encode($outer_key->key))); /** * Encrypt the “outer aes key bundle” with Bob’s RSA public key. * I shall refer to this as the “encrypted outer aes key bundle”. */ common_debug('Diaspora creating "outer aes key bundle", will require magic-public-key'); $key_fetcher = new MagicEnvelope(); $remote_keys = $key_fetcher->getKeyPair($target, true); // actually just gets the public key $enc_outer = $remote_keys->publicKey->encrypt($outer_bundle); /** * Construct the following JSON object, which I shall refer to as * the “encrypted header json object”: * { * "aes_key": ((base64-encoded encrypted outer aes key bundle)), * "ciphertext": ((base64-encoded ciphertextm from above)) * } */ $enc_header = json_encode(array('aes_key' => base64_encode($enc_outer), 'ciphertext' => base64_encode($ciphertext))); /** * Construct the xml snippet: * <encrypted_header>((base64-encoded encrypted header json object))</encrypted_header> */ $xs->element('encrypted_header', null, base64_encode($enc_header)); /** * In order to prepare the payload message for inclusion in your * salmon slap, you will: * * 1. Encrypt the payload message using the aes-256-cbc cipher and * the “inner encryption key” and “inner encryption iv” you * chose earlier. * 2. Base64-encode the encrypted payload message. */ $payload = $inner_key->encrypt($magic_env->getData()); //FIXME: This means we don't actually put an <atom:entry> in the payload, // since Diaspora has its own update method! Silly me. Read up on: // https://wiki.diasporafoundation.org/Federation_Message_Semantics $magic_env->signMessage(base64_encode($payload), 'application/xml'); // Since we have to change the content of me:data we'll just write the // whole thing from scratch. We _could_ otherwise have just manipulated // that element and added the encrypted_header in the EndMagicEnvelopeToXML event. $xs->elementStart('me:env', array('xmlns:me' => MagicEnvelope::NS)); $xs->element('me:data', array('type' => $magic_env->getDataType()), $magic_env->getData()); $xs->element('me:encoding', null, $magic_env->getEncoding()); $xs->element('me:alg', null, $magic_env->getSignatureAlgorithm()); $xs->element('me:sig', null, $magic_env->getSignature()); $xs->elementEnd('me:env'); $xs->elementEnd('entry'); return false; }
public static function getCipher($algo) { $cipher = NULL; switch ($algo) { case 2: if (class_exists('Crypt_TripleDES')) { $cipher = new Crypt_TripleDES(CRYPT_DES_MODE_CFB); $key_bytes = 24; $key_block_bytes = 8; } break; case 3: if (defined('MCRYPT_CAST_128')) { $cipher = new MCryptWrapper(MCRYPT_CAST_128); } else { $cipher = new Horde_Pgp_Crypt_Cast128(); } /* End Horde Change */ break; /* Horde change */ /* Horde change */ case 4: $cipher = new Crypt_Blowfish(CRYPT_BLOWFISH_MODE_CFB); $key_bytes = 16; break; /* End Horde Change */ /* End Horde Change */ case 7: if (class_exists('Crypt_AES')) { $cipher = new Crypt_AES(CRYPT_AES_MODE_CFB); $cipher->setKeyLength(128); } break; case 8: if (class_exists('Crypt_AES')) { $cipher = new Crypt_AES(CRYPT_AES_MODE_CFB); $cipher->setKeyLength(192); } break; case 9: if (class_exists('Crypt_AES')) { $cipher = new Crypt_AES(CRYPT_AES_MODE_CFB); $cipher->setKeyLength(256); } break; /* Horde change */ /* Horde change */ case 10: $cipher = new Crypt_Twofish(CRYPT_TWOFISH_MODE_CFB); $key_bytes = 32; break; /* End Horde Change */ } if (!$cipher) { return array(NULL, NULL, NULL); } // Unsupported cipher if (!isset($key_bytes)) { $key_bytes = $cipher->key_size; } if (!isset($key_block_bytes)) { $key_block_bytes = $cipher->block_size; } return array($cipher, $key_bytes, $key_block_bytes); }
/** */ public function generateKey($opts) { $skey = $this->_generateSecretKeyPacket($opts['keylength'], 'OpenPGP_SecretKeyPacket'); $id = new Horde_Mail_Rfc822_Address($opts['email']); if (strlen($opts['comment'])) { $id->comment[] = $opts['comment']; } if (strlen($opts['name'])) { $id->personal = $opts['name']; } /* This is the private key we are creating. */ $key = new OpenPGP_Message(array($skey, new OpenPGP_UserIDPacket($id->writeAddress(array('comment' => true))))); $rsa = OpenPGP_Crypt_RSA::convert_private_key($skey); $rsa->setHash(Horde_String::lower($opts['hash'])); $rsa_sign_func = array('RSA' => array($opts['hash'] => function ($data) use($rsa) { return array($rsa->sign($data)); })); /* Create signature packet. */ $sig = new OpenPGP_SignaturePacket($key, 'RSA', $opts['hash']); /* "Generic certification of a User ID and Public-Key packet." */ $sig->signature_type = 0x10; /* Add subpacket information. */ $sig->hashed_subpackets[] = new OpenPGP_SignaturePacket_KeyFlagsPacket(array(0x3)); $sig->hashed_subpackets[] = new OpenPGP_SignaturePacket_PreferredSymmetricAlgorithmsPacket(array(0x9, 0x8, 0x7, 0x2)); $sig->hashed_subpackets[] = new OpenPGP_SignaturePacket_PreferredHashAlgorithmsPacket(array(0x8, 0x9, 0xa, 0xb, 0x2)); $sig->hashed_subpackets[] = new OpenPGP_SignaturePacket_PreferredCompressionAlgorithmsPacket(array(0x2, 0x1)); $ks_prefs = new OpenPGP_SignaturePacket_KeyServerPreferencesPacket(); $ks_prefs->no_modify = true; $sig->hashed_subpackets[] = $ks_prefs; $sig->hashed_subpackets[] = new OpenPGP_SignaturePacket_FeaturesPacket(array(0x1)); if (isset($opts['expire'])) { $sig->hashed_subpackets[] = new OpenPGP_SignaturePacket_KeyExpirationTimePacket($opts['expire'] - time()); } $sig->unhashed_subpackets[] = new OpenPGP_SignaturePacket_IssuerPacket(substr($skey->fingerprint, -16)); $key[] = $sig; /* Create self-signature. */ $sig->sign_data($rsa_sign_func); /* OpenPGP currently (as of April 2015) encrypts passphrases w/ * AES-128 & SHA-1, so use this strategy. */ if (strlen($opts['passphrase'])) { $cipher = new Crypt_AES(CRYPT_AES_MODE_CFB); $cipher->setKeyLength(128); $s2k = new OpenPGP_S2K(crypt_random_string(8), 2); $cipher->setKey($s2k->make_key($opts['passphrase'], 16)); $iv = crypt_random_string(16); $this->_encryptPrivateKey($skey, $cipher, $s2k, $iv); } /* Encryption subkey. See RFC 4880 [5.5.1.2] (by convention, top-level * key is used for signing and subkeys are used for encryption) */ $ekey = $this->_generateSecretKeyPacket($opts['keylength'], 'OpenPGP_SecretSubkeyPacket'); /* Computing signature: RFC 4880 [5.2.4] */ $sig = new OpenPGP_SignaturePacket(implode('', $skey->fingerprint_material()) . implode('', $ekey->fingerprint_material()), 'RSA', $opts['hash']); /* This is a "Subkey Binding Signature". */ $sig->signature_type = 0x18; $sig->hashed_subpackets[] = new OpenPGP_SignaturePacket_KeyFlagsPacket(array(0xc)); $sig->unhashed_subpackets[] = new OpenPGP_SignaturePacket_IssuerPacket(substr($skey->fingerprint, -16)); $sig->sign_data($rsa_sign_func); if (strlen($opts['passphrase'])) { $this->_encryptPrivateKey($ekey, $cipher, $s2k, $iv); } $key[] = $ekey; $key[] = $sig; return new Horde_Pgp_Element_PrivateKey($key); }