Skip to content

Commit ab60089

Browse files
fix(migration): Decrypt ownCloud secrets v2
Signed-off-by: Christoph Wurst <christoph@winzerhof-wurst.at> [skip ci]
1 parent 16df6aa commit ab60089

File tree

2 files changed

+43
-4
lines changed

2 files changed

+43
-4
lines changed

lib/private/Security/Crypto.php

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

117+
/*
118+
* Rearrange arguments for legacy ownCloud migrations
119+
*
120+
* The original scheme consistent of three parts. Nextcloud added a
121+
* fourth at the end as "2" or later "3", ownCloud added "v2" at the
122+
* beginning.
123+
*/
124+
$originalParts = $parts;
125+
$isOwnCloudV2Migration = $partCount === 4 && $originalParts[0] === 'v2';
126+
if ($isOwnCloudV2Migration) {
127+
$parts = [
128+
$parts[1],
129+
$parts[2],
130+
$parts[3],
131+
'2'
132+
];
133+
}
134+
135+
// Convert hex-encoded values to binary
117136
$ciphertext = $this->hex2bin($parts[0]);
118137
$iv = $parts[1];
119138
$hmac = $this->hex2bin($parts[2]);
@@ -124,7 +143,7 @@ private function decryptWithoutSecret(string $authenticatedCiphertext, string $p
124143
$iv = $this->hex2bin($iv);
125144
}
126145

127-
if ($version === '3') {
146+
if ($version === '3' || $isOwnCloudV2Migration) {
128147
$keyMaterial = hash_hkdf('sha512', $password);
129148
$encryptionKey = substr($keyMaterial, 0, 32);
130149
$hmacKey = substr($keyMaterial, 32);
@@ -133,8 +152,15 @@ private function decryptWithoutSecret(string $authenticatedCiphertext, string $p
133152
$this->cipher->setPassword($encryptionKey);
134153
$this->cipher->setIV($iv);
135154

136-
if (!hash_equals($this->calculateHMAC($parts[0] . $parts[1], $hmacKey), $hmac)) {
137-
throw new Exception('HMAC does not match.');
155+
if ($isOwnCloudV2Migration) {
156+
// ownCloud uses the binary IV for HMAC calculation
157+
if (!hash_equals($this->calculateHMAC($parts[0] . $iv, $hmacKey), $hmac)) {
158+
throw new Exception('HMAC does not match.');
159+
}
160+
} else {
161+
if (!hash_equals($this->calculateHMAC($parts[0] . $parts[1], $hmacKey), $hmac)) {
162+
throw new Exception('HMAC does not match.');
163+
}
138164
}
139165

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

tests/lib/Security/CryptoTest.php

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,20 @@ public function testVersion2CiphertextDecryptsToCorrectPlaintext() {
8888
);
8989
}
9090

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

0 commit comments

Comments
 (0)