public function isAuthenticated($request)
 {
     $currentTime = time();
     if (isset($request[$this->cookieName])) {
         $connection = $request[$this->cookieName]['CON'];
         $timestamp = $request[$this->cookieName]['TM'];
         if ($connection && $timestamp) {
             if ($currentTime - $timestamp < $this->cookieExpireTime) {
                 $temp = Crypto::decrypt($connection, _Key_New);
                 list($username) = explode("|Z|1|Z|", $temp);
                 if ($username) {
                     $connection = Crypto::encrypt(implode("|Z|1|Z|", array($username, time())), _Key_New);
                     $this->setAuthenticated($connection);
                     return true;
                 }
             } else {
                 // Timed-out
                 return false;
             }
         } else {
             // Not Authenticated
             return false;
         }
     }
 }
Beispiel #2
0
 /**
  * Check if a user is logged in
  */
 public static function isLoggedIn()
 {
     if (empty($_COOKIE['s'])) {
         return false;
     } else {
         $str = Crypto::decrypt($_COOKIE['s'], $_SERVER['ENCRYPTION_KEY']);
         $fields = explode(':', $str);
         return $fields[1];
         // return the userid
     }
 }
Beispiel #3
0
 function testSimple()
 {
     $tests = array_merge(array($this->test_data), $this->passwords);
     foreach ($tests as $subject) {
         $enc = Crypto::encrypt($subject, $this->master, 'simple');
         $dec = Crypto::decrypt($enc, $this->master, 'simple');
         $this->assertEqual($dec, $subject, "{$subject}: Encryption failed closed loop");
         $this->assertNotEqual($enc, $subject, 'Data was not encrypted');
         $this->assertNotEqual($enc, false, 'Encryption failed');
         $this->assertNotEqual($dec, false, 'Decryption failed');
         $dec = Crypto::decrypt($enc, $this->master, 'wrong');
         $this->assertNotEqual($dec, $this->test_data, 'Subkeys are broken');
     }
 }
Beispiel #4
0
 /**
  * Decrypt then verify a password
  * 
  * @param string $password          - The user-provided password
  * @param string $stored            - The encrypted password hash
  * @param EncryptionKey $secret_key  - The master key for all passwords
  * @return boolean
  */
 public static function verify(string $password, string $stored, EncryptionKey $secret_key) : bool
 {
     // First let's decrypt the hash
     $hash_str = Crypto::decrypt($stored, $secret_key);
     // Upon successful decryption, verify the password is correct
     $isArgon2 = \hash_equals(CryptoUtil::safeSubstr($hash_str, 0, 9), \Sodium\CRYPTO_PWHASH_STRPREFIX);
     $isScrypt = \hash_equals(CryptoUtil::safeSubstr($hash_str, 0, 3), \Sodium\CRYPTO_PWHASH_SCRYPTSALSA208SHA256_STRPREFIX);
     if ($isArgon2) {
         return \Sodium\crypto_pwhash_str_verify($hash_str, $password);
     } elseif ($isScrypt) {
         return \Sodium\crypto_pwhash_scryptsalsa208sha256_str_verify($hash_str, $password);
     }
     return false;
 }
Beispiel #5
0
 /**
  * Store a value in an encrypted cookie
  * 
  * @param string $name
  * @return mixed (typically an array)
  */
 public function fetch(string $name)
 {
     if (!isset($_COOKIE[$name])) {
         return null;
     }
     try {
         $decrypted = Crypto::decrypt($_COOKIE[$name], $this->key);
         if (empty($decrypted)) {
             return null;
         }
         return \json_decode($decrypted, true);
     } catch (InvalidMessage $e) {
         return null;
     }
 }
Beispiel #6
0
 public function KeyGet($master, $password, $key)
 {
     if ($this->MasterExists($master)) {
         require_once APP_DIR . "/src/Inc/Crypto.php";
         $items = getData("master_" . $master . "_items");
         $pass_salt = getData("master_" . $master . "_password_salt");
         $encrypt_key = $this->master_salt . $password . $pass_salt;
         Crypto::$KEY_BYTE_SIZE = mb_strlen($encrypt_key, '8bit');
         $items = base64_decode(Crypto::decrypt(base64_decode($items), $encrypt_key));
         $items = str_replace("&quot;", "'", $items);
         $items = $items == null ? array() : json_decode($items, true);
         return isset($items[$key]) ? $items[$key] : null;
     } else {
         return false;
     }
 }
Beispiel #7
0
 /**
  * Store a value in an encrypted cookie
  * 
  * @param string $name
  * @return mixed (typically an array)
  */
 public function fetch(string $name)
 {
     if (!isset($_COOKIE[$name])) {
         return null;
     }
     try {
         $stored = $_COOKIE[$name];
         $config = self::getConfig($stored);
         $decrypted = Crypto::decrypt($stored, $this->key, $config->ENCODING);
         if (empty($decrypted)) {
             return null;
         }
         return \json_decode($decrypted->getString(), true);
     } catch (InvalidMessage $e) {
         return null;
     }
 }
 function search($query)
 {
     $c = $this->getConnection();
     // TODO: Include bind information
     $users = array();
     if ($dn = $this->getConfig()->get('bind_dn')) {
         $pw = Crypto::decrypt($this->getConfig()->get('bind_pw'), SECRET_SALT, $this->getConfig()->getNamespace());
         $r = $c->bind($dn, $pw);
         unset($pw);
         if (PEAR::isError($r)) {
             return $users;
         }
     }
     $schema = static::$schemas[$this->getSchema($c)];
     $schema = $schema['user'];
     $r = $c->search($this->getSearchBase(), str_replace('{q}', $query, $schema['search']), array('attributes' => array_filter(flatten(array($schema['first'], $schema['last'], $schema['full'], $schema['phone'], $schema['mobile'], $schema['email'], $schema['username'])))));
     // XXX: Log or return some kind of error?
     if (PEAR::isError($r)) {
         return $users;
     }
     foreach ($r as $e) {
         // Detect first and last name if only full name is given
         if (!($first = $e->getValue($schema['first'])) || !($last = $e->getValue($schema['last']))) {
             $name = new PersonsName($this->_getValue($e, $schema['full']));
             $first = $name->getFirst();
             $last = $name->getLast();
         }
         $users[] = array('username' => $this->_getValue($e, $schema['username']), 'first' => $first, 'last' => $last, 'email' => $this->_getValue($e, $schema['email']), 'phone' => $this->_getValue($e, $schema['phone']), 'mobile' => $this->_getValue($e, $schema['mobile']), 'backend' => static::$id);
     }
     return $users;
 }
Beispiel #9
0
 function to_php($value)
 {
     return Crypto::decrypt($value, SECRET_SALT, $this->getFormName());
 }
Beispiel #10
0
 function to_php($value)
 {
     return Crypto::decrypt($value, SECRET_SALT, 'pwfield');
 }
Beispiel #11
0
 function pre_save(&$config, &$errors)
 {
     require_once 'include/Net/LDAP2.php';
     global $ost;
     if ($ost && !extension_loaded('ldap')) {
         $ost->setWarning('LDAP extension is not available');
         return;
     }
     if ($config['domain'] && !$config['servers']) {
         if (!($servers = LDAPAuthentication::autodiscover($config['domain'], preg_split('/,?\\s+/', $config['dns'])))) {
             $this->getForm()->getField('servers')->addError("Unable to find LDAP servers for this domain. Try giving\n                    an address of one of the DNS servers or manually specify\n                    the LDAP servers for this domain below.");
         }
     } else {
         if (!$config['servers']) {
             $this->getForm()->getField('servers')->addError("No servers specified. Either specify a Active Directory\n                    domain or a list of servers");
         } else {
             $servers = array();
             foreach (preg_split('/\\s+/', $config['servers']) as $host) {
                 $servers[] = array('host' => $host);
             }
         }
     }
     $connection_error = false;
     foreach ($servers as $info) {
         // Assume MSAD
         $info['options']['LDAP_OPT_REFERRALS'] = 0;
         if ($config['tls']) {
             $info['starttls'] = true;
             // Don't require a certificate here
             putenv('LDAPTLS_REQCERT=never');
         }
         if ($config['bind_dn']) {
             $info['binddn'] = $config['bind_dn'];
             $info['bindpw'] = $config['bind_pw'] ? $config['bind_pw'] : Crypto::decrypt($this->get('bind_pw'), SECRET_SALT, $this->getNamespace());
         }
         // Set reasonable timeouts so we dont exceed max_execution_time
         $info['options'] = array('LDAP_OPT_TIMELIMIT' => 5, 'LDAP_OPT_NETWORK_TIMEOUT' => 5);
         $c = new Net_LDAP2($info);
         $r = $c->bind();
         if (PEAR::isError($r)) {
             $connection_error = $r->getMessage() . ': Unable to bind to ' . $info['host'];
         } else {
             $connection_error = false;
             break;
         }
     }
     if ($connection_error) {
         $this->getForm()->getField('servers')->addError($connection_error);
         $errors['err'] = 'Unable to connect any listed LDAP servers';
     }
     if (!$errors && $config['bind_pw']) {
         $config['bind_pw'] = Crypto::encrypt($config['bind_pw'], SECRET_SALT, $this->getNamespace());
     } else {
         $config['bind_pw'] = $this->get('bind_pw');
     }
     global $msg;
     if (!$errors) {
         $msg = 'LDAP configuration updated successfully';
     }
     return !$errors;
 }
Beispiel #12
0
 /**
  * Decrypt then verify a password
  *
  * @param HiddenString $password    The user's password
  * @param string $stored            The encrypted password hash
  * @param EncryptionKey $secretKey  The master key for all passwords
  * @return bool                     Is this password valid?
  * @throws InvalidMessage
  */
 public static function verify(HiddenString $password, string $stored, EncryptionKey $secretKey) : bool
 {
     $config = self::getConfig($stored);
     // Base64-urlsafe encoded, so 4/3 the size of raw binary
     if (Util::safeStrlen($stored) < $config->SHORTEST_CIPHERTEXT_LENGTH * 4 / 3) {
         throw new InvalidMessage('Encrypted password hash is too short.');
     }
     // First let's decrypt the hash
     $hash_str = Crypto::decrypt($stored, $secretKey, $config->ENCODING);
     // Upon successful decryption, verify the password is correct
     return \Sodium\crypto_pwhash_str_verify($hash_str->getString(), $password->getString());
 }
Beispiel #13
0
 function getSMTPInfo()
 {
     $info = array('host' => $this->ht['smtp_host'], 'port' => $this->ht['smtp_port'], 'auth' => (bool) $this->ht['smtp_auth'], 'username' => $this->ht['userid'], 'password' => Crypto::decrypt($this->ht['userpass'], SECRET_SALT, $this->ht['userid']));
     return $info;
 }
Beispiel #14
0
 public function testEncryptWithFileDecryptWithCrypto()
 {
     $ciphertext_path = self::$TEMP_DIR . '/ciphertext';
     $plaintext_path = self::$TEMP_DIR . '/plaintext';
     $key = Key::createNewRandomKey();
     $plaintext = 'Plaintext!';
     file_put_contents($plaintext_path, $plaintext);
     File::encryptFile($plaintext_path, $ciphertext_path, $key);
     $ciphertext = file_get_contents($ciphertext_path);
     $plaintext_decrypted = Crypto::decrypt($ciphertext, $key, true);
     $this->assertSame($plaintext, $plaintext_decrypted);
 }
Beispiel #15
0
function dfrn_notify_post(&$a)
{
    logger(__FUNCTION__, LOGGER_TRACE);
    $dfrn_id = x($_POST, 'dfrn_id') ? notags(trim($_POST['dfrn_id'])) : '';
    $dfrn_version = x($_POST, 'dfrn_version') ? (double) $_POST['dfrn_version'] : 2.0;
    $challenge = x($_POST, 'challenge') ? notags(trim($_POST['challenge'])) : '';
    $data = x($_POST, 'data') ? $_POST['data'] : '';
    $key = x($_POST, 'key') ? $_POST['key'] : '';
    $rino_remote = x($_POST, 'rino') ? intval($_POST['rino']) : 0;
    $dissolve = x($_POST, 'dissolve') ? intval($_POST['dissolve']) : 0;
    $perm = x($_POST, 'perm') ? notags(trim($_POST['perm'])) : 'r';
    $ssl_policy = x($_POST, 'ssl_policy') ? notags(trim($_POST['ssl_policy'])) : 'none';
    $page = x($_POST, 'page') ? intval($_POST['page']) : 0;
    $forum = $page == 1 ? 1 : 0;
    $prv = $page == 2 ? 1 : 0;
    $writable = -1;
    if ($dfrn_version >= 2.21) {
        $writable = $perm === 'rw' ? 1 : 0;
    }
    $direction = -1;
    if (strpos($dfrn_id, ':') == 1) {
        $direction = intval(substr($dfrn_id, 0, 1));
        $dfrn_id = substr($dfrn_id, 2);
    }
    $r = q("SELECT * FROM `challenge` WHERE `dfrn-id` = '%s' AND `challenge` = '%s' LIMIT 1", dbesc($dfrn_id), dbesc($challenge));
    if (!count($r)) {
        logger('dfrn_notify: could not match challenge to dfrn_id ' . $dfrn_id . ' challenge=' . $challenge);
        xml_status(3);
    }
    $r = q("DELETE FROM `challenge` WHERE `dfrn-id` = '%s' AND `challenge` = '%s'", dbesc($dfrn_id), dbesc($challenge));
    // find the local user who owns this relationship.
    $sql_extra = '';
    switch ($direction) {
        case -1:
            $sql_extra = sprintf(" AND ( `issued-id` = '%s' OR `dfrn-id` = '%s' ) ", dbesc($dfrn_id), dbesc($dfrn_id));
            break;
        case 0:
            $sql_extra = sprintf(" AND `issued-id` = '%s' AND `duplex` = 1 ", dbesc($dfrn_id));
            break;
        case 1:
            $sql_extra = sprintf(" AND `dfrn-id` = '%s' AND `duplex` = 1 ", dbesc($dfrn_id));
            break;
        default:
            xml_status(3);
            break;
            // NOTREACHED
    }
    // be careful - $importer will contain both the contact information for the contact
    // sending us the post, and also the user information for the person receiving it.
    // since they are mixed together, it is easy to get them confused.
    $r = q("SELECT\t`contact`.*, `contact`.`uid` AS `importer_uid`,\n\t\t\t\t\t`contact`.`pubkey` AS `cpubkey`,\n\t\t\t\t\t`contact`.`prvkey` AS `cprvkey`,\n\t\t\t\t\t`contact`.`thumb` AS `thumb`,\n\t\t\t\t\t`contact`.`url` as `url`,\n\t\t\t\t\t`contact`.`name` as `senderName`,\n\t\t\t\t\t`user`.*\n\t\t\tFROM `contact`\n\t\t\tLEFT JOIN `user` ON `contact`.`uid` = `user`.`uid`\n\t\t\tWHERE `contact`.`blocked` = 0 AND `contact`.`pending` = 0\n\t\t\t\tAND `user`.`nickname` = '%s' AND `user`.`account_expired` = 0 AND `user`.`account_removed` = 0 {$sql_extra} LIMIT 1", dbesc($a->argv[1]));
    if (!count($r)) {
        logger('dfrn_notify: contact not found for dfrn_id ' . $dfrn_id);
        xml_status(3);
        //NOTREACHED
    }
    // $importer in this case contains the contact record for the remote contact joined with the user record of our user.
    $importer = $r[0];
    logger("Remote rino version: " . $rino_remote . " for " . $importer["url"], LOGGER_DEBUG);
    if ($writable != -1 && $writable != $importer['writable'] || $importer['forum'] != $forum || $importer['prv'] != $prv) {
        q("UPDATE `contact` SET `writable` = %d, forum = %d, prv = %d WHERE `id` = %d", intval($writable == -1 ? $importer['writable'] : $writable), intval($forum), intval($prv), intval($importer['id']));
        if ($writable != -1) {
            $importer['writable'] = $writable;
        }
        $importer['forum'] = $page;
    }
    // if contact's ssl policy changed, update our links
    fix_contact_ssl_policy($importer, $ssl_policy);
    logger('dfrn_notify: received notify from ' . $importer['name'] . ' for ' . $importer['username']);
    logger('dfrn_notify: data: ' . $data, LOGGER_DATA);
    if ($dissolve == 1) {
        /**
         * Relationship is dissolved permanently
         */
        require_once 'include/Contact.php';
        contact_remove($importer['id']);
        logger('relationship dissolved : ' . $importer['name'] . ' dissolved ' . $importer['username']);
        xml_status(0);
    }
    // If we are setup as a soapbox we aren't accepting input from this person
    // This behaviour is deactivated since it really doesn't make sense to even disallow comments
    // The check if someone is a friend or simply a follower is done in a later place so it needn't to be done here
    //if($importer['page-flags'] == PAGE_SOAPBOX)
    //	xml_status(0);
    $rino = get_config('system', 'rino_encrypt');
    $rino = intval($rino);
    // use RINO1 if mcrypt isn't installed and RINO2 was selected
    if ($rino == 2 and !function_exists('mcrypt_create_iv')) {
        $rino = 1;
    }
    logger("Local rino version: " . $rino, LOGGER_DEBUG);
    if (strlen($key)) {
        // if local rino is lower than remote rino, abort: should not happen!
        // but only for $remote_rino > 1, because old code did't send rino version
        if ($rino_remote_version > 1 && $rino < $rino_remote) {
            logger("rino version '{$rino_remote}' is lower than supported '{$rino}'");
            xml_status(0, "rino version '{$rino_remote}' is lower than supported '{$rino}'");
        }
        $rawkey = hex2bin(trim($key));
        logger('rino: md5 raw key: ' . md5($rawkey));
        $final_key = '';
        if ($dfrn_version >= 2.1) {
            if ($importer['duplex'] && strlen($importer['cprvkey']) || !strlen($importer['cpubkey'])) {
                openssl_private_decrypt($rawkey, $final_key, $importer['cprvkey']);
            } else {
                openssl_public_decrypt($rawkey, $final_key, $importer['cpubkey']);
            }
        } else {
            if ($importer['duplex'] && strlen($importer['cpubkey']) || !strlen($importer['cprvkey'])) {
                openssl_public_decrypt($rawkey, $final_key, $importer['cpubkey']);
            } else {
                openssl_private_decrypt($rawkey, $final_key, $importer['cprvkey']);
            }
        }
        #logger('rino: received key : ' . $final_key);
        switch ($rino_remote) {
            case 0:
            case 1:
                // we got a key. old code send only the key, without RINO version.
                // we assume RINO 1 if key and no RINO version
                $data = aes_decrypt(hex2bin($data), $final_key);
                break;
            case 2:
                try {
                    $data = Crypto::decrypt(hex2bin($data), $final_key);
                } catch (InvalidCiphertext $ex) {
                    // VERY IMPORTANT
                    // Either:
                    //   1. The ciphertext was modified by the attacker,
                    //   2. The key is wrong, or
                    //   3. $ciphertext is not a valid ciphertext or was corrupted.
                    // Assume the worst.
                    logger('The ciphertext has been tampered with!');
                    xml_status(0, 'The ciphertext has been tampered with!');
                } catch (Ex\CryptoTestFailed $ex) {
                    logger('Cannot safely perform dencryption');
                    xml_status(0, 'CryptoTestFailed');
                } catch (Ex\CannotPerformOperation $ex) {
                    logger('Cannot safely perform decryption');
                    xml_status(0, 'Cannot safely perform decryption');
                }
                break;
            default:
                logger("rino: invalid sent verision '{$rino_remote}'");
                xml_status(0);
        }
        logger('rino: decrypted data: ' . $data, LOGGER_DATA);
    }
    $ret = local_delivery($importer, $data);
    xml_status($ret);
    // NOTREACHED
}
Beispiel #16
0
 /**
  * Decryption of encoded data for all of the versions
  *
  * @dataProvider dataDecrypt
  */
 public function testDecrypt($expected, $encrypted, $key, $cipher = null, $mode = null)
 {
     $crypto = new Crypto($key, $cipher, $mode);
     $decrypted = $crypto->decrypt($encrypted);
     $this->assertEquals($expected, $decrypted);
 }