Skip to content

Commit d45d1d6

Browse files
authored
Merge pull request #60735 from nextcloud/fix/noid/crypto-decrypt-fallback-valueerror
fix(security): don't propagate ValueError from Crypto::decrypt() fallback
2 parents 4700c85 + 29f43d8 commit d45d1d6

2 files changed

Lines changed: 28 additions & 1 deletion

File tree

lib/private/Security/Crypto.php

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,13 @@ public function decrypt(string $authenticatedCiphertext, string $password = ''):
103103
} catch (Exception $e) {
104104
if ($password === '') {
105105
// Retry with empty secret as a fallback for instances where the secret might not have been set by accident
106-
return $this->decryptWithoutSecret($authenticatedCiphertext, '');
106+
try {
107+
return $this->decryptWithoutSecret($authenticatedCiphertext, '');
108+
} catch (\Throwable) {
109+
// Fallback failed (e.g. v3 ciphertext requires a non-empty key for hash_hkdf),
110+
// rethrow the original exception
111+
throw $e;
112+
}
107113
}
108114
throw $e;
109115
}

tests/lib/Security/CryptoTest.php

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,27 @@ public function testOcVersion2CiphertextDecryptsToCorrectPlaintext(): void {
9999
);
100100
}
101101

102+
public function testDecryptWithWrongSecretThrowsHmacExceptionNotValueError(): void {
103+
// Encrypt with 'secret-A'
104+
$configA = $this->createMock(IConfig::class);
105+
$configA->method('getSystemValue')->with('secret')->willReturn('secret-A');
106+
$configA->method('getSystemValueString')->with('secret')->willReturn('secret-A');
107+
$cryptoA = new Crypto($configA);
108+
$ciphertext = $cryptoA->encrypt('plaintext');
109+
110+
// Decrypt with 'secret-B': first attempt fails (HMAC mismatch), fallback to empty
111+
// string must not propagate a ValueError for v3 ciphertexts — it must rethrow the
112+
// original HMAC exception instead.
113+
$configB = $this->createMock(IConfig::class);
114+
$configB->method('getSystemValue')->with('secret')->willReturn('secret-B');
115+
$configB->method('getSystemValueString')->with('secret')->willReturn('secret-B');
116+
$cryptoB = new Crypto($configB);
117+
118+
$this->expectException(\Exception::class);
119+
$this->expectExceptionMessage('HMAC does not match.');
120+
$cryptoB->decrypt($ciphertext);
121+
}
122+
102123
public function testVersion3CiphertextDecryptsToCorrectPlaintext(): void {
103124
$this->assertSame(
104125
'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)