fix(migration): Decrypt ownCloud secrets v2

Signed-off-by: Christoph Wurst <christoph@winzerhof-wurst.at>
pull/49523/head
Christoph Wurst 1 year ago
parent 659cd12a8a
commit 1323e5bcb1
No known key found for this signature in database
GPG Key ID: CC42AC2A7F0E56D8
  1. 32
      lib/private/Security/Crypto.php
  2. 13
      tests/lib/Security/CryptoTest.php

@ -114,6 +114,25 @@ class Crypto implements ICrypto {
throw new Exception('Authenticated ciphertext could not be decoded.');
}
/*
* Rearrange arguments for legacy ownCloud migrations
*
* The original scheme consistent of three parts. Nextcloud added a
* fourth at the end as "2" or later "3", ownCloud added "v2" at the
* beginning.
*/
$originalParts = $parts;
$isOwnCloudV2Migration = $partCount === 4 && $originalParts[0] === 'v2';
if ($isOwnCloudV2Migration) {
$parts = [
$parts[1],
$parts[2],
$parts[3],
'2'
];
}
// Convert hex-encoded values to binary
$ciphertext = $this->hex2bin($parts[0]);
$iv = $parts[1];
$hmac = $this->hex2bin($parts[2]);
@ -124,7 +143,7 @@ class Crypto implements ICrypto {
$iv = $this->hex2bin($iv);
}
if ($version === '3') {
if ($version === '3' || $isOwnCloudV2Migration) {
$keyMaterial = hash_hkdf('sha512', $password);
$encryptionKey = substr($keyMaterial, 0, 32);
$hmacKey = substr($keyMaterial, 32);
@ -133,8 +152,15 @@ class Crypto implements ICrypto {
$this->cipher->setPassword($encryptionKey);
$this->cipher->setIV($iv);
if (!hash_equals($this->calculateHMAC($parts[0] . $parts[1], $hmacKey), $hmac)) {
throw new Exception('HMAC does not match.');
if ($isOwnCloudV2Migration) {
// ownCloud uses the binary IV for HMAC calculation
if (!hash_equals($this->calculateHMAC($parts[0] . $iv, $hmacKey), $hmac)) {
throw new Exception('HMAC does not match.');
}
} else {
if (!hash_equals($this->calculateHMAC($parts[0] . $parts[1], $hmacKey), $hmac)) {
throw new Exception('HMAC does not match.');
}
}
$result = $this->cipher->decrypt($ciphertext);

@ -88,6 +88,19 @@ class CryptoTest extends \Test\TestCase {
);
}
/**
* Test data taken from https://github.com/owncloud/core/blob/9deb8196b20354c8de0cd720ad4d18d52ccc96d8/tests/lib/Security/CryptoTest.php#L56-L60
*/
public function testOcVersion2CiphertextDecryptsToCorrectPlaintext(): void {
$this->assertSame(
'Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt.',
$this->crypto->decrypt(
'v2|d57dbe4d1317cdf19d4ddc2df807f6b5d63ab1e119c46590ce54bae56a9cd3969168c4ec1600ac9758dd7e7afb9c4c962dd23072c1463add1d9c77c467723b37bb768ef00e3c50898e59247cbb59ce56b74ce5990648ffe9e40d0e95076c27a785bdcf32c219ea4ad5c316b1f12f48c1|6bd21db258a5e406a2c288a444de195f|a19111a4cf1a11ee95fc1734699c20964eaa05bb007e1cecc4cc6872f827a4b7deedc977c13b138d728d68116aa3d82f9673e20c7e447a9788aa3be994b67cd6',
'ThisIsAVeryS3cur3P4ssw0rd'
)
);
}
public function testVersion3CiphertextDecryptsToCorrectPlaintext(): void {
$this->assertSame(
'Another plaintext value that will be encrypted with version 3. It addresses the related key issue. Old ciphertexts should be decrypted properly, but only use the better version for encryption.',

Loading…
Cancel
Save