@@ -146,6 +146,25 @@ private function decryptWithoutSecret(string $authenticatedCiphertext, string $p
146146 throw new Exception ('Authenticated ciphertext could not be decoded. ' );
147147 }
148148
149+ /*
150+ * Rearrange arguments for legacy ownCloud migrations
151+ *
152+ * The original scheme consistent of three parts. Nextcloud added a
153+ * fourth at the end as "2" or later "3", ownCloud added "v2" at the
154+ * beginning.
155+ */
156+ $ originalParts = $ parts ;
157+ $ isOwnCloudV2Migration = $ partCount === 4 && $ originalParts [0 ] === 'v2 ' ;
158+ if ($ isOwnCloudV2Migration ) {
159+ $ parts = [
160+ $ parts [1 ],
161+ $ parts [2 ],
162+ $ parts [3 ],
163+ '2 '
164+ ];
165+ }
166+
167+ // Convert hex-encoded values to binary
149168 $ ciphertext = $ this ->hex2bin ($ parts [0 ]);
150169 $ iv = $ parts [1 ];
151170 $ hmac = $ this ->hex2bin ($ parts [2 ]);
@@ -156,7 +175,7 @@ private function decryptWithoutSecret(string $authenticatedCiphertext, string $p
156175 $ iv = $ this ->hex2bin ($ iv );
157176 }
158177
159- if ($ version === '3 ' ) {
178+ if ($ version === '3 ' || $ isOwnCloudV2Migration ) {
160179 $ keyMaterial = hash_hkdf ('sha512 ' , $ password );
161180 $ encryptionKey = substr ($ keyMaterial , 0 , 32 );
162181 $ hmacKey = substr ($ keyMaterial , 32 );
@@ -165,8 +184,15 @@ private function decryptWithoutSecret(string $authenticatedCiphertext, string $p
165184 $ this ->cipher ->setPassword ($ encryptionKey );
166185 $ this ->cipher ->setIV ($ iv );
167186
168- if (!hash_equals ($ this ->calculateHMAC ($ parts [0 ] . $ parts [1 ], $ hmacKey ), $ hmac )) {
169- throw new Exception ('HMAC does not match. ' );
187+ if ($ isOwnCloudV2Migration ) {
188+ // ownCloud uses the binary IV for HMAC calculation
189+ if (!hash_equals ($ this ->calculateHMAC ($ parts [0 ] . $ iv , $ hmacKey ), $ hmac )) {
190+ throw new Exception ('HMAC does not match. ' );
191+ }
192+ } else {
193+ if (!hash_equals ($ this ->calculateHMAC ($ parts [0 ] . $ parts [1 ], $ hmacKey ), $ hmac )) {
194+ throw new Exception ('HMAC does not match. ' );
195+ }
170196 }
171197
172198 $ result = $ this ->cipher ->decrypt ($ ciphertext );
0 commit comments