aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
m---------3rdparty0
-rwxr-xr-xconfig/config.sample.php3
-rw-r--r--core/setup/controller.php1
-rw-r--r--core/templates/installation.php7
-rw-r--r--lib/private/repair.php1
-rw-r--r--lib/private/security/crypto.php115
-rw-r--r--lib/private/security/securerandom.php79
-rw-r--r--lib/private/security/stringutils.php42
-rw-r--r--lib/private/server.php26
-rw-r--r--lib/private/setup.php17
-rwxr-xr-xlib/private/util.php46
-rw-r--r--lib/public/security/icrypto.php46
-rw-r--r--lib/public/security/isecurerandom.php61
-rw-r--r--lib/public/security/stringutils.php25
-rw-r--r--lib/public/util.php1
-rw-r--r--lib/repair/repairconfig.php37
-rw-r--r--tests/lib/security/crypto.php70
-rw-r--r--tests/lib/security/securerandom.php76
-rw-r--r--tests/lib/security/stringutils.php38
-rw-r--r--version.php2
20 files changed, 638 insertions, 55 deletions
diff --git a/3rdparty b/3rdparty
-Subproject 57245d2a64c99aab8a438f909988e7a4ffef5b2
+Subproject 82d02dd48ad11312bd740c57720dc84b4d66fa8
diff --git a/config/config.sample.php b/config/config.sample.php
index d232e18ab08..71105a8b10d 100755
--- a/config/config.sample.php
+++ b/config/config.sample.php
@@ -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,
diff --git a/core/setup/controller.php b/core/setup/controller.php
index 91b90e0adef..5da94e83ccc 100644
--- a/core/setup/controller.php
+++ b/core/setup/controller.php
@@ -153,7 +153,6 @@ class Controller {
'hasMSSQL' => $hasMSSQL,
'databases' => $databases,
'directory' => $datadir,
- 'secureRNG' => \OC_Util::secureRNGAvailable(),
'htaccessWorking' => $htaccessWorking,
'vulnerableToNullByte' => $vulnerableToNullByte,
'errors' => $errors,
diff --git a/core/templates/installation.php b/core/templates/installation.php
index f934e3a86c2..b74d4caf107 100644
--- a/core/templates/installation.php
+++ b/core/templates/installation.php
@@ -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>
diff --git a/lib/private/repair.php b/lib/private/repair.php
index 46b5ae46399..4ff446f8608 100644
--- a/lib/private/repair.php
+++ b/lib/private/repair.php
@@ -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(),
);
}
diff --git a/lib/private/security/crypto.php b/lib/private/security/crypto.php
new file mode 100644
index 00000000000..6fdff8d92a2
--- /dev/null
+++ b/lib/private/security/crypto.php
@@ -0,0 +1,115 @@
+<?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\ISecureRandom;
+use OCP\Security\StringUtils;
+use OCP\IConfig;
+
+/**
+ * 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;
+ /** @var IConfig */
+ private $config;
+ /** @var ISecureRandom */
+ private $random;
+
+ function __construct(IConfig $config, ISecureRandom $random) {
+ $this->cipher = new Crypt_AES();
+ $this->config = $config;
+ $this->random = $random;
+ }
+
+ /**
+ * @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 = $this->config->getSystemValue('secret');
+ }
+
+ // Append an "a" behind the password and hash it to prevent reusing the same password as for encryption
+ $password = hash('sha512', $password . 'a');
+
+ $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 = $this->config->getSystemValue('secret');
+ }
+ $this->cipher->setPassword($password);
+
+ $iv = $this->random->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 = $this->config->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);
+ }
+
+}
diff --git a/lib/private/security/securerandom.php b/lib/private/security/securerandom.php
new file mode 100644
index 00000000000..2402e863fb0
--- /dev/null
+++ b/lib/private/security/securerandom.php
@@ -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);
+ }
+}
diff --git a/lib/private/security/stringutils.php b/lib/private/security/stringutils.php
new file mode 100644
index 00000000000..33a3a708012
--- /dev/null
+++ b/lib/private/security/stringutils.php
@@ -0,0 +1,42 @@
+<?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.
+ *
+ * Be aware that this function may leak whether the string to compare have a different
+ * length.
+ *
+ * @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()->getLowStrengthGenerator()->generate(10);
+
+ if(hash('sha512', $expected.$randomString) === hash('sha512', $input.$randomString)) {
+ if($expected === $input) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+} \ No newline at end of file
diff --git a/lib/private/server.php b/lib/private/server.php
index 5d40f1327f6..71a098f9074 100644
--- a/lib/private/server.php
+++ b/lib/private/server.php
@@ -10,6 +10,8 @@ use OC\Security\CertificateManager;
use OC\DB\ConnectionWrapper;
use OC\Files\Node\Root;
use OC\Files\View;
+use OC\Security\Crypto;
+use OC\Security\SecureRandom;
use OCP\IServerContainer;
use OCP\ISession;
@@ -201,6 +203,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(\OC::$server->getConfig(), \OC::$server->getSecureRandom());
+ });
$this->registerService('Db', function ($c) {
return new Db();
});
@@ -468,6 +476,24 @@ class Server extends SimpleContainer implements IServerContainer {
}
/**
+ * 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
*
* @return \OCP\IDb
diff --git a/lib/private/setup.php b/lib/private/setup.php
index 2e23aae8838..7ea4c1bcd26 100644
--- a/lib/private/setup.php
+++ b/lib/private/setup.php
@@ -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);
diff --git a/lib/private/util.php b/lib/private/util.php
index adb7fb83d28..8fae5189ca2 100755
--- a/lib/private/util.php
+++ b/lib/private/util.php
@@ -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,54 +1208,20 @@ class OC_Util {
*
* @param int $length of the random string
* @return string
- * @throws Exception when no secure RNG source is available
- * 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;
- }
- }
-
- // No random numbers are better then bad random numbers
- throw new \Exception('No secure random number generator available, please install the php-openssl extension');
+ 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;
}
/**
diff --git a/lib/public/security/icrypto.php b/lib/public/security/icrypto.php
new file mode 100644
index 00000000000..e55eea8dd66
--- /dev/null
+++ b/lib/public/security/icrypto.php
@@ -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 = '');
+}
diff --git a/lib/public/security/isecurerandom.php b/lib/public/security/isecurerandom.php
new file mode 100644
index 00000000000..3de60f8d717
--- /dev/null
+++ b/lib/public/security/isecurerandom.php
@@ -0,0 +1,61 @@
+<?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 {
+
+ /**
+ * Flags for characters that can be used for <code>generate($length, $characters)</code>
+ */
+ const CHAR_UPPER = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
+ const CHAR_LOWER = 'abcdefghijklmnopqrstuvwxyz';
+ const CHAR_DIGITS = '0123456789';
+ const CHAR_SYMBOLS = '!\"#$%&\\\'()* +,-./:;<=>?@[\]^_`{|}~';
+
+ /**
+ * 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 = '');
+}
diff --git a/lib/public/security/stringutils.php b/lib/public/security/stringutils.php
new file mode 100644
index 00000000000..8e7b132724e
--- /dev/null
+++ b/lib/public/security/stringutils.php
@@ -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);
+ }
+}
diff --git a/lib/public/util.php b/lib/public/util.php
index bc1b90a2c89..2f657facfe8 100644
--- a/lib/public/util.php
+++ b/lib/public/util.php
@@ -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);
diff --git a/lib/repair/repairconfig.php b/lib/repair/repairconfig.php
new file mode 100644
index 00000000000..e09d8e8fe7a
--- /dev/null
+++ b/lib/repair/repairconfig.php
@@ -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);
+ }
+ }
+}
diff --git a/tests/lib/security/crypto.php b/tests/lib/security/crypto.php
new file mode 100644
index 00000000000..0f89253839e
--- /dev/null
+++ b/tests/lib/security/crypto.php
@@ -0,0 +1,70 @@
+<?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 {
+
+ public function defaultEncryptionProvider()
+ {
+ return array(
+ array('Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt.'),
+ array(''),
+ array('我看这本书。 我看這本書')
+ );
+ }
+
+ /** @var Crypto */
+ protected $crypto;
+
+ protected function setUp() {
+ $this->crypto = new Crypto(\OC::$server->getConfig(), \OC::$server->getSecureRandom());
+ }
+
+ /**
+ * @dataProvider defaultEncryptionProvider
+ */
+ function testDefaultEncrypt($stringToEncrypt) {
+ $ciphertext = $this->crypto->encrypt($stringToEncrypt);
+ $this->assertEquals($stringToEncrypt, $this->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.';
+ $ciphertext = $this->crypto->encrypt($stringToEncrypt);
+ $this->crypto->decrypt($ciphertext, 'A wrong password!');
+ }
+
+ function testLaterDecryption() {
+ $stringToEncrypt = 'Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt.';
+ $encryptedString = '44a35023cca2e7a6125e06c29fc4b2ad9d8a33d0873a8b45b0de4ef9284f260c6c46bf25dc62120644c59b8bafe4281ddc47a70c35ae6c29ef7a63d79eefacc297e60b13042ac582733598d0a6b4de37311556bb5c480fd2633de4e6ebafa868c2d1e2d80a5d24f9660360dba4d6e0c8|lhrFgK0zd9U160Wo|a75e57ab701f9124e1113543fd1dc596f21e20d456a0d1e813d5a8aaec9adcb11213788e96598b67fe9486a9f0b99642c18296d0175db44b1ae426e4e91080ee';
+ $this->assertEquals($stringToEncrypt, $this->crypto->decrypt($encryptedString, 'ThisIsAVeryS3cur3P4ssw0rd'));
+ }
+
+ /**
+ * @expectedException \Exception
+ * @expectedExceptionMessage HMAC does not match.
+ */
+ function testWrongIV() {
+ $encryptedString = '560f5436ba864b9f12f7f7ca6d41c327554a6f2c0a160a03316b202af07c65163274993f3a46e7547c07ba89304f00594a2f3bd99f83859097c58049c39d0d4ade10e0de914ff0604961e7c849d0271ed6c0b23f984ba16e7d033e3305fb0910e7b6a2a65c988d17dbee71d8f953684d|d2kdFUspVjC0o0sr|1a5feacf87eaa6869a6abdfba9a296e7bbad45b6ad89f7dce67cdc98e2da5dc4379cc672cc655e52bbf19599bf59482fbea13a73937697fa656bf10f3fc4f1aa';
+ $this->crypto->decrypt($encryptedString, 'ThisIsAVeryS3cur3P4ssw0rd');
+ }
+
+ /**
+ * @expectedException \Exception
+ * @expectedExceptionMessage Authenticated ciphertext could not be decoded.
+ */
+ function testWrongParameters() {
+ $encryptedString = '1|2';
+ $this->crypto->decrypt($encryptedString, 'ThisIsAVeryS3cur3P4ssw0rd');
+ }
+}
diff --git a/tests/lib/security/securerandom.php b/tests/lib/security/securerandom.php
new file mode 100644
index 00000000000..2920077fa1d
--- /dev/null
+++ b/tests/lib/security/securerandom.php
@@ -0,0 +1,76 @@
+<?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\SecureRandom;
+
+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),
+ );
+ }
+
+ public static function charCombinations() {
+ return array(
+ array('CHAR_LOWER', '[a-z]'),
+ array('CHAR_UPPER', '[A-Z]'),
+ array('CHAR_DIGITS', '[0-9]'),
+ );
+ }
+
+ /** @var SecureRandom */
+ protected $rng;
+
+ protected function setUp() {
+ $this->rng = new \OC\Security\SecureRandom();
+ }
+
+ /**
+ * @dataProvider stringGenerationProvider
+ */
+ function testGetLowStrengthGeneratorLength($length, $expectedLength) {
+ $generator = $this->rng->getLowStrengthGenerator();
+
+ $this->assertEquals($expectedLength, strlen($generator->generate($length)));
+ }
+
+ /**
+ * @dataProvider stringGenerationProvider
+ */
+ function testMediumLowStrengthGeneratorLength($length, $expectedLength) {
+ $generator = $this->rng->getMediumStrengthGenerator();
+
+ $this->assertEquals($expectedLength, strlen($generator->generate($length)));
+ }
+
+ /**
+ * @expectedException \Exception
+ * @expectedExceptionMessage Generator is not initialized
+ */
+ function testUninitializedGenerate() {
+ $this->rng->generate(30);
+ }
+
+ /**
+ * @dataProvider charCombinations
+ */
+ public function testScheme($charName, $chars) {
+ $generator = $this->rng->getMediumStrengthGenerator();
+ $scheme = constant('OCP\Security\ISecureRandom::' . $charName);
+ $randomString = $generator->generate(100, $scheme);
+ $matchesRegex = preg_match('/^'.$chars.'+$/', $randomString);
+ $this->assertSame(1, $matchesRegex);
+ }
+}
diff --git a/tests/lib/security/stringutils.php b/tests/lib/security/stringutils.php
new file mode 100644
index 00000000000..039f3d3756a
--- /dev/null
+++ b/tests/lib/security/stringutils.php
@@ -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.
+ */
+
+use \OC\Security\StringUtils;
+
+class StringUtilsTest extends \PHPUnit_Framework_TestCase {
+
+ public function dataProvider()
+ {
+ return array(
+ array('Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt.', 'Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt.'),
+ array('', ''),
+ array('我看这本书。 我看這本書', '我看这本书。 我看這本書'),
+ array('GpKY9fSnWNJbES99zVGvA', 'GpKY9fSnWNJbES99zVGvA')
+ );
+ }
+
+ /**
+ * @dataProvider dataProvider
+ */
+ function testWrongEquals($string) {
+ $this->assertFalse(StringUtils::equals($string, 'A Completely Wrong String'));
+ $this->assertFalse(StringUtils::equals($string, null));
+ }
+
+ /**
+ * @dataProvider dataProvider
+ */
+ function testTrueEquals($string, $expected) {
+ $this->assertTrue(StringUtils::equals($string, $expected));
+ }
+
+}
diff --git a/version.php b/version.php
index 24429434116..4421a06bea0 100644
--- a/version.php
+++ b/version.php
@@ -3,7 +3,7 @@
// We only can count up. The 4. digit is only for the internal patchlevel to trigger DB upgrades
// between betas, final and RCs. This is _not_ the public version number. Reset minor/patchlevel
// when updating major/minor version number.
-$OC_Version=array(7, 8, 0, 0);
+$OC_Version=array(7, 8, 1, 0);
// The human readable string
$OC_VersionString='8.0 pre alpha';