diff options
author | Christoph Wurst <christoph@winzerhof-wurst.at> | 2024-11-27 19:19:36 +0100 |
---|---|---|
committer | Christoph Wurst <christoph@winzerhof-wurst.at> | 2024-11-28 09:45:30 +0100 |
commit | a925e0b2b0e46513cb7724e57c1152d2f00459e5 (patch) | |
tree | 2585b9c758fabb01b594096ac6e7df32084ef7a2 /lib | |
parent | 4875f3281ac8f64b4d819ba00bc7056b63f8ec5e (diff) | |
download | nextcloud-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.php | 32 |
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); |