/** * Hash then encrypt a password * * @param string $password - The user's password * @param EncryptionKey $secret_key - The master key for all passwords * @return string */ public static function hash(string $password, EncryptionKey $secret_key) : string { // First, let's calculate the hash $hashed = \Sodium\crypto_pwhash_str($password, \Sodium\CRYPTO_PWHASH_OPSLIMIT_INTERACTIVE, \Sodium\CRYPTO_PWHASH_MEMLIMIT_INTERACTIVE); // Now let's encrypt the result return Crypto::encrypt($hashed, $secret_key); }
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; } } }
/** * @param $email * @param $password * @param $name * @param $host * @param $port * @param string|null $encryptionProtocol * @param $user * @return MailAccount */ public function connect($email, $password, $name, $host, $port, $encryptionProtocol, $user) { $account = new MailAccount(); $account->setUserId($this->userId); $account->setName($name); $account->setEmail($email); $account->setInboundHost($host); $account->setInboundPort($port); $account->setInboundSslMode($encryptionProtocol); $account->setInboundUser($user); $password = $this->crypto->encrypt($password); $account->setInboundPassword($password); $a = new Account($account); $a->getImapConnection(); $this->logger->info("Test-Account-Successful: {$this->userId}, {$host}, {$port}, {$user}, {$encryptionProtocol}"); return $account; }
/** * Hash then encrypt a password * * @param HiddenString $password The user's password * @param EncryptionKey $secretKey The master key for all passwords * @param string $level The security level for this password * @return string An encrypted hash to store */ public static function hash(HiddenString $password, EncryptionKey $secretKey, string $level = KeyFactory::INTERACTIVE) : string { $kdfLimits = KeyFactory::getSecurityLevels($level); // First, let's calculate the hash $hashed = \Sodium\crypto_pwhash_str($password->getString(), $kdfLimits[0], $kdfLimits[1]); // Now let's encrypt the result return Crypto::encrypt(new HiddenString($hashed), $secretKey); }
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'); } }
function run() { $sql = 'SELECT email_id, userpass, userid FROM ' . EMAIL_TABLE . " WHERE userpass <> ''"; if (($res = db_query($sql)) && db_num_rows($res)) { while (list($id, $passwd, $username) = db_fetch_row($res)) { if (!$passwd) { continue; } $ciphertext = Crypto::encrypt(self::_decrypt($passwd, SECRET_SALT), SECRET_SALT, $username); $sql = 'UPDATE ' . EMAIL_TABLE . ' SET userpass='******' WHERE email_id=' . db_input($id); db_query($sql); } } }
public function KeyAdd($master, $password, $key, $value) { if ($this->MasterExists($master)) { require_once APP_DIR . "/src/Inc/Crypto.php"; $items = getData("master_" . $master . "_items"); $pass_salt = getData("master_" . $master . "_password_salt"); $items = $items == null ? array() : json_decode($items, true); $items[$key] = $value; $items = json_encode($items); $key = $this->master_salt . $password . $pass_salt; Crypto::$KEY_BYTE_SIZE = mb_strlen($key, '8bit'); $items = Crypto::encrypt(base64_encode($items), $key); $items = base64_encode($items); saveData("master_" . $master . "_items", $items); return true; } else { return false; } }
/** * Set a session cookie 's' to indicate a logged in session. * Set a name cookie 'n' containing the user's login name. * Set a first name cookie 'f' containing the user's first name. */ public static function setLoginCookies($nickName, $id, $firstName = '', $lastName = '') { // The session cookie is an encrypted string containing // the user name, the user id key (from the DB), // and a timestamp $str = $nickName . ':' . $id . ':' . time(); $str = Crypto::encrypt($str, $_SERVER['ENCRYPTION_KEY']); // split the domain name apart $d = explode('.', $_SERVER['SERVER_NAME']); // get the last piece $d2 = array_pop($d); // get the second to last piece $d1 = array_pop($d); // get the base domain name (regardless of how many parts it has) $domain = '.' . $d1 . '.' . $d2; setcookie('s', $str, 0, '/', $domain); // if the user gave us a first name, use that for the name // cookie. else use the nickname. $nm = empty($firstName) ? $nickName : $firstName; // expire 6 months in the future $expires = time() + 60 * 60 * 24 * 30 * 6; setcookie('f', $nm, $expires, '/', $domain); setcookie('n', $nickName, $expires, '/', $domain); }
/** * Store a value in an encrypted cookie * * @param string $name * @param mixed $value * @param int $expire (defaults to 0) * @param string $path (defaults to '/') * @param string $domain (defaults to NULL) * @param bool $secure (defaults to TRUE) * @param bool $httponly (defaults to TRUE) * @return bool */ public function store(string $name, $value, int $expire = 0, string $path = '/', $domain = null, bool $secure = true, bool $httponly = true) : bool { return \setcookie($name, Crypto::encrypt(\json_encode($value), $this->key), $expire, $path, $domain, $secure, $httponly); }
function dfrn_deliver($owner, $contact, $atom, $dissolve = false) { $a = get_app(); $idtosend = $orig_id = $contact['dfrn-id'] ? $contact['dfrn-id'] : $contact['issued-id']; if ($contact['duplex'] && $contact['dfrn-id']) { $idtosend = '0:' . $orig_id; } if ($contact['duplex'] && $contact['issued-id']) { $idtosend = '1:' . $orig_id; } $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); $ssl_val = intval(get_config('system', 'ssl_policy')); $ssl_policy = ''; switch ($ssl_val) { case SSL_POLICY_FULL: $ssl_policy = 'full'; break; case SSL_POLICY_SELFSIGN: $ssl_policy = 'self'; break; case SSL_POLICY_NONE: default: $ssl_policy = 'none'; break; } $url = $contact['notify'] . '&dfrn_id=' . $idtosend . '&dfrn_version=' . DFRN_PROTOCOL_VERSION . ($rino ? '&rino=' . $rino : ''); logger('dfrn_deliver: ' . $url); $xml = fetch_url($url); $curl_stat = $a->get_curl_code(); if (!$curl_stat) { return -1; } // timed out logger('dfrn_deliver: ' . $xml, LOGGER_DATA); if (!$xml) { return 3; } if (strpos($xml, '<?xml') === false) { logger('dfrn_deliver: no valid XML returned'); logger('dfrn_deliver: returned XML: ' . $xml, LOGGER_DATA); return 3; } $res = parse_xml_string($xml); if (intval($res->status) != 0 || !strlen($res->challenge) || !strlen($res->dfrn_id)) { return $res->status ? $res->status : 3; } $postvars = array(); $sent_dfrn_id = hex2bin((string) $res->dfrn_id); $challenge = hex2bin((string) $res->challenge); $perm = $res->perm ? $res->perm : null; $dfrn_version = (double) ($res->dfrn_version ? $res->dfrn_version : 2.0); $rino_remote_version = intval($res->rino); $page = $owner['page-flags'] == PAGE_COMMUNITY ? 1 : 0; logger("Remote rino version: " . $rino_remote_version . " for " . $contact["url"], LOGGER_DEBUG); if ($owner['page-flags'] == PAGE_PRVGROUP) { $page = 2; } $final_dfrn_id = ''; if ($perm) { if ($perm == 'rw' && !intval($contact['writable']) || $perm == 'r' && intval($contact['writable'])) { q("update contact set writable = %d where id = %d", intval($perm == 'rw' ? 1 : 0), intval($contact['id'])); $contact['writable'] = (string) 1 - intval($contact['writable']); } } if ($contact['duplex'] && strlen($contact['pubkey']) || $owner['page-flags'] == PAGE_COMMUNITY && strlen($contact['pubkey']) || $contact['rel'] == CONTACT_IS_SHARING && strlen($contact['pubkey'])) { openssl_public_decrypt($sent_dfrn_id, $final_dfrn_id, $contact['pubkey']); openssl_public_decrypt($challenge, $postvars['challenge'], $contact['pubkey']); } else { openssl_private_decrypt($sent_dfrn_id, $final_dfrn_id, $contact['prvkey']); openssl_private_decrypt($challenge, $postvars['challenge'], $contact['prvkey']); } $final_dfrn_id = substr($final_dfrn_id, 0, strpos($final_dfrn_id, '.')); if (strpos($final_dfrn_id, ':') == 1) { $final_dfrn_id = substr($final_dfrn_id, 2); } if ($final_dfrn_id != $orig_id) { logger('dfrn_deliver: wrong dfrn_id.'); // did not decode properly - cannot trust this site return 3; } $postvars['dfrn_id'] = $idtosend; $postvars['dfrn_version'] = DFRN_PROTOCOL_VERSION; if ($dissolve) { $postvars['dissolve'] = '1'; } if ($contact['rel'] && $contact['rel'] != CONTACT_IS_SHARING && !$contact['blocked'] || $owner['page-flags'] == PAGE_COMMUNITY) { $postvars['data'] = $atom; $postvars['perm'] = 'rw'; } else { $postvars['data'] = str_replace('<dfrn:comment-allow>1', '<dfrn:comment-allow>0', $atom); $postvars['perm'] = 'r'; } $postvars['ssl_policy'] = $ssl_policy; if ($page) { $postvars['page'] = $page; } if ($rino > 0 && $rino_remote_version > 0 && !$dissolve) { logger('rino version: ' . $rino_remote_version); switch ($rino_remote_version) { case 1: // Deprecated rino version! $key = substr(random_string(), 0, 16); $data = aes_encrypt($postvars['data'], $key); break; case 2: // RINO 2 based on php-encryption try { $key = Crypto::createNewRandomKey(); } catch (CryptoTestFailed $ex) { logger('Cannot safely create a key'); return -1; } catch (CannotPerformOperation $ex) { logger('Cannot safely create a key'); return -1; } try { $data = Crypto::encrypt($postvars['data'], $key); } catch (CryptoTestFailed $ex) { logger('Cannot safely perform encryption'); return -1; } catch (CannotPerformOperation $ex) { logger('Cannot safely perform encryption'); return -1; } break; default: logger("rino: invalid requested verision '{$rino_remote_version}'"); return -1; } $postvars['rino'] = $rino_remote_version; $postvars['data'] = bin2hex($data); #logger('rino: sent key = ' . $key, LOGGER_DEBUG); if ($dfrn_version >= 2.1) { if ($contact['duplex'] && strlen($contact['pubkey']) || $owner['page-flags'] == PAGE_COMMUNITY && strlen($contact['pubkey']) || $contact['rel'] == CONTACT_IS_SHARING && strlen($contact['pubkey'])) { openssl_public_encrypt($key, $postvars['key'], $contact['pubkey']); } else { openssl_private_encrypt($key, $postvars['key'], $contact['prvkey']); } } else { if ($contact['duplex'] && strlen($contact['prvkey']) || $owner['page-flags'] == PAGE_COMMUNITY) { openssl_private_encrypt($key, $postvars['key'], $contact['prvkey']); } else { openssl_public_encrypt($key, $postvars['key'], $contact['pubkey']); } } logger('md5 rawkey ' . md5($postvars['key'])); $postvars['key'] = bin2hex($postvars['key']); } logger('dfrn_deliver: ' . "SENDING: " . print_r($postvars, true), LOGGER_DATA); $xml = post_url($contact['notify'], $postvars); logger('dfrn_deliver: ' . "RECEIVED: " . $xml, LOGGER_DATA); $curl_stat = $a->get_curl_code(); if (!$curl_stat || !strlen($xml)) { return -1; } // timed out if ($curl_stat == 503 && stristr($a->get_curl_headers(), 'retry-after')) { return -1; } if (strpos($xml, '<?xml') === false) { logger('dfrn_deliver: phase 2: no valid XML returned'); logger('dfrn_deliver: phase 2: returned XML: ' . $xml, LOGGER_DATA); return 3; } if ($contact['term-date'] != '0000-00-00 00:00:00') { logger("dfrn_deliver: {$url} back from the dead - removing mark for death"); require_once 'include/Contact.php'; unmark_for_death($contact); } $res = parse_xml_string($xml); return $res->status; }
function to_database($value) { return Crypto::encrypt($value, SECRET_SALT, $this->getFormName()); }
function to_database($value) { // If not set in UI, don't save the empty value if (!$value) { throw new FieldUnchanged(); } return Crypto::encrypt($value, SECRET_SALT, 'pwfield'); }
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; }
public function testDelete() { $response = $this->call('DELETE', 'quarx/blog/' . Crypto::encrypt(1)); $this->assertEquals(302, $response->getStatusCode()); $this->assertRedirectedTo('quarx/blog'); }
function save($id, $vars, &$errors) { global $cfg; //very basic checks $vars['name'] = Format::striptags(trim($vars['name'])); $vars['email'] = trim($vars['email']); if ($id && $id != $vars['id']) { $errors['err'] = __('Internal error. Get technical help.'); } if (!$vars['email'] || !Validator::is_email($vars['email'])) { $errors['email'] = __('Valid email required'); } elseif (($eid = Email::getIdByEmail($vars['email'])) && $eid != $id) { $errors['email'] = __('Email already exists'); } elseif ($cfg && !strcasecmp($cfg->getAdminEmail(), $vars['email'])) { $errors['email'] = __('Email already used as admin email!'); } elseif (Staff::getIdByEmail($vars['email'])) { //make sure the email doesn't belong to any of the staff $errors['email'] = __('Email in use by an agent'); } if (!$vars['name']) { $errors['name'] = __('Email name required'); } if ($vars['mail_active'] || $vars['smtp_active'] && $vars['smtp_auth']) { if (!$vars['userid']) { $errors['userid'] = __('Username missing'); } if (!$id && !$vars['passwd']) { $errors['passwd'] = __('Password required'); } elseif ($vars['passwd'] && $vars['userid'] && !Crypto::encrypt($vars['passwd'], SECRET_SALT, $vars['userid'])) { $errors['passwd'] = __('Unable to encrypt password - get technical support'); } } list($vars['mail_protocol'], $encryption) = explode('/', $vars['mail_proto']); $vars['mail_encryption'] = $encryption ?: 'NONE'; if ($vars['mail_active']) { //Check pop/imapinfo only when enabled. if (!function_exists('imap_open')) { $errors['mail_active'] = __("IMAP doesn't exist. PHP must be compiled with IMAP enabled."); } if (!$vars['mail_host']) { $errors['mail_host'] = __('Host name required'); } if (!$vars['mail_port']) { $errors['mail_port'] = __('Port required'); } if (!$vars['mail_protocol']) { $errors['mail_protocol'] = __('Select protocol'); } if (!$vars['mail_fetchfreq'] || !is_numeric($vars['mail_fetchfreq'])) { $errors['mail_fetchfreq'] = __('Fetch interval required'); } if (!$vars['mail_fetchmax'] || !is_numeric($vars['mail_fetchmax'])) { $errors['mail_fetchmax'] = __('Maximum emails required'); } if (!isset($vars['postfetch'])) { $errors['postfetch'] = __('Indicate what to do with fetched emails'); } elseif (!strcasecmp($vars['postfetch'], 'archive') && !$vars['mail_archivefolder']) { $errors['postfetch'] = __('Valid folder required'); } } if ($vars['smtp_active']) { if (!$vars['smtp_host']) { $errors['smtp_host'] = __('Host name required'); } if (!$vars['smtp_port']) { $errors['smtp_port'] = __('Port required'); } } //abort on errors if ($errors) { return false; } if (!$errors && ($vars['mail_host'] && $vars['userid'])) { $sql = 'SELECT email_id FROM ' . EMAIL_TABLE . ' WHERE mail_host=' . db_input($vars['mail_host']) . ' AND userid=' . db_input($vars['userid']); if ($id) { $sql .= ' AND email_id!=' . db_input($id); } if (db_num_rows(db_query($sql))) { $errors['userid'] = $errors['host'] = __('Host/userid combination already in use.'); } } $passwd = $vars['passwd'] ? $vars['passwd'] : $vars['cpasswd']; if (!$errors && $vars['mail_active']) { //note: password is unencrypted at this point...MailFetcher expect plain text. $fetcher = new MailFetcher(array('host' => $vars['mail_host'], 'port' => $vars['mail_port'], 'username' => $vars['userid'], 'password' => $passwd, 'protocol' => $vars['mail_protocol'], 'encryption' => $vars['mail_encryption'])); if (!$fetcher->connect()) { //$errors['err']='Invalid login. Check '.Format::htmlchars($vars['mail_protocol']).' settings'; $errors['err'] = sprintf(__('Invalid login. Check %s settings'), Format::htmlchars($vars['mail_protocol'])); $errors['mail'] = '<br>' . $fetcher->getLastError(); } elseif ($vars['mail_archivefolder'] && !$fetcher->checkMailbox($vars['mail_archivefolder'], true)) { //$errors['postfetch']='Invalid or unknown mail folder! >> '.$fetcher->getLastError().''; $errors['postfetch'] = sprintf(__('Invalid or unknown mail folder! >> %s'), $fetcher->getLastError()); if (!$errors['mail']) { $errors['mail'] = __('Invalid or unknown archive folder!'); } } } if (!$errors && $vars['smtp_active']) { //Check SMTP login only. require_once 'Mail.php'; // PEAR Mail package $smtp = mail::factory('smtp', array('host' => $vars['smtp_host'], 'port' => $vars['smtp_port'], 'auth' => (bool) $vars['smtp_auth'], 'username' => $vars['userid'], 'password' => $passwd, 'timeout' => 20, 'debug' => false)); $mail = $smtp->connect(); if (PEAR::isError($mail)) { $errors['err'] = __('Unable to log in. Check SMTP settings.'); $errors['smtp'] = '<br>' . $mail->getMessage(); } else { $smtp->disconnect(); //Thank you, sir! } } if ($errors) { return false; } $sql = 'updated=NOW(),mail_errors=0, mail_lastfetch=NULL' . ',email=' . db_input($vars['email']) . ',name=' . db_input(Format::striptags($vars['name'])) . ',dept_id=' . db_input($vars['dept_id']) . ',priority_id=' . db_input($vars['priority_id']) . ',topic_id=' . db_input($vars['topic_id']) . ',noautoresp=' . db_input(isset($vars['noautoresp']) ? 1 : 0) . ',userid=' . db_input($vars['userid']) . ',mail_active=' . db_input($vars['mail_active']) . ',mail_host=' . db_input($vars['mail_host']) . ',mail_protocol=' . db_input($vars['mail_protocol'] ? $vars['mail_protocol'] : 'POP') . ',mail_encryption=' . db_input($vars['mail_encryption']) . ',mail_port=' . db_input($vars['mail_port'] ? $vars['mail_port'] : 0) . ',mail_fetchfreq=' . db_input($vars['mail_fetchfreq'] ? $vars['mail_fetchfreq'] : 0) . ',mail_fetchmax=' . db_input($vars['mail_fetchmax'] ? $vars['mail_fetchmax'] : 0) . ',smtp_active=' . db_input($vars['smtp_active']) . ',smtp_host=' . db_input($vars['smtp_host']) . ',smtp_port=' . db_input($vars['smtp_port'] ? $vars['smtp_port'] : 0) . ',smtp_auth=' . db_input($vars['smtp_auth']) . ',smtp_spoofing=' . db_input(isset($vars['smtp_spoofing']) ? 1 : 0) . ',notes=' . db_input(Format::sanitize($vars['notes'])); //Post fetch email handling... if ($vars['postfetch'] && !strcasecmp($vars['postfetch'], 'delete')) { $sql .= ',mail_delete=1,mail_archivefolder=NULL'; } elseif ($vars['postfetch'] && !strcasecmp($vars['postfetch'], 'archive') && $vars['mail_archivefolder']) { $sql .= ',mail_delete=0,mail_archivefolder=' . db_input($vars['mail_archivefolder']); } else { $sql .= ',mail_delete=0,mail_archivefolder=NULL'; } if ($vars['passwd']) { //New password - encrypt. $sql .= ',userpass='******'passwd'], SECRET_SALT, $vars['userid'])); } if ($id) { //update $sql = 'UPDATE ' . EMAIL_TABLE . ' SET ' . $sql . ' WHERE email_id=' . db_input($id); if (db_query($sql) && db_affected_rows()) { return true; } $errors['err'] = sprintf(__('Unable to update %s.'), __('this email')) . ' ' . __('Internal error occurred'); } else { $sql = 'INSERT INTO ' . EMAIL_TABLE . ' SET ' . $sql . ',created=NOW()'; if (db_query($sql) && ($id = db_insert_id())) { return $id; } $errors['err'] = sprintf(__('Unable to add %s.'), __('this email')) . ' ' . __('Internal error occurred'); } return false; }
public function testEncryptWithCryptoDecryptWithFile() { $ciphertext_path = self::$TEMP_DIR . '/ciphertext'; $plaintext_path = self::$TEMP_DIR . '/plaintext'; $key = Key::createNewRandomKey(); $plaintext = 'Plaintext!'; $ciphertext = Crypto::encrypt($plaintext, $key, true); file_put_contents($ciphertext_path, $ciphertext); File::decryptFile($ciphertext_path, $plaintext_path, $key); $plaintext_decrypted = file_get_contents($plaintext_path); $this->assertSame($plaintext, $plaintext_decrypted); }
/** * Encryption with known IVs should match * * @dataProvider dataEncrypt */ public function testEncrypt($expected, $iv, $plaintext) { $crypto = new Crypto('Your crypto key would normally go here.'); $encrypted = $crypto->encrypt($plaintext, $iv); $this->assertEquals($expected, $encrypted); }