|
|
|
|
@ -29,6 +29,7 @@ declare(strict_types=1);
|
|
|
|
|
*/
|
|
|
|
|
namespace OC\Security;
|
|
|
|
|
|
|
|
|
|
use Exception;
|
|
|
|
|
use OCP\IConfig;
|
|
|
|
|
use OCP\Security\ICrypto;
|
|
|
|
|
use OCP\Security\ISecureRandom;
|
|
|
|
|
@ -82,9 +83,12 @@ class Crypto implements ICrypto {
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 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
|
|
|
|
|
* @throws Exception if it was not possible to gather sufficient entropy
|
|
|
|
|
* @throws Exception if encrypting the data failed
|
|
|
|
|
*/
|
|
|
|
|
public function encrypt(string $plaintext, string $password = ''): string {
|
|
|
|
|
if ($password === '') {
|
|
|
|
|
@ -96,7 +100,13 @@ class Crypto implements ICrypto {
|
|
|
|
|
$iv = \random_bytes($this->ivLength);
|
|
|
|
|
$this->cipher->setIV($iv);
|
|
|
|
|
|
|
|
|
|
$ciphertext = bin2hex($this->cipher->encrypt($plaintext));
|
|
|
|
|
/** @var string|false $encrypted */
|
|
|
|
|
$encrypted = $this->cipher->encrypt($plaintext);
|
|
|
|
|
if ($encrypted === false) {
|
|
|
|
|
throw new Exception('Encrypting failed.');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$ciphertext = bin2hex($encrypted);
|
|
|
|
|
$iv = bin2hex($iv);
|
|
|
|
|
$hmac = bin2hex($this->calculateHMAC($ciphertext.$iv, substr($keyMaterial, 32)));
|
|
|
|
|
|
|
|
|
|
@ -108,8 +118,8 @@ class Crypto implements ICrypto {
|
|
|
|
|
* @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
|
|
|
|
|
* @throws \Exception If the decryption failed
|
|
|
|
|
* @throws Exception If the HMAC does not match
|
|
|
|
|
* @throws Exception If the decryption failed
|
|
|
|
|
*/
|
|
|
|
|
public function decrypt(string $authenticatedCiphertext, string $password = ''): string {
|
|
|
|
|
if ($password === '') {
|
|
|
|
|
@ -120,7 +130,7 @@ class Crypto implements ICrypto {
|
|
|
|
|
$parts = explode('|', $authenticatedCiphertext);
|
|
|
|
|
$partCount = \count($parts);
|
|
|
|
|
if ($partCount < 3 || $partCount > 4) {
|
|
|
|
|
throw new \Exception('Authenticated ciphertext could not be decoded.');
|
|
|
|
|
throw new Exception('Authenticated ciphertext could not be decoded.');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$ciphertext = $this->hex2bin($parts[0]);
|
|
|
|
|
@ -143,12 +153,12 @@ class Crypto implements ICrypto {
|
|
|
|
|
$this->cipher->setIV($iv);
|
|
|
|
|
|
|
|
|
|
if (!hash_equals($this->calculateHMAC($parts[0] . $parts[1], $hmacKey), $hmac)) {
|
|
|
|
|
throw new \Exception('HMAC does not match.');
|
|
|
|
|
throw new Exception('HMAC does not match.');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$result = $this->cipher->decrypt($ciphertext);
|
|
|
|
|
if ($result === false) {
|
|
|
|
|
throw new \Exception('Decryption failed');
|
|
|
|
|
throw new Exception('Decryption failed');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return $result;
|
|
|
|
|
|