aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorChristoph Wurst <christoph@winzerhof-wurst.at>2024-11-27 19:19:36 +0100
committerChristoph Wurst <christoph@winzerhof-wurst.at>2024-11-28 09:45:30 +0100
commita925e0b2b0e46513cb7724e57c1152d2f00459e5 (patch)
tree2585b9c758fabb01b594096ac6e7df32084ef7a2 /lib
parent4875f3281ac8f64b4d819ba00bc7056b63f8ec5e (diff)
downloadnextcloud-server-a925e0b2b0e46513cb7724e57c1152d2f00459e5.tar.gz
nextcloud-server-a925e0b2b0e46513cb7724e57c1152d2f00459e5.zip
fix(migration): Decrypt ownCloud secrets v2
Signed-off-by: Christoph Wurst <christoph@winzerhof-wurst.at>
Diffstat (limited to 'lib')
-rw-r--r--lib/private/Security/Crypto.php32
1 files changed, 29 insertions, 3 deletions
diff --git a/lib/private/Security/Crypto.php b/lib/private/Security/Crypto.php
index 033456f3f2e..2c42f2506af 100644
--- a/lib/private/Security/Crypto.php
+++ b/lib/private/Security/Crypto.php
@@ -135,6 +135,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]);
@@ -145,7 +164,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);
@@ -154,8 +173,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);