ianathompson is right. The occ tool only allows you to decrypt files if the whole Owncloud installation is up and running. And since 8.2 changed the way encryption is done fundamentally there is basically no 3rd-party script available that works. Anyway, this should be available in core and not some 3rd-party script that does not get maintenance as needed.
If one needs to decrypt a few files then the only option is to restore the whole owncloud instance to decrypt them.
Hello,
I actually try to implement such a process, although this will not be developed as an “inline nextcloud app” (at least not for now…). My starting point is the daily backuped files (from the “data” directory).
My goal is to “get hold of the encrypted file and the administrator’s recovery key. then use the (known) recovery password and have the file decrypted”. Then the decrypted file will be “handed over” to the original user again.
Most of that process is working already for my environment, next step would be the actual decryption.
Currently I am getting an OPENSSL error, when trying to decrypt the “recoverykey” file:
Fatal error: Uncaught Exception: Missing Signature in /…/crypt.php:237
Where could I get some “deep-diving” knowledge of the decryption process?
I removed all “namespace” definitions at the top of the library, and replaced all $this-> … method calls by direct function calls. No other changes were nessessary so far.
calling $recoveryKeyDecrypted = decryptPrivateKey($recoveryKeyEncrypted, $recoveryPassword); [codeline 392 in github]
results in the mentioned error message in the method hasSignature [codeline 557 in github]
So it looks like my recoveryKey is expected to have a signature, but actually this is not found in the key…
The signature is created with a key which is a combination of the file-key + file-version + block-number. The version is stored in the file cache table and get’s increased every time the file is updated. So if you just have a backup of the files there is no way to verify the signature again. But it should be possible to ignore the signature and just decrypt the content as it is. Of course this means that you will not notice if someone changed the file on your backup or on your server right before you created the backup.
Thanks Bjoern,
I do actually backup the file-cache database table as well (actually twice, once BEFORE the files are backuped, and once after, so I can verify I have the relevant datarecord for that file - except for the “very” remote chance, that the file gets edited TWICE during the whole backup process).
So let me have a look at the filecache table and see if I can figure out what exactly you mean…
will be back soon with more questions I belief…
OK, lets assume I want to restore the file “Test-fuer-Ruecksicherung.txt” from my “/privat/” folder… In the filecache-table I have this record for it. So what does this record tell me (and where is this “version” incremented)?
I thought it would be “encrypted”, thanks for confirming this.
will start “reverseEngineering” as you suggested (and might come back here for help probably). Thanks for your help
Regards
Ruediger
I started to copy all the relevant functions from crypt.php to my own class for now. This allows me to dive into the decryption functionality (without all other requirements).
However, I am still getting this “Missing signature” error from:
What I do not understand is: this function checks for the position of the signature in the encrypted data:
but my “recoveryKey” (and fileKey and userShareKey) is not “plaintext”, but some “HEX encoded string”. So the “strpos” function understandably never finds “00sig00” in this…
Do I have to convert this “back to plaintext” first - and where is this done?
Sorry, if this sounds stupid, but I try to find my way through this code…
Thanks tflidd, I looked at that script and it seems that arno01 is decoding the key files first from BASE64. I tried this but the result is not nearly useable. So I am afraid I really need some help here…
The “keyfile” for that given file (test file only) looks like this:
Offset (h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
Offset (d) 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15
Of course, the “Offset” rows and the leading “8-digit numbers” are only for readability, and are NOT in the keyfile.
Keyfile starts with “04193b” and ends with “eb205a”!
So how can I decode this into a “plain text private key”??
Is there any way to switch off the signature check when using decrypt:all by now? Missing such a feature I would highly advise not to use encryption at all. Simply renaming a folder lost me 10.000 photos of the last year and I now have to do a recovery.
I did find a way to turn off the signature check by adding return true; to the checkSignature() in apps/encryption/lib/Crypto/Crypt.php. I added it in the if clause right before the exception is thrown. But switching it off isn’t enough.
The reason for is that the server reports a different filesize to the client and breaks off the download too early. The client therefore thinks that the connection was lost and reports an error. But the files is already downloaded successfully (f.e. in Chrome you just have to remove .crdownload at the end of the downloaded file). I have written a small Python 3 script that can download the files via WebDav. It is a dirty hack, but at least I can recover my files.
(Sorry for repeating this post so often, but there are many forum entries and issues that people looking for a solution might find via Google )
After checking the downloads I discovered that while the JPEGs open without any problem my RAW files didn’t. Looking closer at the JPEGs I could see that in the last pixel line there were some blocks missing. So the download wasn’t finished. Following up on the error message that gets displayed in Nextcloud in the hasSignature() call of splitMetaData() I discovered that the encrypted data field was empty and therefore there can’t be a signature in the file. To bypass this I have added following if clause into the function symmetricDecryptFileContent() in apps/encryption/lib/Crypto/Crypt.php:
if ($keyFileContents == '') {
return '';
}
I have put this code as the first command in the symmetricDecryptFileContent(). Together with disabling the signature check (putting return true; in the checkSignature() function in the same file):
private function checkSignature($data, $passPhrase, $expectedSignature) {
$signature = $this->createSignature($data, $passPhrase);
if (!hash_equals($expectedSignature, $signature)) {
return true;
throw new GenericEncryptionException('Bad Signature', $this->l->t('Bad Signature'));
}
}
I can now see the previews in the web interface and download all files decrypted and even download the folders as zip-files. My script is not necessary anymore