Changing user login pwd now correctly changes encryption key passphrase

All crypt unit tests are now passing
This commit is contained in:
Sam Tuke 2012-12-11 17:12:46 +00:00
parent 31cbb5a09f
commit 453fd66c70
5 changed files with 128 additions and 111 deletions

View File

@ -342,15 +342,10 @@ class Crypt {
// Remove padding // Remove padding
$noPadding = self::removePadding( $keyfileContent ); $noPadding = self::removePadding( $keyfileContent );
// Fetch IV from end of file // Split into enc data and catfile
$iv = substr( $noPadding, -16 ); $catfile = self::splitIv( $noPadding );
// Remove IV and IV identifier text to expose encrypted content if ( $plainContent = self::decrypt( $catfile['encrypted'], $catfile['iv'], $passphrase ) ) {
$encryptedContent = substr( $noPadding, 0, -22 );
//trigger_error( "\n\n\$noPadding = ".var_export($noPadding)."\n\n\$iv = ".var_export($iv )."\n\n\$encryptedContent = ".var_export($encryptedContent) );
if ( $plainContent = self::decrypt( $encryptedContent, $iv, $passphrase ) ) {
return $plainContent; return $plainContent;
@ -493,12 +488,12 @@ class Crypt {
public static function keyDecryptKeyfile( $catfile, $keyfile, $privateKey ) { public static function keyDecryptKeyfile( $catfile, $keyfile, $privateKey ) {
// Decrypt the keyfile with the user's private key // Decrypt the keyfile with the user's private key
$decryptedKey = self::keyDecrypt( $keyfile, $privateKey ); $decryptedKeyfile = self::keyDecrypt( $keyfile, $privateKey );
// trigger_error( "\$keyfile = ".var_export($keyfile, 1)); // trigger_error( "\$keyfile = ".var_export($keyfile, 1));
// Decrypt the catfile symmetrically using the decrypted keyfile // Decrypt the catfile symmetrically using the decrypted keyfile
$decryptedData = self::symmetricDecryptFileContent( $catfile, $decryptedKey ); $decryptedData = self::symmetricDecryptFileContent( $catfile, $decryptedKeyfile );
return $decryptedData; return $decryptedData;
@ -705,11 +700,9 @@ class Crypt {
*/ */
public static function legacyDecrypt( $content, $passphrase = '' ) { public static function legacyDecrypt( $content, $passphrase = '' ) {
$passphrase = '';
//trigger_error("OC2 dec \$content = $content \$key = ".strlen($passphrase) ); //trigger_error("OC2 dec \$content = $content \$key = ".strlen($passphrase) );
$bf = self::getBlowfish( "67362885833455692562" ); $bf = self::getBlowfish( $passphrase );
// trigger_error(var_export($bf, 1) ); // trigger_error(var_export($bf, 1) );

View File

@ -157,11 +157,11 @@ class Proxy extends \OC_FileProxy {
//$cached = \OC_FileCache_Cached::get( $path, '' ); //$cached = \OC_FileCache_Cached::get( $path, '' );
$keyFile = Keymanager::getFileKey( $filePath ); $encryptedKeyfile = Keymanager::getFileKey( $filePath );
$session = new Session(); $session = new Session();
$decrypted = Crypt::keyDecryptKeyfile( $data, $keyFile, $session->getPrivateKey( $split[1] ) ); $decrypted = Crypt::keyDecryptKeyfile( $data, $encryptedKeyfile, $session->getPrivateKey( $split[1] ) );
} elseif ( } elseif (
Crypt::mode() == 'server' Crypt::mode() == 'server'

View File

@ -302,10 +302,6 @@ class Stream {
*/ */
public function stream_write( $data ) { public function stream_write( $data ) {
// file_put_contents('/home/samtuke/newtmp.txt', 'stream_write('.$data.')' );
// Disable the file proxies so that encryption is not automatically attempted when the file is written to disk - we are handling that separately here and we don't want to get into an infinite loop // Disable the file proxies so that encryption is not automatically attempted when the file is written to disk - we are handling that separately here and we don't want to get into an infinite loop
\OC_FileProxy::$enabled = false; \OC_FileProxy::$enabled = false;

View File

@ -71,12 +71,20 @@ class Util {
# Admin UI: # Admin UI:
## DONE: changing user password also changes encryption passphrase
## TODO: add support for optional recovery in case of lost passphrase / keys ## TODO: add support for optional recovery in case of lost passphrase / keys
## TODO: add admin optional required long passphrase for users ## TODO: add admin optional required long passphrase for users
## TODO: add UI buttons for encrypt / decrypt everything ## TODO: add UI buttons for encrypt / decrypt everything
## TODO: implement flag system to allow user to specify encryption by folder, subfolder, etc. ## TODO: implement flag system to allow user to specify encryption by folder, subfolder, etc.
# Sharing:
## TODO: add support for encrypting to multiple public keys
## TODO: add support for decrypting to multiple private keys
# Integration testing: # Integration testing:
## TODO: test new encryption with webdav ## TODO: test new encryption with webdav

View File

@ -64,8 +64,6 @@ class Test_Crypt extends \PHPUnit_Framework_TestCase {
$iv = Encryption\Crypt::generateIv(); $iv = Encryption\Crypt::generateIv();
echo $iv;
$this->assertEquals( 16, strlen( $iv ) ); $this->assertEquals( 16, strlen( $iv ) );
return $iv; return $iv;
@ -223,84 +221,106 @@ class Test_Crypt extends \PHPUnit_Framework_TestCase {
// Get file contents without using any wrapper to get it's actual contents on disk // Get file contents without using any wrapper to get it's actual contents on disk
$retreivedCryptedFile = $this->view->file_get_contents( $this->userId . '/files/' . $filename ); $retreivedCryptedFile = $this->view->file_get_contents( $this->userId . '/files/' . $filename );
//echo "\n\n\$retreivedCryptedFile = $retreivedCryptedFile";
// Check that the file was encrypted before being written to disk // Check that the file was encrypted before being written to disk
$this->assertNotEquals( $this->dataShort, $retreivedCryptedFile ); $this->assertNotEquals( $this->dataShort, $retreivedCryptedFile );
// Get private key
$encryptedPrivateKey = Encryption\Keymanager::getPrivateKey( $this->userId, $this->view );
$key = Encryption\Keymanager::getFileKey( $filename ); $decryptedPrivateKey = Encryption\Crypt::symmetricDecryptFileContent( $encryptedPrivateKey, $this->pass );
$manualDecrypt = Encryption\Crypt::symmetricBlockDecryptFileContent( $retreivedCryptedFile, $key );
// Get keyfile
$encryptedKeyfile = Encryption\Keymanager::getFileKey( $filename );
$decryptedKeyfile = Encryption\Crypt::keyDecrypt( $encryptedKeyfile, $decryptedPrivateKey );
// Manually decrypt
$manualDecrypt = Encryption\Crypt::symmetricBlockDecryptFileContent( $retreivedCryptedFile, $decryptedKeyfile );
// Check that decrypted data matches
$this->assertEquals( $this->dataShort, $manualDecrypt ); $this->assertEquals( $this->dataShort, $manualDecrypt );
} }
// /** /**
// * @brief Test that data that is written by the crypto stream wrapper * @brief Test that data that is written by the crypto stream wrapper
// * @note Encrypted data is manually prepared and decrypted here to avoid dependency on success of stream_read * @note Encrypted data is manually prepared and decrypted here to avoid dependency on success of stream_read
// */ * @note If this test fails with truncate content, check that enough array slices are being rejoined to form $e, as the crypt.php file may have gotten longer and broken the manual
// function testSymmetricStreamEncryptLongFileContent() { * reassembly of its data
// */
// // Generate a a random filename function testSymmetricStreamEncryptLongFileContent() {
// $filename = 'tmp-'.time();
// // Generate a a random filename
// echo "\n\n\$filename = $filename\n\n"; $filename = 'tmp-'.time();
//
// // Save long data as encrypted file using stream wrapper // Save long data as encrypted file using stream wrapper
// $cryptedFile = file_put_contents( 'crypt://' . $filename, $this->dataLong.$this->dataLong ); $cryptedFile = file_put_contents( 'crypt://' . $filename, $this->dataLong.$this->dataLong );
//
// // Test that data was successfully written // Test that data was successfully written
// $this->assertTrue( is_int( $cryptedFile ) ); $this->assertTrue( is_int( $cryptedFile ) );
//
// // Get file contents without using any wrapper to get it's actual contents on disk // Get file contents without using any wrapper to get it's actual contents on disk
// $retreivedCryptedFile = $this->view->file_get_contents( $this->userId . '/files/' . $filename ); $retreivedCryptedFile = $this->view->file_get_contents( $this->userId . '/files/' . $filename );
//
// // echo "\n\n\$retreivedCryptedFile = $retreivedCryptedFile\n\n"; // echo "\n\n\$retreivedCryptedFile = $retreivedCryptedFile\n\n";
//
// // Check that the file was encrypted before being written to disk // Check that the file was encrypted before being written to disk
// $this->assertNotEquals( $this->dataLong.$this->dataLong, $retreivedCryptedFile ); $this->assertNotEquals( $this->dataLong.$this->dataLong, $retreivedCryptedFile );
//
// // Manuallly split saved file into separate IVs and encrypted chunks // Manuallly split saved file into separate IVs and encrypted chunks
// $r = preg_split('/(00iv00.{16,18})/', $retreivedCryptedFile, NULL, PREG_SPLIT_DELIM_CAPTURE); $r = preg_split('/(00iv00.{16,18})/', $retreivedCryptedFile, NULL, PREG_SPLIT_DELIM_CAPTURE);
//
// //print_r($r); //print_r($r);
//
// // Join IVs and their respective data chunks // 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( $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[12].$r[13] );//.$r[11], $r[12].$r[13], $r[14] );
//
// //print_r($e); //print_r($e);
//
// // Manually fetch keyfile
// $keyfile = Encryption\Keymanager::getFileKey( $filename ); // Get private key
// $encryptedPrivateKey = Encryption\Keymanager::getPrivateKey( $this->userId, $this->view );
// // Set var for reassembling decrypted content
// $decrypt = ''; $decryptedPrivateKey = Encryption\Crypt::symmetricDecryptFileContent( $encryptedPrivateKey, $this->pass );
//
// // Manually decrypt chunk
// foreach ($e as $e) { // Get keyfile
// $encryptedKeyfile = Encryption\Keymanager::getFileKey( $filename );
// // echo "\n\$encryptMe = $f";
// $decryptedKeyfile = Encryption\Crypt::keyDecrypt( $encryptedKeyfile, $decryptedPrivateKey );
// $chunkDecrypt = Encryption\Crypt::symmetricDecryptFileContent( $e, $keyfile );
//
// // Assemble decrypted chunks // Set var for reassembling decrypted content
// $decrypt .= $chunkDecrypt; $decrypt = '';
//
// //echo "\n\$chunkDecrypt = $chunkDecrypt"; // Manually decrypt chunk
// foreach ($e as $e) {
// }
// // echo "\n\$e = $e";
// $this->assertEquals( $this->dataLong.$this->dataLong, $decrypt );
// $chunkDecrypt = Encryption\Crypt::symmetricDecryptFileContent( $e, $decryptedKeyfile );
// // Teardown
// // Assemble decrypted chunks
// $this->view->unlink( $filename ); $decrypt .= $chunkDecrypt;
//
// Encryption\Keymanager::deleteFileKey( $filename ); // echo "\n\$chunkDecrypt = $chunkDecrypt";
//
// } }
// echo "\n\$decrypt = $decrypt";
$this->assertEquals( $this->dataLong.$this->dataLong, $decrypt );
// Teardown
$this->view->unlink( $filename );
Encryption\Keymanager::deleteFileKey( $filename );
}
/** /**
* @brief Test that data that is read by the crypto stream wrapper * @brief Test that data that is read by the crypto stream wrapper
@ -493,17 +513,17 @@ class Test_Crypt extends \PHPUnit_Framework_TestCase {
} }
// /** /**
// * @brief test decryption using legacy blowfish method * @brief test decryption using legacy blowfish method
// * @depends testLegacyEncryptShort * @depends testLegacyEncryptShort
// */ */
// function testLegacyDecryptShort( $crypted ) { function testLegacyDecryptShort( $crypted ) {
//
// $decrypted = Encryption\Crypt::legacyDecrypt( $crypted, $this->pass ); $decrypted = Encryption\Crypt::legacyDecrypt( $crypted, $this->pass );
//
// $this->assertEquals( $this->dataShort, $decrypted ); $this->assertEquals( $this->dataShort, $decrypted );
//
// } }
/** /**
* @brief test encryption using legacy blowfish method * @brief test encryption using legacy blowfish method
@ -521,17 +541,17 @@ class Test_Crypt extends \PHPUnit_Framework_TestCase {
} }
// /** /**
// * @brief test decryption using legacy blowfish method * @brief test decryption using legacy blowfish method
// * @depends testLegacyEncryptLong * @depends testLegacyEncryptLong
// */ */
// function testLegacyDecryptLong( $crypted ) { function testLegacyDecryptLong( $crypted ) {
//
// $decrypted = Encryption\Crypt::legacyDecrypt( $crypted, $this->pass ); $decrypted = Encryption\Crypt::legacyDecrypt( $crypted, $this->pass );
//
// $this->assertEquals( $this->dataLong, $decrypted ); $this->assertEquals( $this->dataLong, $decrypted );
//
// } }
/** /**
* @brief test generation of legacy encryption key * @brief test generation of legacy encryption key