Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

use password hash to encrypt private key #18121

Merged
merged 2 commits into from
Aug 24, 2015

Conversation

schiessle
Copy link
Contributor

use password hash instead of the plain password to encrypt the private key as discussed with @LukasReschke .

What should be tested:

  • setup ownCloud with master
  • enable encryption
  • create recovery key (private recovery key shouldn't have "keyFormat" in the header)
  • re-login (user should have a private key which doesn't contain "keyFormat" in the header)
  • upload a encrypted file
  • switch to this branch
  • create a new user (new user should have a private key which has "keyFormat:hash" in the header)
  • check if both the new user and the old one can create new files and read existing ons
  • change recovery key password (new key should have "keyFormat:hash" in the header)
  • the old user changes his password in his personal settings (updated private key should have "keyFormat:hash" in the header) and he should still be able to read/write his files after re-login

@schiessle schiessle added this to the 8.2-current milestone Aug 7, 2015
@karlitschek
Copy link
Contributor

What are the consequences regarding migration?

@LukasReschke LukasReschke changed the title use password hash to encrypt private key use password hash to hash private key Aug 7, 2015
@schiessle
Copy link
Contributor Author

What are the consequences regarding migration?

Nothing, we don't change existing keys.

  • New keys will be encrypted with the hash instead of the login password
  • If we change the password of a existing key it will use the new hash
  • The header of the encrypted key will indicate which method was used (similar to what we did for the aes-128 vs aes-256 setting)

protected function generatePasswordHash($password, $cipher) {
$instanceId = $this->config->getSystemValue('instanceid');
$instanceSecret = $this->config->getSystemValue('secret');
$salt = hash('sha256', $instanceId + $instanceSecret, true);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a nifty one. Basically this will always return 0, the + operator is the wrong one here.

Use please . as otherwise the salt will always be 5feceb66ffc86f38d952786c6d696c79c2dbc239dd4e91b46729d73a27fb57e9, on every instance.

Going further, it might very much make sense to include the user id as well as another work factor:

$salt = hash('sha256', $uid . $instanceId . $instanceSecret, true);

Note that you should use $uid as first argument to prevent potential padding problems etc.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use please . as otherwise the salt will always be

Indeed this should have been a ., good catch. Will fix it and also add the uid.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm, adding the uid is not that easy. We also have the "public link share"-key and the recovery-key. For them the uid isn't unique. Multiple admins could have access to the recovery key and the "public link share"-key gets created for whoever login first. Further at this point we have no idea which kind of key gets encrypted. So I would skip the uid for now.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's acceptable as well. The expectation here is "to make it a little bit harder" and not to offer the best possible security with regards to time-memory trade-off attacks. We can't anyways as the admin could intercept data on it's own.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we touch the code now then let's do it as good as possible. I had another look and added the uid for all regular users, for system users the uid is just a empty string

@LukasReschke LukasReschke changed the title use password hash to hash private key use password hash to encrypt private key Aug 7, 2015
public function generateHeader() {
public function generateHeader($keyFormat = 'hash') {

if (in_array($keyFormat, $this->supportedKeyFormats) === false) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When using in_array please always set the strict parameter to true.

in_array($keyFormat, $this->supportedKeyFormats, true)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed and ready to push once Jenkins finished

@LukasReschke
Copy link
Member

Code looks good to me. Basic functionality testing also did not find any bugs.

@bantu I'd appreciate your feedback on this one as well. Basically previously the encryption key of an user was only encrypted with the user password which limited the potential key space and also made brute-force attacks way easier than necessary. Using PBKDF2 should be a somewhat better approach. It's not perfect but better than before :-)

@ghost
Copy link

ghost commented Aug 7, 2015

🚀 Test PASSed.🚀
chuck

@schiessle schiessle force-pushed the enc_improve_privkey_encryption branch from 4d00ee0 to 854fd63 Compare August 7, 2015 14:09
@scrutinizer-notifier
Copy link

A new inspection was created.

@bantu
Copy link

bantu commented Aug 7, 2015

@LukasReschke Without looking to deep into the code changes and from the point of interacting crypto primitives this is much better and more proper indeed.

Please note that you already depend on phpseclib and there is PBKDF2 support in it via the setPassword() method on Crypt objects. https://github.com/phpseclib/phpseclib/blob/2.0/phpseclib/Crypt/Base.php#L536

@LukasReschke
Copy link
Member

Please note that you already depend on phpseclib and there is PBKDF2 support in it via the setPassword() method on Crypt objects. https://github.com/phpseclib/phpseclib/blob/2.0/phpseclib/Crypt/Base.php#L536

Mhm. Seems like adjusting this for our use-case would require also some more work. Considering that the embedded library also is somewhat widely used and only a fallback for PHP 5.4 I'd keep it as-is.

👍 from my side.

@ghost
Copy link

ghost commented Aug 7, 2015

🚀 Test PASSed.🚀
chuck

@schiessle
Copy link
Contributor Author

needs a second reviewer... maybe @nickvergessen or @PVince81 ? Thanks!

@nickvergessen
Copy link
Contributor

👍

LukasReschke added a commit that referenced this pull request Aug 24, 2015
@LukasReschke LukasReschke merged commit cca35f0 into master Aug 24, 2015
@LukasReschke LukasReschke deleted the enc_improve_privkey_encryption branch August 24, 2015 10:03
@lock lock bot locked as resolved and limited conversation to collaborators Aug 10, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants