summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--apps/files_encryption/hooks/hooks.php3
-rwxr-xr-xapps/files_encryption/lib/crypt.php117
-rw-r--r--apps/files_encryption/lib/util.php99
-rwxr-xr-xapps/files_encryption/tests/crypt.php258
-rw-r--r--apps/files_encryption/tests/keymanager.php18
5 files changed, 50 insertions, 445 deletions
diff --git a/apps/files_encryption/hooks/hooks.php b/apps/files_encryption/hooks/hooks.php
index 07da839e8a2..a37bd5728c1 100644
--- a/apps/files_encryption/hooks/hooks.php
+++ b/apps/files_encryption/hooks/hooks.php
@@ -30,9 +30,6 @@ use OC\Files\Filesystem;
*/
class Hooks {
- // TODO: use passphrase for encrypting private key that is separate to
- // the login password
-
/**
* @brief Startup encryption backend upon user login
* @note This method should never be called for users using client side encryption
diff --git a/apps/files_encryption/lib/crypt.php b/apps/files_encryption/lib/crypt.php
index c3e88e5944e..3947b7d0c3b 100755
--- a/apps/files_encryption/lib/crypt.php
+++ b/apps/files_encryption/lib/crypt.php
@@ -25,7 +25,6 @@
namespace OCA\Encryption;
-//require_once '../3rdparty/Crypt_Blowfish/Blowfish.php';
require_once realpath(dirname(__FILE__) . '/../3rdparty/Crypt_Blowfish/Blowfish.php');
/**
@@ -86,7 +85,7 @@ class Crypt {
* blocks with encryption alone, hence padding is added to achieve the
* required length.
*/
- public static function addPadding($data) {
+ private static function addPadding($data) {
$padded = $data . 'xx';
@@ -99,7 +98,7 @@ class Crypt {
* @param string $padded padded data to remove padding from
* @return string unpadded data on success, false on error
*/
- public static function removePadding($padded) {
+ private static function removePadding($padded) {
if (substr($padded, -2) === 'xx') {
@@ -207,7 +206,7 @@ class Crypt {
* @param string $passphrase
* @return string encrypted file content
*/
- public static function encrypt($plainContent, $iv, $passphrase = '') {
+ private static function encrypt($plainContent, $iv, $passphrase = '') {
if ($encryptedContent = openssl_encrypt($plainContent, 'AES-128-CFB', $passphrase, false, $iv)) {
return $encryptedContent;
@@ -228,7 +227,7 @@ class Crypt {
* @throws \Exception
* @return string decrypted file content
*/
- public static function decrypt($encryptedContent, $iv, $passphrase) {
+ private static function decrypt($encryptedContent, $iv, $passphrase) {
if ($plainContent = openssl_decrypt($encryptedContent, 'AES-128-CFB', $passphrase, false, $iv)) {
@@ -248,7 +247,7 @@ class Crypt {
* @param string $iv IV to be concatenated
* @returns string concatenated content
*/
- public static function concatIv($content, $iv) {
+ private static function concatIv($content, $iv) {
$combined = $content . '00iv00' . $iv;
@@ -261,7 +260,7 @@ class Crypt {
* @param string $catFile concatenated data to be split
* @returns array keys: encrypted, iv
*/
- public static function splitIv($catFile) {
+ private static function splitIv($catFile) {
// Fetch encryption metadata from end of file
$meta = substr($catFile, -22);
@@ -378,34 +377,6 @@ class Crypt {
}
-
- /**
- * @brief Creates symmetric keyfile content using a generated key
- * @param string $plainContent content to be encrypted
- * @returns array keys: key, encrypted
- * @note symmetricDecryptFileContent() can be used to decrypt files created using this method
- *
- * This function decrypts a file
- */
- public static function symmetricEncryptFileContentKeyfile($plainContent) {
-
- $key = self::generateKey();
-
- if ($encryptedContent = self::symmetricEncryptFileContent($plainContent, $key)) {
-
- return array(
- 'key' => $key,
- 'encrypted' => $encryptedContent
- );
-
- } else {
-
- return false;
-
- }
-
- }
-
/**
* @brief Create asymmetrically encrypted keyfile content using a generated key
* @param string $plainContent content to be encrypted
@@ -489,42 +460,10 @@ class Crypt {
}
/**
- * @brief Asymetrically encrypt a string using a public key
- * @param $plainContent
- * @param $publicKey
- * @return string encrypted file
- */
- public static function keyEncrypt($plainContent, $publicKey) {
-
- openssl_public_encrypt($plainContent, $encryptedContent, $publicKey);
-
- return $encryptedContent;
-
- }
-
- /**
- * @brief Asymetrically decrypt a file using a private key
- * @param $encryptedContent
- * @param $privatekey
- * @return string decrypted file
- */
- public static function keyDecrypt($encryptedContent, $privatekey) {
-
- $result = @openssl_private_decrypt($encryptedContent, $plainContent, $privatekey);
-
- if ($result) {
- return $plainContent;
- }
-
- return $result;
-
- }
-
- /**
* @brief Generates a pseudo random initialisation vector
* @return String $iv generated IV
*/
- public static function generateIv() {
+ private static function generateIv() {
if ($random = openssl_random_pseudo_bytes(12, $strong)) {
@@ -550,7 +489,7 @@ class Crypt {
}
/**
- * @brief Generate a pseudo random 1024kb ASCII key
+ * @brief Generate a pseudo random 1024kb ASCII key, used as file key
* @returns $key Generated key
*/
public static function generateKey() {
@@ -576,13 +515,13 @@ class Crypt {
}
/**
- * @brief Get the blowfish encryption handeler for a key
+ * @brief Get the blowfish encryption handler for a key
* @param $key string (optional)
* @return \Crypt_Blowfish blowfish object
*
- * if the key is left out, the default handeler will be used
+ * if the key is left out, the default handler will be used
*/
- public static function getBlowfish($key = '') {
+ private static function getBlowfish($key = '') {
if ($key) {
@@ -597,38 +536,6 @@ class Crypt {
}
/**
- * @param $passphrase
- * @return mixed
- */
- public static function legacyCreateKey($passphrase) {
-
- // Generate a random integer
- $key = mt_rand(10000, 99999) . mt_rand(10000, 99999) . mt_rand(10000, 99999) . mt_rand(10000, 99999);
-
- // Encrypt the key with the passphrase
- $legacyEncKey = self::legacyEncrypt($key, $passphrase);
-
- return $legacyEncKey;
-
- }
-
- /**
- * @brief encrypts content using legacy blowfish system
- * @param string $content the cleartext message you want to encrypt
- * @param string $passphrase
- * @returns string encrypted content
- *
- * This function encrypts an content
- */
- public static function legacyEncrypt($content, $passphrase = '') {
-
- $bf = self::getBlowfish($passphrase);
-
- return $bf->encrypt($content);
-
- }
-
- /**
* @brief decrypts content using legacy blowfish system
* @param string $content the cleartext message you want to decrypt
* @param string $passphrase
@@ -665,4 +572,4 @@ class Crypt {
}
}
-} \ No newline at end of file
+}
diff --git a/apps/files_encryption/lib/util.php b/apps/files_encryption/lib/util.php
index 50e823585d7..c6fc134fe42 100644
--- a/apps/files_encryption/lib/util.php
+++ b/apps/files_encryption/lib/util.php
@@ -21,30 +21,6 @@
*
*/
-# Bugs
-# ----
-# Sharing a file to a user without encryption set up will not provide them with access but won't notify the sharer
-# Sharing all files to admin for recovery purposes still in progress
-# Possibly public links are broken (not tested since last merge of master)
-
-
-# Missing features
-# ----------------
-# Make sure user knows if large files weren't encrypted
-
-
-# Test
-# ----
-# Test that writing files works when recovery is enabled, and sharing API is disabled
-# Test trashbin support
-
-
-// Old Todo:
-// - Crypt/decrypt button in the userinterface
-// - Setting if crypto should be on by default
-// - Add a setting "DonĀ“t encrypt files larger than xx because of performance
-// reasons"
-
namespace OCA\Encryption;
/**
@@ -57,45 +33,6 @@ namespace OCA\Encryption;
class Util {
- // Web UI:
-
- //// DONE: files created via web ui are encrypted
- //// DONE: file created & encrypted via web ui are readable in web ui
- //// DONE: file created & encrypted via web ui are readable via webdav
-
-
- // WebDAV:
-
- //// DONE: new data filled files added via webdav get encrypted
- //// DONE: new data filled files added via webdav are readable via webdav
- //// DONE: reading unencrypted files when encryption is enabled works via
- //// webdav
- //// DONE: files created & encrypted via web ui are readable via webdav
-
-
- // Legacy support:
-
- //// DONE: add method to check if file is encrypted using new system
- //// DONE: add method to check if file is encrypted using old system
- //// DONE: add method to fetch legacy key
- //// DONE: add method to decrypt legacy encrypted data
-
-
- // Admin UI:
-
- //// DONE: changing user password also changes encryption passphrase
-
- //// TODO: add support for optional recovery in case of lost passphrase / keys
- //// TODO: add admin optional required long passphrase for users
- //// TODO: implement flag system to allow user to specify encryption by folder, subfolder, etc.
-
-
- // Integration testing:
-
- //// TODO: test new encryption with versioning
- //// DONE: test new encryption with sharing
- //// TODO: test new encryption with proxies
-
const MIGRATION_COMPLETED = 1; // migration to new encryption completed
const MIGRATION_IN_PROGRESS = -1; // migration is running
const MIGRATION_OPEN = 0; // user still needs to be migrated
@@ -878,46 +815,22 @@ class Util {
}
/**
- * @brief Decrypt a keyfile without knowing how it was encrypted
+ * @brief Decrypt a keyfile
* @param string $filePath
- * @param string $fileOwner
* @param string $privateKey
* @return bool|string
- * @note Checks whether file was encrypted with openssl_seal or
- * openssl_encrypt, and decrypts accrdingly
- * @note This was used when 2 types of encryption for keyfiles was used,
- * but now we've switched to exclusively using openssl_seal()
*/
- public function decryptUnknownKeyfile($filePath, $fileOwner, $privateKey) {
+ private function decryptKeyfile($filePath, $privateKey) {
// Get the encrypted keyfile
- // NOTE: the keyfile format depends on how it was encrypted! At
- // this stage we don't know how it was encrypted
$encKeyfile = Keymanager::getFileKey($this->view, $this->userId, $filePath);
- // We need to decrypt the keyfile
- // Has the file been shared yet?
- if (
- $this->userId === $fileOwner
- && !Keymanager::getShareKey($this->view, $this->userId, $filePath) // NOTE: we can't use isShared() here because it's a post share hook so it always returns true
- ) {
-
- // The file has no shareKey, and its keyfile must be
- // decrypted conventionally
- $plainKeyfile = Crypt::keyDecrypt($encKeyfile, $privateKey);
+ // The file has a shareKey and must use it for decryption
+ $shareKey = Keymanager::getShareKey($this->view, $this->userId, $filePath);
-
- } else {
-
- // The file has a shareKey and must use it for decryption
- $shareKey = Keymanager::getShareKey($this->view, $this->userId, $filePath);
-
- $plainKeyfile = Crypt::multiKeyDecrypt($encKeyfile, $shareKey, $privateKey);
-
- }
+ $plainKeyfile = Crypt::multiKeyDecrypt($encKeyfile, $shareKey, $privateKey);
return $plainKeyfile;
-
}
/**
@@ -956,7 +869,7 @@ class Util {
$fileOwner = \OC\Files\Filesystem::getOwner($filePath);
// Decrypt keyfile
- $plainKeyfile = $this->decryptUnknownKeyfile($filePath, $fileOwner, $privateKey);
+ $plainKeyfile = $this->decryptKeyfile($filePath, $privateKey);
// Re-enc keyfile to (additional) sharekeys
$multiEncKey = Crypt::multiKeyEncrypt($plainKeyfile, $userPubKeys);
diff --git a/apps/files_encryption/tests/crypt.php b/apps/files_encryption/tests/crypt.php
index 9b97df22d16..2330a45be84 100755
--- a/apps/files_encryption/tests/crypt.php
+++ b/apps/files_encryption/tests/crypt.php
@@ -115,130 +115,6 @@ class Test_Encryption_Crypt extends \PHPUnit_Framework_TestCase {
}
- /**
- * @large
- * @return String
- */
- function testGenerateIv() {
-
- $iv = Encryption\Crypt::generateIv();
-
- $this->assertEquals(16, strlen($iv));
-
- return $iv;
-
- }
-
- /**
- * @large
- * @depends testGenerateIv
- */
- function testConcatIv($iv) {
-
- $catFile = Encryption\Crypt::concatIv($this->dataLong, $iv);
-
- // Fetch encryption metadata from end of file
- $meta = substr($catFile, -22);
-
- $identifier = substr($meta, 0, 6);
-
- // Fetch IV from end of file
- $foundIv = substr($meta, 6);
-
- $this->assertEquals('00iv00', $identifier);
-
- $this->assertEquals($iv, $foundIv);
-
- // Remove IV and IV identifier text to expose encrypted content
- $data = substr($catFile, 0, -22);
-
- $this->assertEquals($this->dataLong, $data);
-
- return array(
- 'iv' => $iv
- ,
- 'catfile' => $catFile
- );
-
- }
-
- /**
- * @medium
- * @depends testConcatIv
- */
- function testSplitIv($testConcatIv) {
-
- // Split catfile into components
- $splitCatfile = Encryption\Crypt::splitIv($testConcatIv['catfile']);
-
- // Check that original IV and split IV match
- $this->assertEquals($testConcatIv['iv'], $splitCatfile['iv']);
-
- // Check that original data and split data match
- $this->assertEquals($this->dataLong, $splitCatfile['encrypted']);
-
- }
-
- /**
- * @medium
- * @return string padded
- */
- function testAddPadding() {
-
- $padded = Encryption\Crypt::addPadding($this->dataLong);
-
- $padding = substr($padded, -2);
-
- $this->assertEquals('xx', $padding);
-
- return $padded;
-
- }
-
- /**
- * @medium
- * @depends testAddPadding
- */
- function testRemovePadding($padded) {
-
- $noPadding = Encryption\Crypt::RemovePadding($padded);
-
- $this->assertEquals($this->dataLong, $noPadding);
-
- }
-
- /**
- * @medium
- */
- function testEncrypt() {
-
- $random = openssl_random_pseudo_bytes(13);
-
- $iv = substr(base64_encode($random), 0, -4); // i.e. E5IG033j+mRNKrht
-
- $crypted = Encryption\Crypt::encrypt($this->dataUrl, $iv, 'hat');
-
- $this->assertNotEquals($this->dataUrl, $crypted);
-
- }
-
- /**
- * @medium
- */
- function testDecrypt() {
-
- $random = openssl_random_pseudo_bytes(13);
-
- $iv = substr(base64_encode($random), 0, -4); // i.e. E5IG033j+mRNKrht
-
- $crypted = Encryption\Crypt::encrypt($this->dataUrl, $iv, 'hat');
-
- $decrypt = Encryption\Crypt::decrypt($crypted, $iv, 'hat');
-
- $this->assertEquals($this->dataUrl, $decrypt);
-
- }
-
function testDecryptPrivateKey() {
// test successful decrypt
@@ -364,14 +240,12 @@ class Test_Encryption_Crypt extends \PHPUnit_Framework_TestCase {
//print_r($r);
// Join IVs and their respective data chunks
- $e = array(
- $r[0] . $r[1],
- $r[2] . $r[3],
- $r[4] . $r[5],
- $r[6] . $r[7],
- $r[8] . $r[9],
- $r[10] . $r[11]
- ); //.$r[11], $r[12].$r[13], $r[14] );
+ $e = array();
+ $i = 0;
+ while ($i < count($r)-1) {
+ $e[] = $r[$i] . $r[$i+1];
+ $i = $i + 2;
+ }
//print_r($e);
@@ -469,24 +343,6 @@ class Test_Encryption_Crypt extends \PHPUnit_Framework_TestCase {
/**
* @medium
*/
- function testSymmetricEncryptFileContentKeyfile() {
-
- # TODO: search in keyfile for actual content as IV will ensure this test always passes
-
- $crypted = Encryption\Crypt::symmetricEncryptFileContentKeyfile($this->dataUrl);
-
- $this->assertNotEquals($this->dataUrl, $crypted['encrypted']);
-
-
- $decrypt = Encryption\Crypt::symmetricDecryptFileContent($crypted['encrypted'], $crypted['key']);
-
- $this->assertEquals($this->dataUrl, $decrypt);
-
- }
-
- /**
- * @medium
- */
function testIsEncryptedContent() {
$this->assertFalse(Encryption\Crypt::isCatfileContent($this->dataUrl));
@@ -528,47 +384,11 @@ class Test_Encryption_Crypt extends \PHPUnit_Framework_TestCase {
/**
* @medium
- */
- function testKeyEncrypt() {
-
- // Generate keypair
- $pair1 = Encryption\Crypt::createKeypair();
-
- // Encrypt data
- $crypted = Encryption\Crypt::keyEncrypt($this->dataUrl, $pair1['publicKey']);
-
- $this->assertNotEquals($this->dataUrl, $crypted);
-
- // Decrypt data
- $decrypt = Encryption\Crypt::keyDecrypt($crypted, $pair1['privateKey']);
-
- $this->assertEquals($this->dataUrl, $decrypt);
-
- }
-
- /**
- * @medium
- * @brief test encryption using legacy blowfish method
- */
- function testLegacyEncryptShort() {
-
- $crypted = Encryption\Crypt::legacyEncrypt($this->dataShort, $this->pass);
-
- $this->assertNotEquals($this->dataShort, $crypted);
-
- # TODO: search inencrypted text for actual content to ensure it
- # genuine transformation
-
- return $crypted;
-
- }
-
- /**
- * @medium
* @brief test decryption using legacy blowfish method
- * @depends testLegacyEncryptShort
*/
- function testLegacyDecryptShort($crypted) {
+ function testLegacyDecryptShort() {
+
+ $crypted = $this->legacyEncrypt($this->dataShort, $this->pass);
$decrypted = Encryption\Crypt::legacyBlockDecrypt($crypted, $this->pass);
@@ -578,53 +398,15 @@ class Test_Encryption_Crypt extends \PHPUnit_Framework_TestCase {
/**
* @medium
- * @brief test encryption using legacy blowfish method
- */
- function testLegacyEncryptLong() {
-
- $crypted = Encryption\Crypt::legacyEncrypt($this->dataLong, $this->pass);
-
- $this->assertNotEquals($this->dataLong, $crypted);
-
- # TODO: search inencrypted text for actual content to ensure it
- # genuine transformation
-
- return $crypted;
-
- }
-
- /**
- * @medium
* @brief test decryption using legacy blowfish method
- * @depends testLegacyEncryptLong
*/
- function testLegacyDecryptLong($crypted) {
+ function testLegacyDecryptLong() {
+
+ $crypted = $this->legacyEncrypt($this->dataLong, $this->pass);
$decrypted = Encryption\Crypt::legacyBlockDecrypt($crypted, $this->pass);
$this->assertEquals($this->dataLong, $decrypted);
-
- $this->assertFalse(Encryption\Crypt::getBlowfish(''));
- }
-
- /**
- * @medium
- * @brief test generation of legacy encryption key
- * @depends testLegacyDecryptShort
- */
- function testLegacyCreateKey() {
-
- // Create encrypted key
- $encKey = Encryption\Crypt::legacyCreateKey($this->pass);
-
- // Decrypt key
- $key = Encryption\Crypt::legacyBlockDecrypt($encKey, $this->pass);
-
- $this->assertTrue(is_numeric($key));
-
- // Check that key is correct length
- $this->assertEquals(20, strlen($key));
-
}
/**
@@ -871,4 +653,20 @@ class Test_Encryption_Crypt extends \PHPUnit_Framework_TestCase {
// tear down
$view->unlink($filename);
}
+
+
+ /**
+ * @brief encryption using legacy blowfish method
+ * @param $data string data to encrypt
+ * @param $passwd string password
+ * @return string
+ */
+ function legacyEncrypt($data, $passwd) {
+
+ $bf = new \Crypt_Blowfish($passwd);
+ $crypted = $bf->encrypt($data);
+
+ return $crypted;
+ }
+
}
diff --git a/apps/files_encryption/tests/keymanager.php b/apps/files_encryption/tests/keymanager.php
index b644856d95d..13f8c3197c7 100644
--- a/apps/files_encryption/tests/keymanager.php
+++ b/apps/files_encryption/tests/keymanager.php
@@ -141,10 +141,7 @@ class Test_Encryption_Keymanager extends \PHPUnit_Framework_TestCase {
*/
function testSetFileKey() {
- # NOTE: This cannot be tested until we are able to break out
- # of the FileSystemView data directory root
-
- $key = Encryption\Crypt::symmetricEncryptFileContentKeyfile($this->randomKey, 'hat');
+ $key = $this->randomKey;
$file = 'unittest-' . time() . '.txt';
@@ -152,24 +149,17 @@ class Test_Encryption_Keymanager extends \PHPUnit_Framework_TestCase {
$proxyStatus = \OC_FileProxy::$enabled;
\OC_FileProxy::$enabled = false;
- $this->view->file_put_contents($this->userId . '/files/' . $file, $key['encrypted']);
+ $this->view->file_put_contents($this->userId . '/files/' . $file, $this->dataShort);
- // Re-enable proxy - our work is done
- \OC_FileProxy::$enabled = $proxyStatus;
+ Encryption\Keymanager::setFileKey($this->view, $file, $this->userId, $key);
- //$view = new \OC_FilesystemView( '/' . $this->userId . '/files_encryption/keyfiles' );
- Encryption\Keymanager::setFileKey($this->view, $file, $this->userId, $key['key']);
-
- // enable encryption proxy
- $proxyStatus = \OC_FileProxy::$enabled;
- \OC_FileProxy::$enabled = true;
+ $this->assertTrue($this->view->file_exists('/' . $this->userId . '/files_encryption/keyfiles/' . $file . '.key'));
// cleanup
$this->view->unlink('/' . $this->userId . '/files/' . $file);
// change encryption proxy to previous state
\OC_FileProxy::$enabled = $proxyStatus;
-
}
/**