Skip to content

Commit 21e2556

Browse files
Merge pull request #49540 from nextcloud/backport/49535/stable25
[stable25] fix(migration): Decrypt ownCloud secrets v2
2 parents 79f1df9 + 9fe9cfe commit 21e2556

File tree

2 files changed

+42
-3
lines changed

2 files changed

+42
-3
lines changed

lib/private/Security/Crypto.php

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,25 @@ private function decryptWithoutSecret(string $authenticatedCiphertext, string $p
146146
throw new Exception('Authenticated ciphertext could not be decoded.');
147147
}
148148

149+
/*
150+
* Rearrange arguments for legacy ownCloud migrations
151+
*
152+
* The original scheme consistent of three parts. Nextcloud added a
153+
* fourth at the end as "2" or later "3", ownCloud added "v2" at the
154+
* beginning.
155+
*/
156+
$originalParts = $parts;
157+
$isOwnCloudV2Migration = $partCount === 4 && $originalParts[0] === 'v2';
158+
if ($isOwnCloudV2Migration) {
159+
$parts = [
160+
$parts[1],
161+
$parts[2],
162+
$parts[3],
163+
'2'
164+
];
165+
}
166+
167+
// Convert hex-encoded values to binary
149168
$ciphertext = $this->hex2bin($parts[0]);
150169
$iv = $parts[1];
151170
$hmac = $this->hex2bin($parts[2]);
@@ -156,7 +175,7 @@ private function decryptWithoutSecret(string $authenticatedCiphertext, string $p
156175
$iv = $this->hex2bin($iv);
157176
}
158177

159-
if ($version === '3') {
178+
if ($version === '3' || $isOwnCloudV2Migration) {
160179
$keyMaterial = hash_hkdf('sha512', $password);
161180
$encryptionKey = substr($keyMaterial, 0, 32);
162181
$hmacKey = substr($keyMaterial, 32);
@@ -165,8 +184,15 @@ private function decryptWithoutSecret(string $authenticatedCiphertext, string $p
165184
$this->cipher->setPassword($encryptionKey);
166185
$this->cipher->setIV($iv);
167186

168-
if (!hash_equals($this->calculateHMAC($parts[0] . $parts[1], $hmacKey), $hmac)) {
169-
throw new Exception('HMAC does not match.');
187+
if ($isOwnCloudV2Migration) {
188+
// ownCloud uses the binary IV for HMAC calculation
189+
if (!hash_equals($this->calculateHMAC($parts[0] . $iv, $hmacKey), $hmac)) {
190+
throw new Exception('HMAC does not match.');
191+
}
192+
} else {
193+
if (!hash_equals($this->calculateHMAC($parts[0] . $parts[1], $hmacKey), $hmac)) {
194+
throw new Exception('HMAC does not match.');
195+
}
170196
}
171197

172198
$result = $this->cipher->decrypt($ciphertext);

tests/lib/Security/CryptoTest.php

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,19 @@ public function testVersion2CiphertextDecryptsToCorrectPlaintext() {
8989
);
9090
}
9191

92+
/**
93+
* Test data taken from https://github.com/owncloud/core/blob/9deb8196b20354c8de0cd720ad4d18d52ccc96d8/tests/lib/Security/CryptoTest.php#L56-L60
94+
*/
95+
public function testOcVersion2CiphertextDecryptsToCorrectPlaintext() {
96+
$this->assertSame(
97+
'Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt.',
98+
$this->crypto->decrypt(
99+
'v2|d57dbe4d1317cdf19d4ddc2df807f6b5d63ab1e119c46590ce54bae56a9cd3969168c4ec1600ac9758dd7e7afb9c4c962dd23072c1463add1d9c77c467723b37bb768ef00e3c50898e59247cbb59ce56b74ce5990648ffe9e40d0e95076c27a785bdcf32c219ea4ad5c316b1f12f48c1|6bd21db258a5e406a2c288a444de195f|a19111a4cf1a11ee95fc1734699c20964eaa05bb007e1cecc4cc6872f827a4b7deedc977c13b138d728d68116aa3d82f9673e20c7e447a9788aa3be994b67cd6',
100+
'ThisIsAVeryS3cur3P4ssw0rd'
101+
)
102+
);
103+
}
104+
92105
public function testVersion3CiphertextDecryptsToCorrectPlaintext() {
93106
$this->assertSame(
94107
'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.',

0 commit comments

Comments
 (0)