/** * Encrypt data. * * @param string $text Plaintext. * * @return array Array of MPI values (c1, c2). */ public function encrypt($text) { $p_len = strlen($this->_key->key['p']); $length = $p_len - 11; if ($length <= 0) { return false; } $g = new Math_BigInteger($this->_key->key['g'], 256); $p = new Math_BigInteger($this->_key->key['p'], 256); $y = new Math_BigInteger($this->_key->key['y'], 256); $out = array(); foreach (str_split($text, $length) as $m) { // EME-PKCS1-v1_5 encoding $psLen = $p_len - strlen($m) - 3; $ps = ''; while (($psLen2 = strlen($ps)) != $psLen) { $tmp = crypt_random_string($psLen - $psLen2); $ps .= str_replace("", '', $tmp); } $em = new Math_BigInteger(chr(0) . chr(2) . $ps . chr(0) . $m, 256); // End EME-PKCS1-v1_5 encoding $k = Horde_Pgp_Crypt_DSA::randomNumber($p); $c1 = $g->modPow($k, $p); $c2_base = $y->modPow($k, $p)->multiply($em)->divide($p); $c2 = $c2_base[1]; $out[] = str_pad($c1->toBytes(), $p_len, chr(0), STR_PAD_LEFT); $out[] = str_pad($c2->toBytes(), $p_len, chr(0), STR_PAD_LEFT); } return $out; }
function encrypt_message($plaintext, $asym_key, $key_length = 150) { $rsa = new Crypt_RSA(); $rij = new Crypt_Rijndael(); // Generate Random Symmetric Key $sym_key = crypt_random_string($key_length); // Encrypt Message with new Symmetric Key $rij->setKey($sym_key); $ciphertext = $rij->encrypt($plaintext); $ciphertext = base64_encode($ciphertext); // Encrypted the Symmetric Key with the Asymmetric Key $rsa->loadKey($asym_key); $sym_key = $rsa->encrypt($sym_key); // Base 64 encode the symmetric key for transport $sym_key = base64_encode($sym_key); $len = strlen($sym_key); // Get the length $len = dechex($len); // The first 3 bytes of the message are the key length $len = str_pad($len, 3, '0', STR_PAD_LEFT); // Zero pad to be sure. // Concatinate the length, the encrypted symmetric key, and the message $message = $len . $sym_key . $ciphertext; return $message; }
/** * Takes a set of random values of length 128 bits and asserts all taken * values are unique. */ public function testStringUniqueness() { $values = array(); for ($i = 0; $i < 10000; ++$i) { $rand = crypt_random_string(16); $this->assertSame(16, strlen($rand)); $this->assertArrayNotHasKey($rand, $values, 'Failed asserting that generated value does not exist in set.'); $values[$rand] = true; } }
/** * Generate a number that lies between 0 and q-1. * * @param Math_BigInteger $q Max number. * * @return Math_BigInteger Generated number. */ public static function randomNumber($q) { $bytes = strlen($q->toBytes()) + 8; $ints = $bytes + 1 >> 2; $cstring = crypt_random_string($ints); $random = ''; for ($i = 0; $i < $ints; ++$i) { $random .= pack('N', $cstring[$i]); } $c = new Math_BigInteger(substr($random, 0, $bytes), 256); $one = new Math_BigInteger(1); $result_base = $c->divide($q->subtract($one)); return $result_base[1]->add($one); }
/** * Encrypt $plaintext with $secret, then date and sign the message. * * @param string $secret * @param string $plaintext * @return array * Array(string $body, string $signature). * Note that $body begins with an unencrypted envelope (ttl, iv). * @throws InvalidMessageException */ public static function encryptThenSign($secret, $plaintext) { $iv = crypt_random_string(Constants::AES_BYTES); $keys = AesHelper::deriveAesKeys($secret); $cipher = new \Crypt_AES(CRYPT_AES_MODE_CBC); $cipher->setKeyLength(Constants::AES_BYTES); $cipher->setKey($keys['enc']); $cipher->setIV($iv); // JSON string; this will be signed but not encrypted $jsonEnvelope = json_encode(array('ttl' => Time::getTime() + Constants::REQUEST_TTL, 'iv' => BinHex::bin2hex($iv))); // JSON string; this will be signed and encrypted $jsonEncrypted = $cipher->encrypt($plaintext); $body = $jsonEnvelope . Constants::PROTOCOL_DELIM . $jsonEncrypted; $signature = hash_hmac('sha256', $body, $keys['auth']); return array($body, $signature); }
/** * Encrypt the OAuth token * @param \stdClass $token Serialized token object * @return string */ public function encrypt($token) { // Encryption: we always use phpseclib for this global $updraftplus; $updraftplus->ensure_phpseclib('Crypt_AES', 'Crypt/AES'); $updraftplus->ensure_phpseclib('Crypt_Rijndael', 'Crypt/Rijndael'); if (!function_exists('crypt_random_string')) { require_once UPDRAFTPLUS_DIR . '/includes/phpseclib/Crypt/Random.php'; } $iv = crypt_random_string(self::IV_SIZE); // Defaults to CBC mode $rijndael = new Crypt_Rijndael(); $rijndael->setKey($this->key); $rijndael->setIV($iv); $cipherText = $rijndael->encrypt($token); return base64_encode($iv . $cipherText); }
function genMasterKey($dirKey, $apacheGroup = "www-data") { if ($apacheGroup === "") { $apacheGroup = "www-data"; } $dirKey = rtrim($dirKey, "/"); $dirs = explode("/", $dirKey); chdir("/"); foreach ($dirs as $dir) { if ($dir === "") { continue; } if (!file_exists($dir)) { mkdir($dir, 0750); chgrp($dir, $apacheGroup); } if (!is_readable($dir)) { chmod($dir, 0750); chgrp($dir, $apacheGroup); } chdir($dir); } $f = fopen($dirKey . "/.mediboard.key", "w"); if (!$f) { echo "Failed to create key file!"; return 0; } fclose($f); chmod(".mediboard.key", 0760); chgrp(".mediboard.key", $apacheGroup); $keyA = bin2hex(crypt_random_string(16)); $keyB = bin2hex(crypt_random_string(16)); $handle = fopen(".mediboard.key", "w"); if (!$handle) { return 0; } fwrite($handle, $keyA . "\n" . $keyB); fclose($handle); chmod(".mediboard.key", 0750); return 1; }
public static function encrypt($passphrases_and_keys, $message, $symmetric_algorithm = 9) { list($cipher, $key_bytes, $key_block_bytes) = self::getCipher($symmetric_algorithm); if (!$cipher) { throw new Exception("Unsupported cipher"); } $prefix = crypt_random_string($key_block_bytes); $prefix .= substr($prefix, -2); $key = crypt_random_string($key_bytes); $cipher->setKey($key); $to_encrypt = $prefix . $message->to_bytes(); $mdc = new OpenPGP_ModificationDetectionCodePacket(hash('sha1', $to_encrypt . "Ó", true)); $to_encrypt .= $mdc->to_bytes(); $encrypted = array(new OpenPGP_IntegrityProtectedDataPacket($cipher->encrypt($to_encrypt))); if (!is_array($passphrases_and_keys) && !$passphrases_and_keys instanceof IteratorAggregate) { $passphrases_and_keys = (array) $passphrases_and_keys; } foreach ($passphrases_and_keys as $pass) { if ($pass instanceof OpenPGP_PublicKeyPacket) { if (!in_array($pass->algorithm, array(1, 2, 3))) { throw new Exception("Only RSA keys are supported."); } $crypt_rsa = new OpenPGP_Crypt_RSA($pass); $rsa = $crypt_rsa->public_key(); $rsa->setEncryptionMode(CRYPT_RSA_ENCRYPTION_PKCS1); $esk = $rsa->encrypt(chr($symmetric_algorithm) . $key . pack('n', self::checksum($key))); $esk = pack('n', OpenPGP::bitlength($esk)) . $esk; array_unshift($encrypted, new OpenPGP_AsymmetricSessionKeyPacket($pass->algorithm, $pass->fingerprint(), $esk)); } else { if (is_string($pass)) { $s2k = new OpenPGP_S2K(crypt_random_string(10)); $cipher->setKey($s2k->make_key($pass, $key_bytes)); $esk = $cipher->encrypt(chr($symmetric_algorithm) . $key); array_unshift($encrypted, new OpenPGP_SymmetricSessionKeyPacket($s2k, $esk, $symmetric_algorithm)); } } } return new OpenPGP_Message($encrypted); }
/** * Sign an X.509 certificate * * $issuer's private key needs to be loaded. * $subject can be either an existing X.509 cert (if you want to resign it), * a CSR or something with the DN and public key explicitly set. * * @param File_X509 $issuer * @param File_X509 $subject * @param string $signatureAlgorithm optional * @access public * @return mixed */ function sign($issuer, $subject, $signatureAlgorithm = 'sha1WithRSAEncryption') { if (!is_object($issuer->privateKey) || empty($issuer->dn)) { return false; } if (isset($subject->publicKey) && !($subjectPublicKey = $subject->_formatSubjectPublicKey())) { return false; } $currentCert = isset($this->currentCert) ? $this->currentCert : null; $signatureSubject = isset($this->signatureSubject) ? $this->signatureSubject : null; if (isset($subject->currentCert) && is_array($subject->currentCert) && isset($subject->currentCert['tbsCertificate'])) { $this->currentCert = $subject->currentCert; $this->currentCert['tbsCertificate']['signature']['algorithm'] = $signatureAlgorithm; $this->currentCert['signatureAlgorithm']['algorithm'] = $signatureAlgorithm; if (!empty($this->startDate)) { $this->currentCert['tbsCertificate']['validity']['notBefore'] = $this->_timeField($this->startDate); } if (!empty($this->endDate)) { $this->currentCert['tbsCertificate']['validity']['notAfter'] = $this->_timeField($this->endDate); } if (!empty($this->serialNumber)) { $this->currentCert['tbsCertificate']['serialNumber'] = $this->serialNumber; } if (!empty($subject->dn)) { $this->currentCert['tbsCertificate']['subject'] = $subject->dn; } if (!empty($subject->publicKey)) { $this->currentCert['tbsCertificate']['subjectPublicKeyInfo'] = $subjectPublicKey; } $this->removeExtension('id-ce-authorityKeyIdentifier'); if (isset($subject->domains)) { $this->removeExtension('id-ce-subjectAltName'); } } elseif (isset($subject->currentCert) && is_array($subject->currentCert) && isset($subject->currentCert['tbsCertList'])) { return false; } else { if (!isset($subject->publicKey)) { return false; } $startDate = !empty($this->startDate) ? $this->startDate : @date('D, d M Y H:i:s O'); $endDate = !empty($this->endDate) ? $this->endDate : @date('D, d M Y H:i:s O', strtotime('+1 year')); if (!empty($this->serialNumber)) { $serialNumber = $this->serialNumber; } else { if (!function_exists('crypt_random_string')) { include_once 'Crypt/Random.php'; } /* "The serial number MUST be a positive integer" "Conforming CAs MUST NOT use serialNumber values longer than 20 octets." -- https://tools.ietf.org/html/rfc5280#section-4.1.2.2 for the integer to be positive the leading bit needs to be 0 hence the application of a bitmap */ $serialNumber = new Math_BigInteger(crypt_random_string(20) & "" . str_repeat("ÿ", 19), 256); } $this->currentCert = array('tbsCertificate' => array('version' => 'v3', 'serialNumber' => $serialNumber, 'signature' => array('algorithm' => $signatureAlgorithm), 'issuer' => false, 'validity' => array('notBefore' => $this->_timeField($startDate), 'notAfter' => $this->_timeField($endDate)), 'subject' => $subject->dn, 'subjectPublicKeyInfo' => $subjectPublicKey), 'signatureAlgorithm' => array('algorithm' => $signatureAlgorithm), 'signature' => false); // Copy extensions from CSR. $csrexts = $subject->getAttribute('pkcs-9-at-extensionRequest', 0); if (!empty($csrexts)) { $this->currentCert['tbsCertificate']['extensions'] = $csrexts; } } $this->currentCert['tbsCertificate']['issuer'] = $issuer->dn; if (isset($issuer->currentKeyIdentifier)) { $this->setExtension('id-ce-authorityKeyIdentifier', array('keyIdentifier' => $issuer->currentKeyIdentifier)); //$extensions = &$this->currentCert['tbsCertificate']['extensions']; //if (isset($issuer->serialNumber)) { // $extensions[count($extensions) - 1]['authorityCertSerialNumber'] = $issuer->serialNumber; //} //unset($extensions); } if (isset($subject->currentKeyIdentifier)) { $this->setExtension('id-ce-subjectKeyIdentifier', $subject->currentKeyIdentifier); } $altName = array(); if (isset($subject->domains) && count($subject->domains) > 1) { $altName = array_map(array('File_X509', '_dnsName'), $subject->domains); } if (isset($subject->ipAddresses) && count($subject->ipAddresses)) { // should an IP address appear as the CN if no domain name is specified? idk //$ips = count($subject->domains) ? $subject->ipAddresses : array_slice($subject->ipAddresses, 1); $ipAddresses = array(); foreach ($subject->ipAddresses as $ipAddress) { $encoded = $subject->_ipAddress($ipAddress); if ($encoded !== false) { $ipAddresses[] = $encoded; } } if (count($ipAddresses)) { $altName = array_merge($altName, $ipAddresses); } } if (!empty($altName)) { $this->setExtension('id-ce-subjectAltName', $altName); } if ($this->caFlag) { $keyUsage = $this->getExtension('id-ce-keyUsage'); if (!$keyUsage) { $keyUsage = array(); } $this->setExtension('id-ce-keyUsage', array_values(array_unique(array_merge($keyUsage, array('cRLSign', 'keyCertSign'))))); $basicConstraints = $this->getExtension('id-ce-basicConstraints'); if (!$basicConstraints) { $basicConstraints = array(); } $this->setExtension('id-ce-basicConstraints', array_unique(array_merge(array('cA' => true), $basicConstraints)), true); if (!isset($subject->currentKeyIdentifier)) { $this->setExtension('id-ce-subjectKeyIdentifier', base64_encode($this->computeKeyIdentifier($this->currentCert)), false, false); } } // resync $this->signatureSubject // save $tbsCertificate in case there are any File_ASN1_Element objects in it $tbsCertificate = $this->currentCert['tbsCertificate']; $this->loadX509($this->saveX509($this->currentCert)); $result = $this->_sign($issuer->privateKey, $signatureAlgorithm); $result['tbsCertificate'] = $tbsCertificate; $this->currentCert = $currentCert; $this->signatureSubject = $signatureSubject; return $result; }
/** * Generate a random string. * * Although microoptimizations are generally discouraged as they impair readability this function is ripe with * microoptimizations because this function has the potential of being called a huge number of times. * eg. for RSA key generation. * * @param Integer $length * @return String * @access public */ function crypt_random_string($length) { if (CRYPT_RANDOM_IS_WINDOWS) { // method 1. prior to PHP 5.3 this would call rand() on windows hence the function_exists('class_alias') call. // ie. class_alias is a function that was introduced in PHP 5.3 if (function_exists('mcrypt_create_iv') && function_exists('class_alias')) { return mcrypt_create_iv($length); } // method 2. openssl_random_pseudo_bytes was introduced in PHP 5.3.0 but prior to PHP 5.3.4 there was, // to quote <http://php.net/ChangeLog-5.php#5.3.4>, "possible blocking behavior". as of 5.3.4 // openssl_random_pseudo_bytes and mcrypt_create_iv do the exact same thing on Windows. ie. they both // call php_win32_get_random_bytes(): // // https://github.com/php/php-src/blob/7014a0eb6d1611151a286c0ff4f2238f92c120d6/ext/openssl/openssl.c#L5008 // https://github.com/php/php-src/blob/7014a0eb6d1611151a286c0ff4f2238f92c120d6/ext/mcrypt/mcrypt.c#L1392 // // php_win32_get_random_bytes() is defined thusly: // // https://github.com/php/php-src/blob/7014a0eb6d1611151a286c0ff4f2238f92c120d6/win32/winutil.c#L80 // // we're calling it, all the same, in the off chance that the mcrypt extension is not available if (function_exists('openssl_random_pseudo_bytes') && version_compare(PHP_VERSION, '5.3.4', '>=')) { return openssl_random_pseudo_bytes($length); } } else { // method 1. the fastest if (function_exists('openssl_random_pseudo_bytes')) { return openssl_random_pseudo_bytes($length); } // method 2 static $fp = true; if ($fp === true) { // warning's will be output unles the error suppression operator is used. errors such as // "open_basedir restriction in effect", "Permission denied", "No such file or directory", etc. $fp = @fopen('/dev/urandom', 'rb'); } if ($fp !== true && $fp !== false) { // surprisingly faster than !is_bool() or is_resource() return fread($fp, $length); } // method 3. pretty much does the same thing as method 2 per the following url: // https://github.com/php/php-src/blob/7014a0eb6d1611151a286c0ff4f2238f92c120d6/ext/mcrypt/mcrypt.c#L1391 // surprisingly slower than method 2. maybe that's because mcrypt_create_iv does a bunch of error checking that we're // not doing. regardless, this'll only be called if this PHP script couldn't open /dev/urandom due to open_basedir // restrictions or some such if (function_exists('mcrypt_create_iv')) { return mcrypt_create_iv($length, MCRYPT_DEV_URANDOM); } } // at this point we have no choice but to use a pure-PHP CSPRNG // cascade entropy across multiple PHP instances by fixing the session and collecting all // environmental variables, including the previous session data and the current session // data. // // mt_rand seeds itself by looking at the PID and the time, both of which are (relatively) // easy to guess at. linux uses mouse clicks, keyboard timings, etc, as entropy sources, but // PHP isn't low level to be able to use those as sources and on a web server there's not likely // going to be a ton of keyboard or mouse action. web servers do have one thing that we can use // however. a ton of people visiting the website. obviously you don't want to base your seeding // soley on parameters a potential attacker sends but (1) not everything in $_SERVER is controlled // by the user and (2) this isn't just looking at the data sent by the current user - it's based // on the data sent by all users. one user requests the page and a hash of their info is saved. // another user visits the page and the serialization of their data is utilized along with the // server envirnment stuff and a hash of the previous http request data (which itself utilizes // a hash of the session data before that). certainly an attacker should be assumed to have // full control over his own http requests. he, however, is not going to have control over // everyone's http requests. static $crypto = false, $v; if ($crypto === false) { // save old session data $old_session_id = session_id(); $old_use_cookies = ini_get('session.use_cookies'); $old_session_cache_limiter = session_cache_limiter(); if (isset($_SESSION)) { $_OLD_SESSION = $_SESSION; } if ($old_session_id != '') { session_write_close(); } session_id(1); ini_set('session.use_cookies', 0); session_cache_limiter(''); session_start(); $v = $seed = $_SESSION['seed'] = pack('H*', sha1(serialize($_SERVER) . serialize($_POST) . serialize($_GET) . serialize($_COOKIE) . serialize($GLOBALS) . serialize($_SESSION) . serialize($_OLD_SESSION))); if (!isset($_SESSION['count'])) { $_SESSION['count'] = 0; } $_SESSION['count']++; session_write_close(); // restore old session data if ($old_session_id != '') { session_id($old_session_id); session_start(); ini_set('session.use_cookies', $old_use_cookies); session_cache_limiter($old_session_cache_limiter); } else { if (isset($_OLD_SESSION)) { $_SESSION = $_OLD_SESSION; unset($_OLD_SESSION); } else { unset($_SESSION); } } // in SSH2 a shared secret and an exchange hash are generated through the key exchange process. // the IV client to server is the hash of that "nonce" with the letter A and for the encryption key it's the letter C. // if the hash doesn't produce enough a key or an IV that's long enough concat successive hashes of the // original hash and the current hash. we'll be emulating that. for more info see the following URL: // // http://tools.ietf.org/html/rfc4253#section-7.2 // // see the is_string($crypto) part for an example of how to expand the keys $key = pack('H*', sha1($seed . 'A')); $iv = pack('H*', sha1($seed . 'C')); // ciphers are used as per the nist.gov link below. also, see this link: // // http://en.wikipedia.org/wiki/Cryptographically_secure_pseudorandom_number_generator#Designs_based_on_cryptographic_primitives switch (true) { case class_exists('Crypt_AES'): $crypto = new Crypt_AES(CRYPT_AES_MODE_CTR); break; case class_exists('Crypt_TripleDES'): $crypto = new Crypt_TripleDES(CRYPT_DES_MODE_CTR); break; case class_exists('Crypt_DES'): $crypto = new Crypt_DES(CRYPT_DES_MODE_CTR); break; case class_exists('Crypt_RC4'): $crypto = new Crypt_RC4(); break; default: $crypto = $seed; return crypt_random_string($length); } $crypto->setKey($key); $crypto->setIV($iv); $crypto->enableContinuousBuffer(); } if (is_string($crypto)) { // the following is based off of ANSI X9.31: // // http://csrc.nist.gov/groups/STM/cavp/documents/rng/931rngext.pdf // // OpenSSL uses that same standard for it's random numbers: // // http://www.opensource.apple.com/source/OpenSSL/OpenSSL-38/openssl/fips-1.0/rand/fips_rand.c // (do a search for "ANS X9.31 A.2.4") // // ANSI X9.31 recommends ciphers be used and phpseclib does use them if they're available (see // later on in the code) but if they're not we'll use sha1 $result = ''; while (strlen($result) < $length) { // each loop adds 20 bytes // microtime() isn't packed as "densely" as it could be but then neither is that the idea. // the idea is simply to ensure that each "block" has a unique element to it. $i = pack('H*', sha1(microtime())); $r = pack('H*', sha1($i ^ $v)); $v = pack('H*', sha1($r ^ $i)); $result .= $r; } return substr($result, 0, $length); } //return $crypto->encrypt(str_repeat("\0", $length)); $result = ''; while (strlen($result) < $length) { $i = $crypto->encrypt(microtime()); $r = $crypto->encrypt($i ^ $v); $v = $crypto->encrypt($r ^ $i); $result .= $r; } return substr($result, 0, $length); }
private function generateRandomBytes($length) { return crypt_random_string($length); }
/** * RSA Encrypt * * Returns mod(pow($m, $e), $n), where $n should be the product of two (large) primes $p and $q and where $e * should be a number with the property that gcd($e, ($p - 1) * ($q - 1)) == 1. Could just make anything that * calls this call modexp, instead, but I think this makes things clearer, maybe... * * @see Net_SSH1::Net_SSH1() * @param Math_BigInteger $m * @param Array $key * @return Math_BigInteger * @access private */ function _rsa_crypt($m, $key) { /* if (!class_exists('Crypt_RSA')) { include_once 'Crypt/RSA.php'; } $rsa = new Crypt_RSA(); $rsa->loadKey($key, CRYPT_RSA_PUBLIC_FORMAT_RAW); $rsa->setEncryptionMode(CRYPT_RSA_ENCRYPTION_PKCS1); return $rsa->encrypt($m); */ // To quote from protocol-1.5.txt: // The most significant byte (which is only partial as the value must be // less than the public modulus, which is never a power of two) is zero. // // The next byte contains the value 2 (which stands for public-key // encrypted data in the PKCS standard [PKCS#1]). Then, there are non- // zero random bytes to fill any unused space, a zero byte, and the data // to be encrypted in the least significant bytes, the last byte of the // data in the least significant byte. // Presumably the part of PKCS#1 they're refering to is "Section 7.2.1 Encryption Operation", // under "7.2 RSAES-PKCS1-v1.5" and "7 Encryption schemes" of the following URL: // ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1.pdf $modulus = $key[1]->toBytes(); $length = strlen($modulus) - strlen($m) - 3; $random = ''; while (strlen($random) != $length) { $block = crypt_random_string($length - strlen($random)); $block = str_replace("", '', $block); $random .= $block; } $temp = chr(0) . chr(2) . $random . chr(0) . $m; $m = new Math_BigInteger($temp, 256); $m = $m->modPow($key[0], $key[1]); return $m->toBytes(); }
/** * Generate a pseudo random binary string * * @param int $length Binary string length * * @return string */ static function getRandomBinaryString($length) { return crypt_random_string($length); }
function encryptString($pwd = null, $iv_field = "iv") { if (is_null($pwd)) { $pwd = $this->password; } 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); // keys are null-padded to the closest valid size // longer than the longest key and it's truncated $cipher->setKeyLength(256); $keyAB = file($master_key_filepath . "/.mediboard.key"); if (count($keyAB) == 2) { $cipher->setKey($keyAB[0] . $keyAB[1]); $iv = bin2hex(crypt_random_string(16)); $this->{$iv_field} = $iv; $cipher->setIV($iv); $encrypted = rtrim(base64_encode($cipher->encrypt($pwd)), ""); if ($encrypted) { return $encrypted; } } } else { // Key is not available $this->{$iv_field} = ""; } } catch (Exception $e) { return $pwd; } return $pwd; }
function create_RandomString($length = 32) { return bin2hex(crypt_random_string($length)); }
/** * Generate a random number * * @param optional Integer $min * @param optional Integer $max * @return Math_BigInteger * @access public */ function random($min = false, $max = false) { if ($min === false) { $min = new Math_BigInteger(0); } if ($max === false) { $max = new Math_BigInteger(0x7fffffff); } $compare = $max->compare($min); if (!$compare) { return $this->_normalize($min); } else { if ($compare < 0) { // if $min is bigger then $max, swap $min and $max $temp = $max; $max = $min; $min = $temp; } } $generator = $this->generator; $max = $max->subtract($min); $max = ltrim($max->toBytes(), chr(0)); $size = strlen($max) - 1; $crypt_random = function_exists('crypt_random_string') || !class_exists('Crypt_Random') && function_exists('crypt_random_string'); if ($crypt_random) { $random = crypt_random_string($size); } else { $random = ''; if ($size & 1) { $random .= chr(mt_rand(0, 255)); } $blocks = $size >> 1; for ($i = 0; $i < $blocks; ++$i) { // mt_rand(-2147483648, 0x7FFFFFFF) always produces -2147483648 on some systems $random .= pack('n', mt_rand(0, 0xffff)); } } $fragment = new Math_BigInteger($random, 256); $leading = $fragment->compare(new Math_BigInteger(substr($max, 1), 256)) > 0 ? ord($max[0]) - 1 : ord($max[0]); if (!$crypt_random) { $msb = chr(mt_rand(0, $leading)); } else { $cutoff = floor(0xff / $leading) * $leading; while (true) { $msb = ord(crypt_random_string(1)); if ($msb <= $cutoff) { $msb %= $leading; break; } } $msb = chr($msb); } $random = new Math_BigInteger($msb . $random, 256); return $this->_normalize($random->add($min)); }
/** * EMSA-PSS-ENCODE * * See {@link http://tools.ietf.org/html/rfc3447#section-9.1.1 RFC3447#section-9.1.1}. * * @access private * @param String $m * @param Integer $emBits */ function _emsa_pss_encode($m, $emBits) { // if $m is larger than two million terrabytes and you're using sha1, PKCS#1 suggests a "Label too long" error // be output. $emLen = $emBits + 1 >> 3; // ie. ceil($emBits / 8) $sLen = $this->sLen === false ? $this->hLen : $this->sLen; $mHash = $this->hash->hash($m); if ($emLen < $this->hLen + $sLen + 2) { user_error('Encoding error'); return false; } $salt = crypt_random_string($sLen); $m2 = "" . $mHash . $salt; $h = $this->hash->hash($m2); $ps = str_repeat(chr(0), $emLen - $sLen - $this->hLen - 2); $db = $ps . chr(1) . $salt; $dbMask = $this->_mgf1($h, $emLen - $this->hLen - 1); $maskedDB = $db ^ $dbMask; $maskedDB[0] = ~chr(0xff << ($emBits & 7)) & $maskedDB[0]; $em = $maskedDB . $h . chr(0xbc); return $em; }
/** * @param int $byte_len * @return String */ public static function randomBytes($byte_len) { return crypt_random_string($byte_len); }
/** * Initialization * Store the initialization vector because it will be needed for * further decryption. I don't think necessary to have one iv * per server so I don't put the server number in the cookie name. * * @return void */ public function createIV() { if ($this->_useOpenSSL()) { $this->_cookie_iv = openssl_random_pseudo_bytes($this->getIVSize()); } else { $this->_cookie_iv = crypt_random_string($this->getIVSize()); } $GLOBALS['PMA_Config']->setCookie('pma_iv-' . $GLOBALS['server'], base64_encode($this->_cookie_iv)); }
/** * @return string */ public static function createId() { return 'cxn:' . BinHex::bin2hex(crypt_random_string(Constants::CXN_ID_CHARS)); }
public function encrypt_message($plaintext, $use_key = false, $key_length = 32) { if (!$use_key) { if ($this->format == 1) { if (!$this->key_local) { throw new Exception('No encryption key has been set'); } $use_key = $this->key_local; } else { if (!$this->key_remote) { throw new Exception('No encryption key has been set'); } $use_key = $this->key_remote; } } $this->ensure_crypto_loaded(); $rsa = new Crypt_RSA(); if (defined('UDRPC_PHPSECLIB_ENCRYPTION_MODE')) { $rsa->setEncryptionMode(UDRPC_PHPSECLIB_ENCRYPTION_MODE); } $rij = new Crypt_Rijndael(); // Generate Random Symmetric Key $sym_key = crypt_random_string($key_length); if ($this->debug) { $this->log('Unencrypted symmetric key (hex): ' . bin2hex($sym_key)); } // Encrypt Message with new Symmetric Key $rij->setKey($sym_key); $ciphertext = $rij->encrypt($plaintext); if ($this->debug) { $this->log('Encrypted ciphertext (hex): ' . bin2hex($ciphertext)); } $ciphertext = base64_encode($ciphertext); // Encrypt the Symmetric Key with the Asymmetric Key $rsa->loadKey($use_key); $sym_key = $rsa->encrypt($sym_key); if ($this->debug) { $this->log('Encrypted symmetric key (hex): ' . bin2hex($sym_key)); } // Base 64 encode the symmetric key for transport $sym_key = base64_encode($sym_key); if ($this->debug) { $this->log('Encrypted symmetric key (b64): ' . $sym_key); } $len = str_pad(dechex(strlen($sym_key)), 3, '0', STR_PAD_LEFT); // Zero pad to be sure. // 16 characters of hex is enough for the payload to be to 16 exabytes (giga < tera < peta < exa) of data $cipherlen = str_pad(dechex(strlen($ciphertext)), 16, '0', STR_PAD_LEFT); // Concatenate the length, the encrypted symmetric key, and the message return $len . $sym_key . $cipherlen . $ciphertext; }
/** * Sends Binary Packets * * Returns true on success, false on failure. * * @see Net_SSH1::_get_binary_packet() * * @param String $data * * @return Boolean * @access private */ function _send_binary_packet($data) { if (feof($this->fsock)) { //user_error('connection closed prematurely'); return false; } $length = strlen($data) + 4; $padding = crypt_random_string(8 - ($length & 7)); $orig = $data; $data = $padding . $data; $data .= pack('N', $this->_crc($data)); if ($this->crypto !== false) { $data = $this->crypto->encrypt($data); } $packet = pack('Na*', $length, $data); $start = strtok(microtime(), ' ') + strtok(''); // http://php.net/microtime#61838 $result = strlen($packet) == fputs($this->fsock, $packet); $stop = strtok(microtime(), ' ') + strtok(''); if (defined('NET_SSH1_LOGGING')) { $temp = isset($this->protocol_flags[ord($orig[0])]) ? $this->protocol_flags[ord($orig[0])] : 'UNKNOWN'; $temp = '-> ' . $temp . ' (' . round($stop - $start, 4) . 's)'; $this->_append_log($temp, $orig); } return $result; }
public function encrypt_message($plaintext, $use_key = false, $key_length = 150) { if (!$use_key && !$this->key_local) { throw new Exception('No encryption key has been set'); } if (!$use_key) { $use_key = $this->key_local; } $this->ensure_crypto_loaded(); $rsa = new Crypt_RSA(); $rij = new Crypt_Rijndael(); // Generate Random Symmetric Key $sym_key = crypt_random_string($key_length); // Encrypt Message with new Symmetric Key $rij->setKey($sym_key); $ciphertext = $rij->encrypt($plaintext); $ciphertext = base64_encode($ciphertext); // Encrypted the Symmetric Key with the Asymmetric Key $rsa->loadKey($use_key); $sym_key = $rsa->encrypt($sym_key); // Base 64 encode the symmetric key for transport $sym_key = base64_encode($sym_key); $len = str_pad(dechex(strlen($sym_key)), 3, '0', STR_PAD_LEFT); // Zero pad to be sure. // 16 characters of hex is enough for the payload to be to 16 exabytes (giga < tera < peta < exa) of data $cipherlen = str_pad(dechex(strlen($ciphertext)), 16, '0', STR_PAD_LEFT); // Concatenate the length, the encrypted symmetric key, and the message return $len . $sym_key . $cipherlen . $ciphertext; }
public function restore_backup($backup_file, $type, $info, $last_one = false) { if ('more' == $type) { $this->skin->feedback('not_possible'); return; } global $wp_filesystem, $updraftplus_addons_migrator, $updraftplus; $updraftplus->log("restore_backup(backup_file={$backup_file}, type={$type}, info=" . serialize($info) . ", last_one={$last_one})"); $updraft_dir = $updraftplus->backups_dir_location(); $get_dir = empty($info['path']) ? '' : $info['path']; $wp_filesystem_dir = $this->get_wp_filesystem_dir($get_dir); if ($wp_filesystem_dir === false) { return false; } if (empty($this->abspath)) { $this->abspath = trailingslashit($wp_filesystem->abspath()); } @set_time_limit(1800); /* TODO: - The backup set may no longer be in the DB - a restore may have over-written it. - UD might be installed, but not active. Test that too. (All combinations need testing - new/old UD vers, logged-in/not, etc.). - logging - authorisation on the AJAX call, given that our login may not even be valid any more. - pass on the WP filesystem credentials somehow - they have been POSTed, and should be included in what's POSTed back. - the restore function wants to know the UD version the backup set came from - the restore function wants to know whether we're restoring an individual blog into a multisite - the restore function has some things only done the first time, which isn't directly tracked (uses internal state instead, which won't work over AJAX) - how to handle/set this->delete - how to show the final result - how to do the clear-up of restored stuff in the restore function - remember, we need to do unauthenticated AJAX, as the authentication is happening via a different means. Use a separate procedure from the usual one (and no nonce, as login status may have changed). */ if (defined('UPDRAFTPLUS_EXPERIMENTAL_AJAX_RESTORE') && UPDRAFTPLUS_EXPERIMENTAL_AJAX_RESTORE && 'uploads' == $type) { // Read this each time, as we don't know what might have been done in the mean-time (specifically with UD being replaced by a different UD from a backup). Of course, we know what the currently running process is capable of. if (file_exists(UPDRAFTPLUS_DIR . '/updraftplus.php') && ($fp = fopen(UPDRAFTPLUS_DIR . '/updraftplus.php', 'r'))) { $file_data = fread($fp, 1024); if (preg_match("/Version: ([\\d\\.]+)(\r|\n)/", $file_data, $matches)) { $ud_version = $matches[1]; } fclose($fp); } if (!empty($ud_version) && $this->can_version_ajax_restore($ud_version) && !empty($this->ud_backup_info['timestamp'])) { $nonce = $updraftplus->nonce; if (!function_exists('crypt_random_string')) { $updraftplus->ensure_phpseclib('Crypt_Random', 'Crypt/Random'); } $this->ajax_restore_auth_code = bin2hex(crypt_random_string(32)); // TODO: Delete this when done, to prevent abuse update_site_option('updraft_ajax_restore_' . $nonce, $this->ajax_restore_auth_code . ':' . time()); $this->add_ajax_restore_admin_footer(); $print_last_one = $last_one ? "1" : "0"; // TODO: Also want the timestamp // We don't bother to include info, as that is backup-independent information that can be re-created when needed echo '<p style="margin: 0px 0px;" class="updraft-ajaxrestore" data-type="' . $type . '" data-lastone="' . $print_last_one . '" data-backupfile="' . esc_attr($backup_file) . '">' . "\n"; $updraftplus->log("Deferring handling of uploads ({$backup_file})"); echo "{$backup_file}: " . '<span class="deferprogress">' . __('Deferring...', 'updraftplus') . '</span>'; echo '</p>'; return true; } } // This returns the wp_filesystem path $working_dir = $this->unpack_package($backup_file, $this->delete, $type); if (is_wp_error($working_dir)) { return $working_dir; } $working_dir_localpath = WP_CONTENT_DIR . '/upgrade/' . basename($working_dir); @set_time_limit(1800); // We copy the variable because we may be importing with a different prefix (e.g. on multisite imports of individual blog data) $import_table_prefix = $updraftplus->get_table_prefix(false); if (is_multisite() && $this->ud_backup_is_multisite === 0 && ('plugins' == $type || 'themes' == $type || 'uploads' == $type && !empty($updraftplus_addons_migrator->new_blogid))) { # Migrating a single site into a multisite if ('plugins' == $type || 'themes' == $type) { $move_from = $this->get_first_directory($working_dir, array(basename($info['path']), $type)); $this->skin->feedback('moving_backup'); // Only move in entities that are not already there (2) $new_move_failed = false === $move_from ? true : false; if (false === $new_move_failed) { $move_in = $this->move_backup_in($move_from, trailingslashit($wp_filesystem_dir), 2, array(), $type, true); if (is_wp_error($move_in)) { return $move_in; } if (!$move_in) { $new_move_failed = true; } } if ($new_move_failed) { return new WP_Error('new_move_failed', $this->strings['new_move_failed']); } @$wp_filesystem->delete($move_from); } else { // Uploads $this->skin->feedback('moving_old'); switch_to_blog($updraftplus_addons_migrator->new_blogid); $ud = wp_upload_dir(); $wpud = $ud['basedir']; $fsud = trailingslashit($wp_filesystem->find_folder($wpud)); restore_current_blog(); // TODO: What is below will move the entire uploads directory if blog id is 1. Detect this situation. (Can that happen? We created a new blog, so should not be possible). // TODO: the upload dir is not necessarily reachable through wp_filesystem - try ordinary method instead if (is_string($fsud)) { // This is not expected to exist, since we created a new blog if ($wp_filesystem->exists($fsud) && !$wp_filesystem->move($fsud, untrailingslashit($fsud) . "-old", true)) { return new WP_Error('old_move_failed', $this->strings['old_move_failed']); } $this->skin->feedback('moving_backup'); $move_from = $this->get_first_directory($working_dir, array(basename($info['path']), $type)); if (!$wp_filesystem->move($move_from, $fsud, true)) { return new WP_Error('new_move_failed', $this->strings['new_move_failed']); } @$wp_filesystem->delete($move_from); } else { return new WP_Error('new_move_failed', $this->strings['new_move_failed']); } } } elseif ('db' == $type) { // $import_table_prefix is received as a reference $rdb = $this->restore_backup_db($working_dir, $working_dir_localpath, $import_table_prefix); if (false === $rdb || is_wp_error($rdb)) { return $rdb; } } elseif ('others' == $type) { $dirname = basename($info['path']); # For foreign 'Simple Backup', we need to keep going down until we find wp-content if (empty($this->ud_foreign)) { $move_from = $working_dir; } else { $move_from = $this->search_for_folder('wp-content', $working_dir); if (!is_string($move_from)) { return new WP_Error('not_found', __('The WordPress content folder (wp-content) was not found in this zip file.', 'updraftplus')); } } // In this special case, the backup contents are not in a folder, so it is not simply a case of moving the folder around, but rather looping over all that we find # On subsequent archives of a multi-archive set, don't move anything; but do on the first $preserve_existing = isset($this->been_restored['others']) ? 3 : 1; $this->move_backup_in($move_from, trailingslashit($wp_filesystem_dir), $preserve_existing, array('plugins', 'themes', 'uploads', 'upgrade'), 'others'); $this->been_restored['others'] = true; } else { // Default action: used for plugins, themes and uploads (and wpcore, via a filter) // Multi-archive sets: we record what we've already begun on, and on subsequent runs, copy in instead of replacing $movedin = apply_filters('updraftplus_restore_movein_' . $type, $working_dir, $this->abspath, $wp_filesystem_dir); // A filter, to allow add-ons to perform the install of non-standard entities, or to indicate that it's not possible if (false === $movedin) { $this->skin->feedback('not_possible'); } elseif (is_wp_error($movedin)) { return $movedin; } elseif (true !== $movedin) { # On the first time, create the -old directory in updraft_dir # (Old style: On the first time, move the existing data to -old) if (!isset($this->been_restored[$type])) { # First, try filesystem-level move $old_dir = $updraft_dir . '/' . $type . '-old'; if (is_dir($old_dir)) { $updraftplus->log_e('%s: This directory already exists, and will be replaced', $old_dir); $updraftplus->remove_local_directory($old_dir); } $move_old_destination = 0; if (@mkdir($old_dir)) { $updraftplus->log("Moving old data: filesystem method / updraft_dir is potentially possible"); $move_old_destination = 1; } # Try wp_filesystem instead if ($wp_filesystem->exists($wp_filesystem_dir . "-old")) { // Is better to warn and delete the backup than abort mid-restore and leave inconsistent site $updraftplus->log_e('%s: This directory already exists, and will be replaced', $wp_filesystem_dir . "-old"); # In theory, supply true as the 3rd parameter of true achieves this; in practice, not always so (leads to support requests) $wp_filesystem->delete($wp_filesystem_dir . "-old", true); if ($wp_filesystem->exists($wp_filesystem_dir . "-old")) { $updraftplus->log("Failed to remove existing directory (" . $wp_filesystem_dir . "-old"); $failed_to_remove = true; #return new WP_Error('old_move_failed', $this->strings['old_move_failed']); } } if (empty($failed_to_remove) && @$wp_filesystem->mkdir($wp_filesystem_dir . "-old")) { $updraftplus->log("Moving old data: can potentially use wp_filesystem method / -old"); $move_old_destination += 2; } if (0 == $move_old_destination) { $updraftplus->log_e("File permissions do not allow the old data to be moved and retained; instead, it will be deleted."); } $this->skin->feedback('moving_old'); # First, try direct filesystem method into updraft_dir if (1 == $move_old_destination % 2) { # The final 'true' forces direct filesystem access $move_old = @$this->move_backup_in($get_dir, $updraft_dir . '/' . $type . '-old/', 3, array(), $type, false, true); if (is_wp_error($move_old)) { $updraftplus->log_wp_error($move_old); } } # Try wp_filesystem method into -old if that failed if (2 >= $move_old_destination && (0 == $move_old_destination % 2 || !empty($move_old) && is_wp_error($move_old))) { $move_old = @$this->move_backup_in($wp_filesystem_dir, $wp_filesystem_dir . "-old/", 3, array(), $type); #if (is_wp_error($move_old)) return $move_old; if (is_wp_error($move_old)) { $updraftplus->log_wp_error($move_old); } // if ( !$wp_filesystem->move($wp_filesystem_dir, $wp_filesystem_dir."-old", false) ) { // return new WP_Error('old_move_failed', $this->strings['old_move_failed']); // } } # Finally, when all else fails, nuke it if (0 == $move_old_destination || !empty($move_old) && is_wp_error($move_old)) { $updraftplus->log("{$type}: {$wp_filesystem_dir}: deleting contents (as attempts to copy failed)"); $del_files = $wp_filesystem->dirlist($wp_filesystem_dir, true, false); if (empty($del_files)) { $del_files = array(); } foreach ($del_files as $file => $filestruc) { if (empty($file)) { continue; } $wp_filesystem->delete($wp_filesystem_dir . '/' . $file, true); } } } # For foreign 'Simple Backup', we need to keep going down until we find wp-content if (empty($this->ud_foreign)) { $working_dir_use = $working_dir; } else { $working_dir_use = $this->search_for_folder('wp-content', $working_dir); if (!is_string($working_dir_use)) { return new WP_Error('not_found', __('The WordPress content folder (wp-content) was not found in this zip file.', 'updraftplus')); } } // The backup may not actually have /$type, since that is info from the present site $move_from = $this->get_first_directory($working_dir_use, array(basename($info['path']), $type)); if (false === $move_from) { return new WP_Error('new_move_failed', $this->strings['new_move_failed']); } $this->skin->feedback('moving_backup'); // Old-style // if (!isset($this->been_restored[$type])) { // if (!$wp_filesystem->move($move_from, $wp_filesystem_dir, true) ) { // return new WP_Error('new_move_failed', $this->strings['new_move_failed']); // } // } else { $move_in = $this->move_backup_in($move_from, trailingslashit($wp_filesystem_dir), 3, array(), $type); if (is_wp_error($move_in)) { return $move_in; } if (!$move_in) { return new WP_Error('new_move_failed', $this->strings['new_move_failed']); } $wp_filesystem->rmdir($move_from); // } } $this->been_restored[$type] = true; } $attempt_delete = true; if (!empty($this->ud_foreign) && !$last_one) { $attempt_delete = false; } // Non-recursive, so the directory needs to be empty if ($attempt_delete) { $this->skin->feedback('cleaning_up'); } if ($attempt_delete && !$wp_filesystem->delete($working_dir, !empty($this->ud_foreign))) { # TODO: Can remove this after 1-Jan-2015; or at least, make it so that it requires the version number to be present. $fixed_it_now = false; # Deal with a corner-case in version 1.8.5 if ('uploads' == $type && (empty($this->created_by_version) || version_compare($this->created_by_version, '1.8.5', '>=') && version_compare($this->created_by_version, '1.8.8', '<'))) { $updraftplus->log("Clean-up failed with uploads: will attempt 1.8.5-1.8.7 fix (" . $this->created_by_version . ")"); $move_in = @$this->move_backup_in(dirname($move_from), trailingslashit($wp_filesystem_dir), 3, array(), $type); $updraftplus->log("Result: " . serialize($move_in)); if ($wp_filesystem->delete($working_dir)) { $fixed_it_now = true; } } if (!$fixed_it_now) { $updraftplus->log_e('Error: %s', $this->strings['delete_failed'] . ' (' . $working_dir . ')'); # List contents // No need to make this a restoration-aborting error condition - it's not #return new WP_Error('delete_failed', $this->strings['delete_failed'].' ('.$working_dir.')'); $dirlist = $wp_filesystem->dirlist($working_dir, true, true); if (is_array($dirlist)) { echo __('Files found:', 'updraftplus') . '<br><ul style="list-style: disc inside;">'; foreach ($dirlist as $name => $struc) { echo "<li>" . htmlspecialchars($name) . "</li>"; } echo '</ul>'; } else { $updraftplus->log_e('Unable to enumerate files in that directory.'); } } } # Permissions changes (at the top level - i.e. this does not apply if using recursion) are now *additive* - i.e. there's no danger of permissions being removed from what's on-disk switch ($type) { case 'wpcore': $this->chmod_if_needed($wp_filesystem_dir, FS_CHMOD_DIR, false, $wp_filesystem); // In case we restored a .htaccess which is incorrect for the local setup $this->flush_rewrite_rules(); break; case 'uploads': $this->chmod_if_needed($wp_filesystem_dir, FS_CHMOD_DIR, false, $wp_filesystem); break; case 'themes': // Cherry Framework needs its cache files removing after migration if ((empty($this->old_siteurl) || $this->old_siteurl != $this->our_siteurl) && function_exists('glob')) { $cherry_child = glob(WP_CONTENT_DIR . '/themes/theme*'); if (is_array($cherry_child)) { foreach ($cherry_child as $theme) { if (file_exists($theme . '/style.less.cache')) { unlink($theme . '/style.less.cache'); } if (file_exists($theme . '/bootstrap/less/bootstrap.less.cache')) { unlink($theme . '/bootstrap/less/bootstrap.less.cache'); } } } } break; case 'db': if (function_exists('wp_cache_flush')) { wp_cache_flush(); } do_action('updraftplus_restored_db', array('expected_oldsiteurl' => $this->old_siteurl, 'expected_oldhome' => $this->old_home, 'expected_oldcontent' => $this->old_content), $import_table_prefix); $this->flush_rewrite_rules(); # N.B. flush_rewrite_rules() causes $wp_rewrite to become up to date again if (function_exists('apache_get_modules')) { global $wp_rewrite; $mods = apache_get_modules(); if (($wp_rewrite->using_mod_rewrite_permalinks() && in_array('core', $mods) || in_array('http_core', $mods)) && !in_array('mod_rewrite', $mods)) { $updraftplus->log("Using Apache, with permalinks (" . get_option('permalink_structure') . ") but no mod_rewrite enabled - enable it to make your permalinks work"); $warn_no_rewrite = sprintf(__('You are using the %s webserver, but do not seem to have the %s module loaded.', 'updraftplus'), 'Apache', 'mod_rewrite') . ' ' . sprintf(__('You should enable %s to make your pretty permalinks (e.g. %s) work', 'updraftplus'), 'mod_rewrite', 'http://example.com/my-page/'); echo '<p><strong>' . htmlspecialchars($warn_no_rewrite) . '</strong></p>'; } } break; default: $this->chmod_if_needed($wp_filesystem_dir, FS_CHMOD_DIR, false, $wp_filesystem); } # db was already done if ('db' != $type) { do_action('updraftplus_restored_' . $type); } return true; }
*/ ini_set('mbstring.internal_encoding', 'UTF-8'); ini_set('mbstring.func_overload', 7); header('Content-Type: text/html; charset=UTF-8'); //开始处理数据 @($isforceEncrypt = $_POST["forceEncrypt"]); //用于跨CA的数据跳转 @($action = $_POST["action"]); @($interfaceData = $_POST["data"]); if ($action === "GetPublishX509") { GetPublishX509(); echo ','; echo create_guid(); } else { if ($action === "UILoginStart") { $_SESSION['AESKEY'] = bin2hex(crypt_random_string(8)); echo $_SESSION['AESKEY']; } else { if ($action === "UIdoLogin") { UIdoLogin($interfaceData); } else { if ($action === "doGetCertStep2") { doGetCertStep2($interfaceData); } else { if ($action === "doGetCertStep4") { doGetCertStep4($interfaceData); } else { if ($action === "UIFinishLogin") { UIFinishLogin(); } else { if ($action === "deleteSignCert") {
public function restore_backup($backup_file, $type, $info, $last_one = false) { if ('more' == $type) { $this->skin->feedback('not_possible'); return; } global $wp_filesystem, $updraftplus_addons_migrator, $updraftplus; $updraftplus->log("restore_backup(backup_file={$backup_file}, type={$type}, info=" . serialize($info) . ", last_one={$last_one})"); $get_dir = empty($info['path']) ? '' : $info['path']; if (false === ($wp_filesystem_dir = $this->get_wp_filesystem_dir($get_dir))) { return false; } if (empty($this->abspath)) { $this->abspath = trailingslashit($wp_filesystem->abspath()); } @set_time_limit(1800); /* TODO: - The backup set may no longer be in the DB - a restore may have over-written it. - UD might be installed, but not active. Test that too. (All combinations need testing - new/old UD vers, logged-in/not, etc.). - logging - authorisation on the AJAX call, given that our login may not even be valid any more. - pass on the WP filesystem credentials somehow - they have been POSTed, and should be included in what's POSTed back. - the restore function wants to know the UD version the backup set came from - the restore function wants to know whether we're restoring an individual blog into a multisite - the restore function has some things only done the first time, which isn't directly tracked (uses internal state instead, which won't work over AJAX) - how to handle/set this->delete - how to show the final result - how to do the clear-up of restored stuff in the restore function - remember, we need to do unauthenticated AJAX, as the authentication is happening via a different means. Use a separate procedure from the usual one (and no nonce, as login status may have changed). */ if (defined('UPDRAFTPLUS_EXPERIMENTAL_AJAX_RESTORE') && UPDRAFTPLUS_EXPERIMENTAL_AJAX_RESTORE && 'uploads' == $type) { // Read this each time, as we don't know what might have been done in the mean-time (specifically with UD being replaced by a different UD from a backup). Of course, we know what the currently running process is capable of. if (file_exists(UPDRAFTPLUS_DIR . '/updraftplus.php') && ($fp = fopen(UPDRAFTPLUS_DIR . '/updraftplus.php', 'r'))) { $file_data = fread($fp, 1024); if (preg_match("/Version: ([\\d\\.]+)(\r|\n)/", $file_data, $matches)) { $ud_version = $matches[1]; } fclose($fp); } if (!empty($ud_version) && $this->can_version_ajax_restore($ud_version) && !empty($this->ud_backup_info['timestamp'])) { $nonce = $updraftplus->nonce; if (!function_exists('crypt_random_string')) { $updraftplus->ensure_phpseclib('Crypt_Random', 'Crypt/Random'); } $this->ajax_restore_auth_code = bin2hex(crypt_random_string(32)); // TODO: Delete this when done, to prevent abuse update_site_option('updraft_ajax_restore_' . $nonce, $this->ajax_restore_auth_code . ':' . time()); $this->add_ajax_restore_admin_footer(); $print_last_one = $last_one ? "1" : "0"; // TODO: Also want the timestamp // We don't bother to include info, as that is backup-independent information that can be re-created when needed echo '<p style="margin: 0px 0px;" class="updraft-ajaxrestore" data-type="' . $type . '" data-lastone="' . $print_last_one . '" data-backupfile="' . esc_attr($backup_file) . '">' . "\n"; $updraftplus->log("Deferring handling of uploads ({$backup_file})"); echo "{$backup_file}: " . '<span class="deferprogress">' . __('Deferring...', 'updraftplus') . '</span>'; echo '</p>'; return true; } } // This returns the wp_filesystem path $working_dir = $this->unpack_package($backup_file, $this->delete, $type); if (is_wp_error($working_dir)) { return $working_dir; } $working_dir_localpath = WP_CONTENT_DIR . '/upgrade/' . basename($working_dir); @set_time_limit(1800); // We copy the variable because we may be importing with a different prefix (e.g. on multisite imports of individual blog data) $import_table_prefix = $updraftplus->get_table_prefix(false); $now_done = apply_filters('updraftplus_pre_restore_move_in', false, $type, $working_dir, $info, $this->ud_backup_info, $this, $wp_filesystem_dir); if (is_wp_error($now_done)) { return $now_done; } // A slightly ugly way of getting a particular result back if (is_string($now_done)) { $wp_filesystem_dir = $now_done; $now_done = false; $do_not_move_old = true; } if (!$now_done) { if ('db' == $type) { // $import_table_prefix is received as a reference $rdb = $this->restore_backup_db($working_dir, $working_dir_localpath, $import_table_prefix); if (false === $rdb || is_wp_error($rdb)) { return $rdb; } } elseif ('others' == $type) { $dirname = basename($info['path']); # For foreign 'Simple Backup', we need to keep going down until we find wp-content if (empty($this->ud_foreign)) { $move_from = $working_dir; } else { $move_from = $this->search_for_folder('wp-content', $working_dir); if (!is_string($move_from)) { return new WP_Error('not_found', __('The WordPress content folder (wp-content) was not found in this zip file.', 'updraftplus')); } } // In this special case, the backup contents are not in a folder, so it is not simply a case of moving the folder around, but rather looping over all that we find // On subsequent archives of a multi-archive set, don't move anything; but do on the first $preserve_existing = isset($this->been_restored['others']) ? self::MOVEIN_COPY_IN_CONTENTS : self::MOVEIN_MAKE_BACKUP_OF_EXISTING; $preserve_existing = apply_filters('updraft_move_others_preserve_existing', $preserve_existing, $this->been_restored, $this->ud_restore_options, $this->ud_backup_info); $new_move_from = apply_filters('updraft_restore_backup_move_from', $move_from, 'others', $this->ud_restore_options, $this->ud_backup_info); if ($new_move_from != $move_from && 0 === strpos($new_move_from, $move_from)) { $new_suffix = substr($new_move_from, strlen($move_from)); $wp_filesystem_dir .= $new_suffix; $move_from = $new_move_from; } $move_in = $this->move_backup_in($move_from, trailingslashit($wp_filesystem_dir), $preserve_existing, array('plugins', 'themes', 'uploads', 'upgrade'), 'others'); if (is_wp_error($move_in)) { return $move_in; } if (!$move_in) { return new WP_Error('new_move_failed', $this->strings['new_move_failed']); } $this->been_restored['others'] = true; } else { // Default action: used for plugins, themes and uploads (and wpcore, via a filter) // Multi-archive sets: we record what we've already begun on, and on subsequent runs, copy in instead of replacing $movedin = apply_filters('updraftplus_restore_movein_' . $type, $working_dir, $this->abspath, $wp_filesystem_dir); // A filter, to allow add-ons to perform the install of non-standard entities, or to indicate that it's not possible if (false === $movedin) { $this->skin->feedback('not_possible'); } elseif (is_wp_error($movedin)) { return $movedin; } elseif (true !== $movedin) { // We get the directory to move from early, in case there is a problem with the backup that affects the result - we want to detect that before moving existing data out of the way $short_circuit = false; // For foreign 'Simple Backup', we need to keep going down until we find wp-content if (empty($this->ud_foreign)) { $working_dir_use = $working_dir; } else { $working_dir_use = $this->search_for_folder('wp-content', $working_dir); if (!is_string($working_dir_use)) { if (empty($this->ud_foreign) || !apply_filters('updraftplus_foreign_allow_missing_entity', false, $type, $this->ud_foreign)) { return new WP_Error('not_found', __('The WordPress content folder (wp-content) was not found in this zip file.', 'updraftplus')); } else { $short_circuit = true; } } } // The backup may not actually have /$type, since that is info from the present site $move_from = $this->get_first_directory($working_dir_use, array(basename($info['path']), $type)); if (false !== $move_from) { $move_from = apply_filters('updraft_restore_backup_move_from', $move_from, $type, $this->ud_restore_options, $this->ud_backup_info); } if (false === $move_from) { if (!empty($this->ud_foreign) && !apply_filters('updraftplus_foreign_allow_missing_entity', false, $type, $this->ud_foreign)) { return new WP_Error('new_move_failed', $this->strings['new_move_failed']); } } // On the first time, create the -old directory in updraft_dir // (Old style was: On the first time, move the existing data to -old) if (!isset($this->been_restored[$type]) && empty($do_not_move_old)) { $this->move_existing_to_old($type, $get_dir, $wp_filesystem, $wp_filesystem_dir); } if (empty($short_circuit)) { if (false === $move_from) { if (!empty($this->ud_foreign) && !apply_filters('updraftplus_foreign_allow_missing_entity', false, $type, $this->ud_foreign)) { return new WP_Error('new_move_failed', $this->strings['new_move_failed']); } } else { $this->skin->feedback('moving_backup'); $move_in = $this->move_backup_in($move_from, trailingslashit($wp_filesystem_dir), self::MOVEIN_COPY_IN_CONTENTS, array(), $type); if (is_wp_error($move_in)) { return $move_in; } if (!$move_in) { return new WP_Error('new_move_failed', $this->strings['new_move_failed']); } $wp_filesystem->rmdir($move_from); } } } $this->been_restored[$type] = true; } } $attempt_delete = true; if (!empty($this->ud_foreign) && !$last_one) { $attempt_delete = false; } // Non-recursive, so the directory needs to be empty if ($attempt_delete) { $this->skin->feedback('cleaning_up'); } if ($attempt_delete) { if (!empty($do_not_move_old)) { @$wp_filesystem->delete($working_dir . '/' . $type); } // Foreign backups can contain extra data and thus leave stuff behind, thus causing errors $recurse = empty($this->ud_foreign) ? false : true; $recurse = apply_filters('updraftplus_restore_delete_recursive', $recurse, $this->ud_foreign, $this->ud_restore_options, $type); if (!$wp_filesystem->delete($working_dir, $recurse)) { # TODO: Can remove this after 1-Jan-2015; or at least, make it so that it requires the version number to be present. $fixed_it_now = false; # Deal with a corner-case in version 1.8.5 if ('uploads' == $type && (empty($this->created_by_version) || version_compare($this->created_by_version, '1.8.5', '>=') && version_compare($this->created_by_version, '1.8.8', '<'))) { $updraftplus->log("Clean-up failed with uploads: will attempt 1.8.5-1.8.7 fix (" . $this->created_by_version . ")"); $move_in = @$this->move_backup_in(dirname($move_from), trailingslashit($wp_filesystem_dir), 3, array(), $type); $updraftplus->log("Result: " . serialize($move_in)); if ($wp_filesystem->delete($working_dir)) { $fixed_it_now = true; } } if (!$fixed_it_now) { $updraftplus->log_e('Error: %s', $this->strings['delete_failed'] . ' (' . $working_dir . ')'); # List contents // No need to make this a restoration-aborting error condition - it's not #return new WP_Error('delete_failed', $this->strings['delete_failed'].' ('.$working_dir.')'); $dirlist = $wp_filesystem->dirlist($working_dir, true, true); if (is_array($dirlist)) { echo __('Files found:', 'updraftplus') . '<br><ul style="list-style: disc inside;">'; foreach ($dirlist as $name => $struc) { echo "<li>" . htmlspecialchars($name) . "</li>"; } echo '</ul>'; } else { $updraftplus->log_e('Unable to enumerate files in that directory.'); } } } } # Permissions changes (at the top level - i.e. this does not apply if using recursion) are now *additive* - i.e. there's no danger of permissions being removed from what's on-disk switch ($type) { case 'wpcore': $this->chmod_if_needed($wp_filesystem_dir, FS_CHMOD_DIR, false, $wp_filesystem); // In case we restored a .htaccess which is incorrect for the local setup $this->flush_rewrite_rules(); break; case 'uploads': $this->chmod_if_needed($wp_filesystem_dir, FS_CHMOD_DIR, false, $wp_filesystem); break; case 'themes': // Cherry Framework needs its cache files removing after migration if ((empty($this->old_siteurl) || $this->old_siteurl != $this->our_siteurl) && function_exists('glob')) { $cherry_child = glob(WP_CONTENT_DIR . '/themes/theme*'); if (is_array($cherry_child)) { foreach ($cherry_child as $theme) { if (file_exists($theme . '/style.less.cache')) { unlink($theme . '/style.less.cache'); } if (file_exists($theme . '/bootstrap/less/bootstrap.less.cache')) { unlink($theme . '/bootstrap/less/bootstrap.less.cache'); } } } } break; case 'db': if (function_exists('wp_cache_flush')) { wp_cache_flush(); } do_action('updraftplus_restored_db', array('expected_oldsiteurl' => $this->old_siteurl, 'expected_oldhome' => $this->old_home, 'expected_oldcontent' => $this->old_content), $import_table_prefix); # N.B. flush_rewrite_rules() causes $wp_rewrite to become up to date again - important for the no_mod_rewrite() call $this->flush_rewrite_rules(); if ($updraftplus->mod_rewrite_unavailable()) { $updraftplus->log("Using Apache, with permalinks (" . get_option('permalink_structure') . ") but no mod_rewrite enabled - enable it to make your permalinks work"); $warn_no_rewrite = sprintf(__('You are using the %s webserver, but do not seem to have the %s module loaded.', 'updraftplus'), 'Apache', 'mod_rewrite') . ' ' . sprintf(__('You should enable %s to make any pretty permalinks (e.g. %s) work', 'updraftplus'), 'mod_rewrite', 'http://example.com/my-page/'); echo '<p><strong>' . htmlspecialchars($warn_no_rewrite) . '</strong></p>'; } break; default: $this->chmod_if_needed($wp_filesystem_dir, FS_CHMOD_DIR, false, $wp_filesystem); } # db was already done if ('db' != $type) { do_action('updraftplus_restored_' . $type); } return true; }
/** * Generates a random BigInteger * * Byte length is equal to $length. Uses crypt_random if it's loaded and mt_rand if it's not. * * @param int $length * @return Math_BigInteger * @access private */ function _random_number_helper($size) { if (function_exists('crypt_random_string')) { $random = crypt_random_string($size); } else { $random = ''; if ($size & 1) { $random .= chr(mt_rand(0, 255)); } $blocks = $size >> 1; for ($i = 0; $i < $blocks; ++$i) { // mt_rand(-2147483648, 0x7FFFFFFF) always produces -2147483648 on some systems $random .= pack('n', mt_rand(0, 0xffff)); } } return new Math_BigInteger($random, 256); }
/** * Build the user authorisation URL * @return string */ public function getAuthoriseUrl() { /* Generate a random key to be passed to Dropbox and stored in session to be checked to prevent CSRF Uses OpenSSL or Mcrypt or defaults to pure PHP implementaion if neither are available. */ global $updraftplus; if (!function_exists('crypt_random_string')) { $updraftplus->ensure_phpseclib('Crypt_Random', 'Crypt/Random'); } $CSRF = base64_encode(crypt_random_string(16)); $this->storage->set($CSRF, 'CSRF'); // Prepare request parameters /* For OAuth v2 Dropbox needs to use a authorisation url that matches one that is set inside the Dropbox developer console. In order to check this it needs the client ID for the OAuth v2 app This will use the default one unless the user is using their own Dropbox App For users that use their own Dropbox App there is also no need to provide the callbackhome as part of the CSRF as there is no need to go to auth.updraftplus.com also the redirect uri can then be set to the home as default Check if the key has dropbox: if so then remove it to stop the request from being invalid */ $appkey = $this->storage->get('appkey'); if (!empty($appkey) && 'dropbox:' == substr($appkey, 0, 8)) { $key = substr($appkey, 8); } else { if (!empty($appkey)) { $key = $appkey; } } $params = array('client_id' => empty($key) ? $this->oauth2_id : $key, 'response_type' => 'code', 'redirect_uri' => empty($key) ? $this->callback : $this->callbackhome, 'state' => empty($key) ? $CSRF . $this->callbackhome : $CSRF); // Build the URL and redirect the user $query = '?' . http_build_query($params, '', '&'); $url = self::WEB_URL . self::AUTHORISE_METHOD . $query; return $url; }
/** * Sends Binary Packets * * See '6. Binary Packet Protocol' of rfc4253 for more info. * * @param String $data * @param optional String $logged * @see Net_SSH2::_get_binary_packet() * @return Boolean * @access private */ function _send_binary_packet($data, $logged = null) { if (!is_resource($this->fsock) || feof($this->fsock)) { user_error('Connection closed prematurely'); $this->bitmap = 0; return false; } //if ($this->compress) { // // the -4 removes the checksum: // // http://php.net/function.gzcompress#57710 // $data = substr(gzcompress($data), 0, -4); //} // 4 (packet length) + 1 (padding length) + 4 (minimal padding amount) == 9 $packet_length = strlen($data) + 9; // round up to the nearest $this->encrypt_block_size $packet_length += ($this->encrypt_block_size - 1) * $packet_length % $this->encrypt_block_size; // subtracting strlen($data) is obvious - subtracting 5 is necessary because of packet_length and padding_length $padding_length = $packet_length - strlen($data) - 5; $padding = crypt_random_string($padding_length); // we subtract 4 from packet_length because the packet_length field isn't supposed to include itself $packet = pack('NCa*', $packet_length - 4, $padding_length, $data . $padding); $hmac = $this->hmac_create !== false ? $this->hmac_create->hash(pack('Na*', $this->send_seq_no, $packet)) : ''; $this->send_seq_no++; if ($this->encrypt !== false) { $packet = $this->encrypt->encrypt($packet); } $packet .= $hmac; $start = strtok(microtime(), ' ') + strtok(''); // http://php.net/microtime#61838 $result = strlen($packet) == fputs($this->fsock, $packet); $stop = strtok(microtime(), ' ') + strtok(''); if (defined('NET_SSH2_LOGGING')) { $current = strtok(microtime(), ' ') + strtok(''); $message_number = isset($this->message_numbers[ord($data[0])]) ? $this->message_numbers[ord($data[0])] : 'UNKNOWN (' . ord($data[0]) . ')'; $message_number = '-> ' . $message_number . ' (since last: ' . round($current - $this->last_packet, 4) . ', network: ' . round($stop - $start, 4) . 's)'; $this->_append_log($message_number, isset($logged) ? $logged : $data); $this->last_packet = $current; } return $result; }
/** * Encrypt data. * * @param mixed $key The list of public keys used to encrypt or a list * of passphrases. * @param mixed $data The data to be PGP encrypted. * @param array $opts Additional options: * - cipher: (integer) Cipher algorithm. * - compress: (integer) Compression algorithm. * * @param Horde_Pgp_Element_Message Encrypted message. */ protected function _encrypt($key, $data, $opts) { $msg = $this->_compressMessageOb($this->_getMessageOb($data), $opts['compress']); /* Following code adapted from OpenPGP_Crypt_Symmetric::encrypt(). */ list($cipher, $key_bytes, $block_bytes) = OpenPGP_Crypt_Symmetric::getCipher($opts['cipher']); $prefix = crypt_random_string($block_bytes); $prefix .= substr($prefix, -2); $to_encrypt = $prefix . $msg->to_bytes(); $mdc = new OpenPGP_ModificationDetectionCodePacket(hash('sha1', $to_encrypt . "Ó", true)); /* This is the symmetric encryption session key. */ $ckey = crypt_random_string($key_bytes); $cipher->setKey($ckey); /* This is the symmetrically encrypted version of plaintext. */ $encrypted = array(new OpenPGP_IntegrityProtectedDataPacket($cipher->encrypt($to_encrypt . $mdc->to_bytes()))); /* Now we need to encrypt the symmetric session key into the various * session key encrypted entities. */ foreach ($key as $k) { /* Symmetric encryption. */ if (is_string($k)) { $s2k = new OpenPGP_S2K(crypt_random_string(8, 2)); // SHA-1 $cipher->setKey($s2k->make_key($k, $key_bytes)); $encrypted[] = new OpenPGP_SymmetricSessionKeyPacket($s2k, $cipher->encrypt(chr($opts['cipher']) . $ckey), $opts['cipher']); continue; } /* Public key encryption. */ switch ($k->algorithm) { case 1: case 2: case 3: $rsa = new OpenPGP_Crypt_RSA($k); $pk = $rsa->public_key(); $pk->setEncryptionMode(CRYPT_RSA_ENCRYPTION_PKCS1); break; case 16: $pk = new Horde_Pgp_Crypt_Elgamal($k); break; } $pk_encrypt = $pk->encrypt(chr($opts['cipher']) . $ckey . pack('n', OpenPGP_Crypt_Symmetric::checksum($ckey))); $esk = array(); foreach (is_array($pk_encrypt) ? $pk_encrypt : array($pk_encrypt) as $val) { $esk[] = pack('n', OpenPGP::bitlength($val)) . $val; } $encrypted[] = new OpenPGP_AsymmetricSessionKeyPacket($k->algorithm, $k->fingerprint(), implode('', $esk)); } return new Horde_Pgp_Element_Message(new OpenPGP_Message(array_reverse($encrypted))); }