Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 8 additions & 13 deletions lib/private/Security/Crypto.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,7 @@

use OCP\IConfig;
use OCP\Security\ICrypto;
use OCP\Security\ISecureRandom;
use phpseclib\Crypt\AES;
use phpseclib\Crypt\Hash;

/**
* Class Crypto provides a high-level encryption layer using AES-CBC. If no key has been provided
Expand All @@ -55,7 +53,6 @@ class Crypto implements ICrypto {

/**
* @param IConfig $config
* @param ISecureRandom $random
*/
public function __construct(IConfig $config) {
$this->cipher = new AES();
Expand All @@ -72,12 +69,7 @@ public function calculateHMAC(string $message, string $password = ''): string {
$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 Hash('sha512');
$hash->setKey($password);
return $hash->hash($message);
return hash_hmac('sha512', $message, $password, true);
}

/**
Expand All @@ -90,16 +82,19 @@ public function encrypt(string $plaintext, string $password = ''): string {
if ($password === '') {
$password = $this->config->getSystemValue('secret');
}
$this->cipher->setPassword($password);

$keyMaterial = hash_hkdf('sha512', $password);
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
$keyMaterial = hash_hkdf('sha512', $password);
$keyMaterial = hash_hkdf('sha512', $password, 32);

I'm not 100% sure. The documentation says "Desired output length in bytes" 🤷‍♂️

Copy link
Contributor Author

@lynn-stephenson lynn-stephenson Oct 14, 2020

Choose a reason for hiding this comment

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

@kesselb The documentation says hash_hkdf with a $length of 0 will use the provided hash function length (which is 64 bytes in this case). Also, 32 bytes is not enough. If anything, we'll explicitly ask for 64 bytes.


$this->cipher->setPassword(substr($keyMaterial, 0, 32));

$iv = \random_bytes($this->ivLength);
$this->cipher->setIV($iv);

$ciphertext = bin2hex($this->cipher->encrypt($plaintext));
$iv = bin2hex($iv);
$hmac = bin2hex($this->calculateHMAC($ciphertext.$iv, $password));
$hmac = bin2hex($this->calculateHMAC($ciphertext.$iv, substr($keyMaterial, 32)));

return $ciphertext.'|'.$iv.'|'.$hmac.'|2';
return $ciphertext.'|'.$iv.'|'.$hmac.'|3';
}

/**
Expand Down Expand Up @@ -128,7 +123,7 @@ public function decrypt(string $authenticatedCiphertext, string $password = ''):

if ($partCount === 4) {
$version = $parts[3];
if ($version === '2') {
if ($version >= '2') {
$iv = hex2bin($iv);
}
}
Expand Down