Merge pull request #49538 from nextcloud/backport/49535/stable27

[stable27] fix(migration): Decrypt ownCloud secrets v2
This commit is contained in:
Joas Schilling 2024-11-28 13:49:47 +01:00 committed by GitHub
commit cfb51dd58b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 42 additions and 3 deletions

View file

@ -146,6 +146,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]);
@ -156,7 +175,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);
@ -165,8 +184,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);

View file

@ -89,6 +89,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() {
$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() {
$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.',