@@ -135,6 +135,25 @@ private function decryptWithoutSecret(string $authenticatedCiphertext, string $p
135135 throw new Exception ('Authenticated ciphertext could not be decoded. ' );
136136 }
137137
138+ /*
139+ * Rearrange arguments for legacy ownCloud migrations
140+ *
141+ * The original scheme consistent of three parts. Nextcloud added a
142+ * fourth at the end as "2" or later "3", ownCloud added "v2" at the
143+ * beginning.
144+ */
145+ $ originalParts = $ parts ;
146+ $ isOwnCloudV2Migration = $ partCount === 4 && $ originalParts [0 ] === 'v2 ' ;
147+ if ($ isOwnCloudV2Migration ) {
148+ $ parts = [
149+ $ parts [1 ],
150+ $ parts [2 ],
151+ $ parts [3 ],
152+ '2 '
153+ ];
154+ }
155+
156+ // Convert hex-encoded values to binary
138157 $ ciphertext = $ this ->hex2bin ($ parts [0 ]);
139158 $ iv = $ parts [1 ];
140159 $ hmac = $ this ->hex2bin ($ parts [2 ]);
@@ -145,7 +164,7 @@ private function decryptWithoutSecret(string $authenticatedCiphertext, string $p
145164 $ iv = $ this ->hex2bin ($ iv );
146165 }
147166
148- if ($ version === '3 ' ) {
167+ if ($ version === '3 ' || $ isOwnCloudV2Migration ) {
149168 $ keyMaterial = hash_hkdf ('sha512 ' , $ password );
150169 $ encryptionKey = substr ($ keyMaterial , 0 , 32 );
151170 $ hmacKey = substr ($ keyMaterial , 32 );
@@ -154,8 +173,15 @@ private function decryptWithoutSecret(string $authenticatedCiphertext, string $p
154173 $ this ->cipher ->setPassword ($ encryptionKey );
155174 $ this ->cipher ->setIV ($ iv );
156175
157- if (!hash_equals ($ this ->calculateHMAC ($ parts [0 ] . $ parts [1 ], $ hmacKey ), $ hmac )) {
158- throw new Exception ('HMAC does not match. ' );
176+ if ($ isOwnCloudV2Migration ) {
177+ // ownCloud uses the binary IV for HMAC calculation
178+ if (!hash_equals ($ this ->calculateHMAC ($ parts [0 ] . $ iv , $ hmacKey ), $ hmac )) {
179+ throw new Exception ('HMAC does not match. ' );
180+ }
181+ } else {
182+ if (!hash_equals ($ this ->calculateHMAC ($ parts [0 ] . $ parts [1 ], $ hmacKey ), $ hmac )) {
183+ throw new Exception ('HMAC does not match. ' );
184+ }
159185 }
160186
161187 $ result = $ this ->cipher ->decrypt ($ ciphertext );
0 commit comments