This adds some security utilities to core including: - A library for basic crypto operations (e.g. to encrypt passwords) - A better library for cryptographic actions which allows you to specify the charset - A library for secure string comparisions Remove .htaccess Remove .htaccess Fix typo Add public API Use timing constant comparision Remove CBC constant Adjust code Remove confusing $thistags/v8.0.0alpha1
@@ -35,6 +35,9 @@ $CONFIG = array( | |||
/* Define the salt used to hash the user passwords. All your user passwords are lost if you lose this string. */ | |||
"passwordsalt" => "", | |||
/* Secret used by ownCloud for various purposes, e.g. to encrypt data. If you lose this string there will be data corruption. */ | |||
"secret" => "", | |||
/* Force use of HTTPS connection (true = use HTTPS) */ | |||
"forcessl" => false, | |||
@@ -153,7 +153,6 @@ class Controller { | |||
'hasMSSQL' => $hasMSSQL, | |||
'databases' => $databases, | |||
'directory' => $datadir, | |||
'secureRNG' => \OC_Util::secureRNGAvailable(), | |||
'htaccessWorking' => $htaccessWorking, | |||
'vulnerableToNullByte' => $vulnerableToNullByte, | |||
'errors' => $errors, |
@@ -27,13 +27,6 @@ | |||
<?php p($l->t('Please update your PHP installation to use %s securely.', $theme->getName() )); ?></p> | |||
</fieldset> | |||
<?php endif; ?> | |||
<?php if(!$_['secureRNG']): ?> | |||
<fieldset class="warning"> | |||
<legend><strong><?php p($l->t('Security Warning'));?></strong></legend> | |||
<p><?php p($l->t('No secure random number generator is available, please enable the PHP OpenSSL extension.'));?><br/> | |||
<?php p($l->t('Without a secure random number generator an attacker may be able to predict password reset tokens and take over your account.'));?></p> | |||
</fieldset> | |||
<?php endif; ?> | |||
<?php if(!$_['htaccessWorking']): ?> | |||
<fieldset class="warning"> | |||
<legend><strong><?php p($l->t('Security Warning'));?></strong></legend> |
@@ -71,6 +71,7 @@ class Repair extends BasicEmitter { | |||
return array( | |||
new \OC\Repair\RepairMimeTypes(), | |||
new \OC\Repair\RepairLegacyStorages(\OC::$server->getConfig(), \OC_DB::getConnection()), | |||
new \OC\Repair\RepairConfig(), | |||
); | |||
} | |||
@@ -0,0 +1,104 @@ | |||
<?php | |||
/** | |||
* Copyright (c) 2014 Lukas Reschke <lukas@owncloud.com> | |||
* This file is licensed under the Affero General Public License version 3 or | |||
* later. | |||
* See the COPYING-README file. | |||
*/ | |||
namespace OC\Security; | |||
use Crypt_AES; | |||
use Crypt_Hash; | |||
use OCP\Security\ICrypto; | |||
use OCP\Security\StringUtils; | |||
/** | |||
* Class Crypto provides a high-level encryption layer using AES-CBC. If no key has been provided | |||
* it will use the secret defined in config.php as key. Additionally the message will be HMAC'd. | |||
* | |||
* Usage: | |||
* $encryptWithDefaultPassword = \OC::$server->getCrypto()->encrypt('EncryptedText'); | |||
* $encryptWithCustompassword = \OC::$server->getCrypto()->encrypt('EncryptedText', 'password'); | |||
* | |||
* @package OC\Security | |||
*/ | |||
class Crypto implements ICrypto { | |||
/** @var Crypt_AES $cipher */ | |||
private $cipher; | |||
/** @var int */ | |||
private $ivLength = 16; | |||
function __construct() { | |||
$this->cipher = new Crypt_AES(); | |||
} | |||
/** | |||
* @param string $message The message to authenticate | |||
* @param string $password Password to use (defaults to `secret` in config.php) | |||
* @return string Calculated HMAC | |||
*/ | |||
public function calculateHMAC($message, $password = '') { | |||
if($password === '') { | |||
$password = \OC::$server->getConfig()->getSystemValue('secret'); | |||
} | |||
$hash = new Crypt_Hash('sha512'); | |||
$hash->setKey($password); | |||
return $hash->hash($message); | |||
} | |||
/** | |||
* Encrypts a value and adds an HMAC (Encrypt-Then-MAC) | |||
* @param string $plaintext | |||
* @param string $password Password to encrypt, if not specified the secret from config.php will be taken | |||
* @return string Authenticated ciphertext | |||
*/ | |||
public function encrypt($plaintext, $password = '') { | |||
if($password === '') { | |||
$password = \OC::$server->getConfig()->getSystemValue('secret'); | |||
} | |||
$this->cipher->setPassword($password); | |||
$iv = \OC::$server->getSecureRandom()->getLowStrengthGenerator()->generate($this->ivLength); | |||
$this->cipher->setIV($iv); | |||
$ciphertext = bin2hex($this->cipher->encrypt($plaintext)); | |||
$hmac = bin2hex($this->calculateHMAC($ciphertext.$iv, $password)); | |||
return $ciphertext.'|'.$iv.'|'.$hmac; | |||
} | |||
/** | |||
* Decrypts a value and verifies the HMAC (Encrypt-Then-Mac) | |||
* @param string $authenticatedCiphertext | |||
* @param string $password Password to encrypt, if not specified the secret from config.php will be taken | |||
* @return string plaintext | |||
* @throws \Exception If the HMAC does not match | |||
*/ | |||
public function decrypt($authenticatedCiphertext, $password = '') { | |||
if($password === '') { | |||
$password = \OC::$server->getConfig()->getSystemValue('secret'); | |||
} | |||
$this->cipher->setPassword($password); | |||
$parts = explode('|', $authenticatedCiphertext); | |||
if(sizeof($parts) !== 3) { | |||
throw new \Exception('Authenticated ciphertext could not be decoded.'); | |||
} | |||
$ciphertext = hex2bin($parts[0]); | |||
$iv = $parts[1]; | |||
$hmac = hex2bin($parts[2]); | |||
$this->cipher->setIV($iv); | |||
if(!StringUtils::equals($this->calculateHMAC($parts[0].$parts[1], $password), $hmac)) { | |||
throw new \Exception('HMAC does not match.'); | |||
} | |||
return $this->cipher->decrypt($ciphertext); | |||
} | |||
} |
@@ -0,0 +1,79 @@ | |||
<?php | |||
/** | |||
* Copyright (c) 2014 Lukas Reschke <lukas@owncloud.com> | |||
* This file is licensed under the Affero General Public License version 3 or | |||
* later. | |||
* See the COPYING-README file. | |||
*/ | |||
namespace OC\Security; | |||
use RandomLib; | |||
use Sabre\DAV\Exception; | |||
use OCP\Security\ISecureRandom; | |||
/** | |||
* Class SecureRandom provides a layer around RandomLib to generate | |||
* secure random strings. | |||
* | |||
* Usage: | |||
* \OC::$server->getSecureRandom()->getMediumStrengthGenerator()->generate(10); | |||
* | |||
* @package OC\Security | |||
*/ | |||
class SecureRandom implements ISecureRandom { | |||
/** @var \RandomLib\Factory */ | |||
var $factory; | |||
/** @var \RandomLib\Generator */ | |||
var $generator; | |||
function __construct() { | |||
$this->factory = new RandomLib\Factory; | |||
} | |||
/** | |||
* Convenience method to get a low strength random number generator. | |||
* | |||
* Low Strength should be used anywhere that random strings are needed | |||
* in a non-cryptographical setting. They are not strong enough to be | |||
* used as keys or salts. They are however useful for one-time use tokens. | |||
* | |||
* @return $this | |||
*/ | |||
public function getLowStrengthGenerator() { | |||
$this->generator = $this->factory->getLowStrengthGenerator(); | |||
return $this; | |||
} | |||
/** | |||
* Convenience method to get a medium strength random number generator. | |||
* | |||
* Medium Strength should be used for most needs of a cryptographic nature. | |||
* They are strong enough to be used as keys and salts. However, they do | |||
* take some time and resources to generate, so they should not be over-used | |||
* | |||
* @return $this | |||
*/ | |||
public function getMediumStrengthGenerator() { | |||
$this->generator = $this->factory->getMediumStrengthGenerator(); | |||
return $this; | |||
} | |||
/** | |||
* Generate a random string of specified length. | |||
* @param string $length The length of the generated string | |||
* @param string $characters An optional list of characters to use if no characterlist is | |||
* specified 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ./ | |||
* is used. | |||
* @return string | |||
* @throws \Exception If the generator is not initialized. | |||
*/ | |||
public function generate($length, $characters = '') { | |||
if(is_null($this->generator)) { | |||
throw new \Exception('Generator is not initialized.'); | |||
} | |||
return $this->generator->generateString($length, $characters); | |||
} | |||
} |
@@ -0,0 +1,38 @@ | |||
<?php | |||
/** | |||
* Copyright (c) 2014 Lukas Reschke <lukas@owncloud.com> | |||
* This file is licensed under the Affero General Public License version 3 or | |||
* later. | |||
* See the COPYING-README file. | |||
*/ | |||
namespace OC\Security; | |||
class StringUtils { | |||
/** | |||
* Compares whether two strings are equal. To prevent guessing of the string | |||
* length this is done by comparing two hashes against each other and afterwards | |||
* a comparison of the real string to prevent against the unlikely chance of | |||
* collisions. | |||
* @param string $expected The expected value | |||
* @param string $input The input to compare against | |||
* @return bool True if the two strings are equal, otherwise false. | |||
*/ | |||
public static function equals($expected, $input) { | |||
if(function_exists('hash_equals')) { | |||
return hash_equals($expected, $input); | |||
} | |||
$randomString = \OC::$server->getSecureRandom()->getMediumStrengthGenerator()->generate(10); | |||
if(hash('sha512', $expected.$randomString) === hash('sha512', $input.$randomString)) { | |||
if($expected === $input) { | |||
return true; | |||
} | |||
} | |||
return false; | |||
} | |||
} |
@@ -9,6 +9,8 @@ use OC\Cache\UserCache; | |||
use OC\DB\ConnectionWrapper; | |||
use OC\Files\Node\Root; | |||
use OC\Files\View; | |||
use OC\Security\Crypto; | |||
use OC\Security\SecureRandom; | |||
use OCP\IServerContainer; | |||
/** | |||
@@ -199,6 +201,12 @@ class Server extends SimpleContainer implements IServerContainer { | |||
$this->registerService('Search', function ($c) { | |||
return new Search(); | |||
}); | |||
$this->registerService('SecureRandom', function($c) { | |||
return new SecureRandom(); | |||
}); | |||
$this->registerService('Crypto', function($c) { | |||
return new Crypto(); | |||
}); | |||
$this->registerService('Db', function ($c) { | |||
return new Db(); | |||
}); | |||
@@ -455,6 +463,24 @@ class Server extends SimpleContainer implements IServerContainer { | |||
return $this->query('Search'); | |||
} | |||
/** | |||
* Returns a SecureRandom instance | |||
* | |||
* @return \OCP\Security\ISecureRandom | |||
*/ | |||
function getSecureRandom() { | |||
return $this->query('SecureRandom'); | |||
} | |||
/** | |||
* Returns a Crypto instance | |||
* | |||
* @return \OCP\Security\ICrypto | |||
*/ | |||
function getCrypto() { | |||
return $this->query('Crypto'); | |||
} | |||
/** | |||
* Returns an instance of the db facade | |||
* |
@@ -67,14 +67,19 @@ class OC_Setup { | |||
} | |||
//generate a random salt that is used to salt the local user passwords | |||
$salt = OC_Util::generateRandomBytes(30); | |||
OC_Config::setValue('passwordsalt', $salt); | |||
$salt = \OC::$server->getSecureRandom()->getLowStrengthGenerator()->generate(30); | |||
\OC::$server->getConfig()->setSystemValue('passwordsalt', $salt); | |||
// generate a secret | |||
$secret = \OC::$server->getSecureRandom()->getMediumStrengthGenerator()->generate(48); | |||
\OC::$server->getConfig()->setSystemValue('secret', $secret); | |||
//write the config file | |||
OC_Config::setValue('trusted_domains', $trustedDomains); | |||
OC_Config::setValue('datadirectory', $datadir); | |||
OC_Config::setValue('dbtype', $dbtype); | |||
OC_Config::setValue('version', implode('.', OC_Util::getVersion())); | |||
\OC::$server->getConfig()->setSystemValue('trusted_domains', $trustedDomains); | |||
\OC::$server->getConfig()->setSystemValue('datadirectory', $datadir); | |||
\OC::$server->getConfig()->setSystemValue('dbtype', $dbtype); | |||
\OC::$server->getConfig()->setSystemValue('version', implode('.', OC_Util::getVersion())); | |||
try { | |||
$dbSetup->initialize($options); | |||
$dbSetup->setupDatabase($username); |
@@ -905,7 +905,7 @@ class OC_Util { | |||
$id = OC_Config::getValue('instanceid', null); | |||
if (is_null($id)) { | |||
// We need to guarantee at least one letter in instanceid so it can be used as the session_name | |||
$id = 'oc' . self::generateRandomBytes(10); | |||
$id = 'oc' . \OC::$server->getSecureRandom()->getLowStrengthGenerator()->generate(10); | |||
OC_Config::$object->setValue('instanceid', $id); | |||
} | |||
return $id; | |||
@@ -1208,62 +1208,20 @@ class OC_Util { | |||
* | |||
* @param int $length of the random string | |||
* @return string | |||
* Please also update secureRNGAvailable if you change something here | |||
* @deprecated Use \OC::$server->getSecureRandom()->getMediumStrengthGenerator()->generate($length); instead | |||
*/ | |||
public static function generateRandomBytes($length = 30) { | |||
// Try to use openssl_random_pseudo_bytes | |||
if (function_exists('openssl_random_pseudo_bytes')) { | |||
$pseudoByte = bin2hex(openssl_random_pseudo_bytes($length, $strong)); | |||
if ($strong == true) { | |||
return substr($pseudoByte, 0, $length); // Truncate it to match the length | |||
} | |||
} | |||
// Try to use /dev/urandom | |||
if (!self::runningOnWindows()) { | |||
$fp = @file_get_contents('/dev/urandom', false, null, 0, $length); | |||
if ($fp !== false) { | |||
$string = substr(bin2hex($fp), 0, $length); | |||
return $string; | |||
} | |||
} | |||
// Fallback to mt_rand() | |||
$characters = '0123456789'; | |||
$characters .= 'abcdefghijklmnopqrstuvwxyz'; | |||
$charactersLength = strlen($characters) - 1; | |||
$pseudoByte = ""; | |||
// Select some random characters | |||
for ($i = 0; $i < $length; $i++) { | |||
$pseudoByte .= $characters[mt_rand(0, $charactersLength)]; | |||
} | |||
return $pseudoByte; | |||
return \OC::$server->getSecureRandom()->getMediumStrengthGenerator()->generate($length); | |||
} | |||
/** | |||
* Checks if a secure random number generator is available | |||
* | |||
* @return bool | |||
* @return true | |||
* @deprecated Function will be removed in the future and does only return true. | |||
*/ | |||
public static function secureRNGAvailable() { | |||
// Check openssl_random_pseudo_bytes | |||
if (function_exists('openssl_random_pseudo_bytes')) { | |||
openssl_random_pseudo_bytes(1, $strong); | |||
if ($strong == true) { | |||
return true; | |||
} | |||
} | |||
// Check /dev/urandom | |||
if (!self::runningOnWindows()) { | |||
$fp = @file_get_contents('/dev/urandom', false, null, 0, 1); | |||
if ($fp !== false) { | |||
return true; | |||
} | |||
} | |||
return false; | |||
return true; | |||
} | |||
/** |
@@ -0,0 +1,46 @@ | |||
<?php | |||
/** | |||
* Copyright (c) 2014 Lukas Reschke <lukas@owncloud.com> | |||
* This file is licensed under the Affero General Public License version 3 or | |||
* later. | |||
* See the COPYING-README file. | |||
*/ | |||
namespace OCP\Security; | |||
/** | |||
* Class Crypto provides a high-level encryption layer using AES-CBC. If no key has been provided | |||
* it will use the secret defined in config.php as key. Additionally the message will be HMAC'd. | |||
* | |||
* Usage: | |||
* $encryptWithDefaultPassword = \OC::$server->getCrypto()->encrypt('EncryptedText'); | |||
* $encryptWithCustomPassword = \OC::$server->getCrypto()->encrypt('EncryptedText', 'password'); | |||
* | |||
* @package OCP\Security | |||
*/ | |||
interface ICrypto { | |||
/** | |||
* @param string $message The message to authenticate | |||
* @param string $password Password to use (defaults to `secret` in config.php) | |||
* @return string Calculated HMAC | |||
*/ | |||
public function calculateHMAC($message, $password = ''); | |||
/** | |||
* Encrypts a value and adds an HMAC (Encrypt-Then-MAC) | |||
* @param string $plaintext | |||
* @param string $password Password to encrypt, if not specified the secret from config.php will be taken | |||
* @return string Authenticated ciphertext | |||
*/ | |||
public function encrypt($plaintext, $password = ''); | |||
/** | |||
* Decrypts a value and verifies the HMAC (Encrypt-Then-Mac) | |||
* @param string $authenticatedCiphertext | |||
* @param string $password Password to encrypt, if not specified the secret from config.php will be taken | |||
* @return string plaintext | |||
* @throws \Exception If the HMAC does not match | |||
*/ | |||
public function decrypt($authenticatedCiphertext, $password = ''); | |||
} |
@@ -0,0 +1,53 @@ | |||
<?php | |||
/** | |||
* Copyright (c) 2014 Lukas Reschke <lukas@owncloud.com> | |||
* This file is licensed under the Affero General Public License version 3 or | |||
* later. | |||
* See the COPYING-README file. | |||
*/ | |||
namespace OCP\Security; | |||
/** | |||
* Class SecureRandom provides a layer around RandomLib to generate | |||
* secure random numbers. | |||
* | |||
* Usage: | |||
* $rng = new \OC\Security\SecureRandom(); | |||
* $randomString = $rng->getMediumStrengthGenerator()->generateString(30); | |||
* | |||
* @package OCP\Security | |||
*/ | |||
interface ISecureRandom { | |||
/** | |||
* Convenience method to get a low strength random number generator. | |||
* | |||
* Low Strength should be used anywhere that random strings are needed | |||
* in a non-cryptographical setting. They are not strong enough to be | |||
* used as keys or salts. They are however useful for one-time use tokens. | |||
* | |||
* @return $this | |||
*/ | |||
public function getLowStrengthGenerator(); | |||
/** | |||
* Convenience method to get a medium strength random number generator. | |||
* | |||
* Medium Strength should be used for most needs of a cryptographic nature. | |||
* They are strong enough to be used as keys and salts. However, they do | |||
* take some time and resources to generate, so they should not be over-used | |||
* | |||
* @return $this | |||
*/ | |||
public function getMediumStrengthGenerator(); | |||
/** | |||
* Generate a random string of specified length. | |||
* @param string $length The length of the generated string | |||
* @param string $characters An optional list of characters to use | |||
* @return string | |||
* @throws \Exception | |||
*/ | |||
public function generate($length, $characters = ''); | |||
} |
@@ -0,0 +1,25 @@ | |||
<?php | |||
/** | |||
* Copyright (c) 2014 Lukas Reschke <lukas@owncloud.com> | |||
* This file is licensed under the Affero General Public License version 3 or | |||
* later. | |||
* See the COPYING-README file. | |||
*/ | |||
namespace OCP\Security; | |||
class StringUtils { | |||
/** | |||
* Compares whether two strings are equal. To prevent guessing of the string | |||
* length this is done by comparing two hashes against each other and afterwards | |||
* a comparison of the real string to prevent against the unlikely chance of | |||
* collisions. | |||
* @param string $expected The expected value | |||
* @param string $input The input to compare against | |||
* @return bool True if the two strings are equal, otherwise false. | |||
*/ | |||
public static function equals($expected, $input) { | |||
return \OC\Security\StringUtils::equals($expected, $input); | |||
} | |||
} |
@@ -505,6 +505,7 @@ class Util { | |||
* Generates a cryptographic secure pseudo-random string | |||
* @param int $length of the random string | |||
* @return string | |||
* @deprecated Use \OC::$server->getSecureRandom()->getMediumStrengthGenerator()->generate($length); instead | |||
*/ | |||
public static function generateRandomBytes($length = 30) { | |||
return \OC_Util::generateRandomBytes($length); |
@@ -0,0 +1,37 @@ | |||
<?php | |||
/** | |||
* Copyright (c) 2014 Lukas Reschke <lukas@owncloud.com> | |||
* This file is licensed under the Affero General Public License version 3 or | |||
* later. | |||
* See the COPYING-README file. | |||
*/ | |||
namespace OC\Repair; | |||
use OC\Hooks\BasicEmitter; | |||
use OC\RepairStep; | |||
use Sabre\DAV\Exception; | |||
class RepairConfig extends BasicEmitter implements RepairStep { | |||
public function getName() { | |||
return 'Repair config'; | |||
} | |||
/** | |||
* Updates the configuration after running an update | |||
*/ | |||
public function run() { | |||
$this->addSecret(); | |||
} | |||
/** | |||
* Adds a secret to config.php | |||
*/ | |||
private function addSecret() { | |||
if(\OC::$server->getConfig()->getSystemValue('secret', null) === null) { | |||
$secret = \OC::$server->getSecureRandom()->getMediumStrengthGenerator()->generate(48); | |||
\OC::$server->getConfig()->setSystemValue('secret', $secret); | |||
} | |||
} | |||
} |
@@ -0,0 +1,63 @@ | |||
<?php | |||
/** | |||
* Copyright (c) 2014 Lukas Reschke <lukas@owncloud.com> | |||
* This file is licensed under the Affero General Public License version 3 or | |||
* later. | |||
* See the COPYING-README file. | |||
*/ | |||
use \OC\Security\Crypto; | |||
class CryptoTest extends \PHPUnit_Framework_TestCase { | |||
function testDefaultEncrypt() { | |||
$stringToEncrypt = 'Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt.'; | |||
$crypto = new Crypto(); | |||
$ciphertext = $crypto->encrypt($stringToEncrypt); | |||
$this->assertEquals($stringToEncrypt, $crypto->decrypt($ciphertext)); | |||
$stringToEncrypt = ''; | |||
$ciphertext = $crypto->encrypt($stringToEncrypt); | |||
$this->assertEquals($stringToEncrypt, $crypto->decrypt($ciphertext)); | |||
} | |||
/** | |||
* @expectedException \Exception | |||
* @expectedExceptionMessage HMAC does not match. | |||
*/ | |||
function testWrongPassword() { | |||
$stringToEncrypt = 'Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt.'; | |||
$encryptCrypto = new Crypto(); | |||
$ciphertext = $encryptCrypto->encrypt($stringToEncrypt); | |||
$decryptCrypto = new Crypto(); | |||
$this->assertFalse($decryptCrypto->decrypt($ciphertext, 'A wrong password!')); | |||
} | |||
function testLaterDecryption() { | |||
$stringToEncrypt = 'Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt.'; | |||
$encryptedString = '560f5436ba864b9f12f7f7ca6d41c327554a6f2c0a160a03316b202af07c65163274993f3a46e7547c07ba89304f00594a2f3bd99f83859097c58049c39d0d4ade10e0de914ff0604961e7c849d0271ed6c0b23f984ba16e7d033e3305fb0910e7b6a2a65c988d17dbee71d8f953684d|d2kdFUspVjC0Y0sr|1a5feacf87eaa6869a6abdfba9a296e7bbad45b6ad89f7dce67cdc98e2da5dc4379cc672cc655e52bbf19599bf59482fbea13a73937697fa656bf10f3fc4f1aa'; | |||
$crypto = new Crypto(); | |||
$this->assertEquals($stringToEncrypt, $crypto->decrypt($encryptedString, 'ThisIsAVeryS3cur3P4ssw0rd')); | |||
} | |||
/** | |||
* @expectedException \Exception | |||
* @expectedExceptionMessage HMAC does not match. | |||
*/ | |||
function testWrongIV() { | |||
$encryptedString = '560f5436ba864b9f12f7f7ca6d41c327554a6f2c0a160a03316b202af07c65163274993f3a46e7547c07ba89304f00594a2f3bd99f83859097c58049c39d0d4ade10e0de914ff0604961e7c849d0271ed6c0b23f984ba16e7d033e3305fb0910e7b6a2a65c988d17dbee71d8f953684d|d2kdFUspVjC0o0sr|1a5feacf87eaa6869a6abdfba9a296e7bbad45b6ad89f7dce67cdc98e2da5dc4379cc672cc655e52bbf19599bf59482fbea13a73937697fa656bf10f3fc4f1aa'; | |||
$crypto = new Crypto(); | |||
$crypto->decrypt($encryptedString, 'ThisIsAVeryS3cur3P4ssw0rd'); | |||
} | |||
/** | |||
* @expectedException \Exception | |||
* @expectedExceptionMessage Authenticated ciphertext could not be decoded. | |||
*/ | |||
function testWrongParameters() { | |||
$encryptedString = '1|2'; | |||
$crypto = new Crypto(); | |||
$crypto->decrypt($encryptedString, 'ThisIsAVeryS3cur3P4ssw0rd'); | |||
} | |||
} |
@@ -0,0 +1,51 @@ | |||
<?php | |||
/** | |||
* Copyright (c) 2014 Lukas Reschke <lukas@owncloud.com> | |||
* This file is licensed under the Affero General Public License version 3 or | |||
* later. | |||
* See the COPYING-README file. | |||
*/ | |||
class SecureRandomTest extends \PHPUnit_Framework_TestCase { | |||
public function stringGenerationProvider() { | |||
return array( | |||
array(0, 0), | |||
array(1, 1), | |||
array(128, 128), | |||
array(256, 256), | |||
array(1024, 1024), | |||
array(2048, 2048), | |||
array(64000, 64000), | |||
); | |||
} | |||
/** | |||
* @dataProvider stringGenerationProvider | |||
*/ | |||
function testGetLowStrengthGeneratorLength($length, $expectedLength) { | |||
$rng = new \OC\Security\SecureRandom(); | |||
$generator = $rng->getLowStrengthGenerator(); | |||
$this->assertEquals($expectedLength, strlen($generator->generate($length))); | |||
} | |||
/** | |||
* @dataProvider stringGenerationProvider | |||
*/ | |||
function testMediumLowStrengthGeneratorLength($length, $expectedLength) { | |||
$rng = new \OC\Security\SecureRandom(); | |||
$generator = $rng->getMediumStrengthGenerator(); | |||
$this->assertEquals($expectedLength, strlen($generator->generate($length))); | |||
} | |||
/** | |||
* @expectedException \Exception | |||
* @expectedExceptionMessage Generator is not initialized | |||
*/ | |||
function testUninitializedGenerate() { | |||
$rng = new \OC\Security\SecureRandom(); | |||
$rng->generate(30); | |||
} | |||
} |
@@ -0,0 +1,21 @@ | |||
<?php | |||
/** | |||
* Copyright (c) 2014 Lukas Reschke <lukas@owncloud.com> | |||
* This file is licensed under the Affero General Public License version 3 or | |||
* later. | |||
* See the COPYING-README file. | |||
*/ | |||
use \OC\Security\StringUtils; | |||
class StringUtilsTest extends \PHPUnit_Framework_TestCase { | |||
function testEquals() { | |||
$this->assertTrue(StringUtils::equals('GpKY9fSnWRaeFNJbES99zVGvA', 'GpKY9fSnWRaeFNJbES99zVGvA')); | |||
$this->assertFalse(StringUtils::equals('GpKY9fSnWNJbES99zVGvA', 'GpKY9fSnWRaeFNJbES99zVGvA')); | |||
$this->assertFalse(StringUtils::equals('', 'GpKY9fSnWRaeFNJbES99zVGvA')); | |||
$this->assertFalse(StringUtils::equals('GpKY9fSnWRaeFNJbES99zVGvA', '')); | |||
$this->assertTrue(StringUtils::equals('', '')); | |||
} | |||
} |