Skip to content

Instantly share code, notes, and snippets.

@dguerri
Last active September 25, 2023 09:01
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save dguerri/92d9330bf9e8f1303b4004ddd4e00f00 to your computer and use it in GitHub Desktop.
Save dguerri/92d9330bf9e8f1303b4004ddd4e00f00 to your computer and use it in GitHub Desktop.
Quick shell script to decrypt client-side encrypted file using QNAP HBS *Sync* jobs. Only work with version 2 files - Doesn't work with QNAP HBS Backup jobs!
#!/bin/sh
set -ue
[ "$#" -lt 2 ] && { echo "Syntax: $0 <filename> <key>"; exit 1; }
filename="$1"
key="$2"
# Compose the key by repeating the user input until we have 32 characters (64 hex digits)
openssl_key=""
while [ "$(printf '%s' "${openssl_key}" | wc -m)" -lt 64 ]; do
openssl_key=${openssl_key}$(printf '%s' "${key}" | od -An -tx1 | tr -d '\ \n')
done
openssl_key=$(printf '%s' "${openssl_key}" | cut -c1-64)
# Determine if the cleartext has been compressed
compressed="$(dd if="${filename}" bs=1 skip=9 count=1 2>/dev/null | od -An -tx1 | tr -d '\ \n')"
[ "${compressed}" -ne 0 ] && echo "Compressed, use bzip2 to decompress" >&2
# Decipher the header
header="$(dd if="${filename}" bs=1 skip=16 count=64 2>/dev/null | \
openssl aes-256-ecb -d -K "${openssl_key}" -nopad | od -An -tx1 | tr -d '\ \n')"
# Extract key and iv from the header
ckey="$(printf '%s' "${header}" | cut -c17-80)"
salt="$(printf '%s' "${header}" | cut -c81-112)"
# Decipher the file
dd if="${filename}" bs=1 skip=80 2>/dev/null | openssl aes-256-cbc -d -K "${ckey}" -iv "${salt}"
@dguerri
Copy link
Author

dguerri commented Mar 28, 2021

Tested on MacOS 11.2.3 and 11.5.1, OpenSSL 1.1.1j and LibreSSL 2.8.3

@mnylen
Copy link

mnylen commented Apr 15, 2021

Hi! I found this through QNAP forums. There you mentioned that this only works with version 2 of the algorithm. Do you have any idea how to check which version the file is using? (I would imagine I'm using the latest version, as I just setup my brand-new QNAP NAS).

I'm getting the "Compressed, use bzip2 to decompress" message, but bzip2 says the file is not a bzip2 file. It still proceeds to trying to decrypt the file, but fails with "bad decrypt" error message. It might be a M1 issue - I'm running this on a M1 MBP with Big Sur installed.

@dguerri
Copy link
Author

dguerri commented Apr 23, 2021

Hey @mnylen, sorry for the delayed reply.

There are some magic numbers at the very beginning of the encrypted files. This is what I know:

# Magic - Version 1
5f  5f  51  43  53  5f  5f

# Magic - Version 2 - Compressed
4b  ca  94  72  5e  83  1c  31  01  01

# Magic - Version 2 - Not Compressed
4b  ca  94  72  5e  83  1c  31  01  00

In this quick script I don't check the header, but I guess it would be a nice thing to do!

@ceelian
Copy link

ceelian commented Aug 2, 2021

Not working for me on Mac OS 11.4 (libressl v2.8) . Source file was encrypted on a 2021 NAS Model QTS 4.5.4.1741 with HBS 3 (V17.1.0719)

Have manually checked the source file, it is Magic - Version 2

And that is the error:

bad decrypt
4692311724:error:06FFF064:digital envelope routines:CRYPTO_internal:bad decrypt:/System/Volumes/Data/SWE/macOS/BuildRoots/e90674e518/Library/Caches/com.apple.xbs/Sources/libressl/libressl-56.60.2/libressl-2.8/crypto/evp/evp_enc.c:521

@dguerri
Copy link
Author

dguerri commented Aug 2, 2021

@ceelian, sorry to hear that.
I have the same versions installed on my NAS, but I am using Big Sur. I don't think it should make a difference.

Typically, I get that error when the password is incorrect.

Can you please summarize the configuration settings of your sync job?
I have client-side encryption enabled in the Policy "tab" and no compression in Advanced settings, under "Methods".

Thanks

@ceelian
Copy link

ceelian commented Aug 3, 2021

@dguerri thx for the quick answer and thx for the script 🙏..
That's very interesting because I am also using Big Sur (11.4 is Big Sur). I also checked the passphrase multiple times, and it works in a restore job but not with the script. I will have a look at the configuration of the backup job later today when I have access to the NAS and get back to you then.

@dguerri
Copy link
Author

dguerri commented Aug 3, 2021

I mean 11.5, yes Big Sur.
Since you mentioned passphrase, I am thinking that there could be a problem with the creation of openssl_key here.
Is your passphrase longer than 32 characters, by any chance?

@ceelian
Copy link

ceelian commented Aug 3, 2021

Okay, so there is one minor version difference in the OS but as you said that shouldn't make the difference. I checked the settings and I deactivated QDedup. Maybe this is what you meant with compression because I couldn't find any other compression option? Password is for testing just 123456 so it is not exceeding 32 char limit.

I copied your script in a decrypt.sh and did the following with a hello_world.txt with the Content "Hello World!" which is encrypted with 123456 passphrase.

cat hello_world.txt | base64
SGVsbG8gV29ybGQh

# Then Qnap does the Backup with encryption Job

./decrypt.sh hello_world.txt 123456
bad decrypt
4651892396:error:06FFF064:digital envelope routines:CRYPTO_internal:bad decrypt:/System/Volumes/Data/SWE/macOS/BuildRoots/e90674e518/Library/Caches/com.apple.xbs/Sources/libressl/libressl-56.60.2/libressl-2.8/crypto/evp/evp_enc.c:521:

# the encrypted file
cat hello_world.txt 
Kʔr^?1?W?7?b?s??z[)H)Cޠ??????{????}?m?~=??????}{u?A?1V???t??0Sż(?????>g?????

# the encrypted file content base64 encoded
cat hello_world.txt | base64
S8qUcl6DHDEBAAAAAAAAANJX8jemYtdz9MF6WylIKUPeoBOCngSQHT/C2nsF5avdyfN9wG3hfj2AhoG3jsl9e3WuQe8xVpm36nTv9DBTxbwo//YEv6EDnj5npIqrlsMK

I added the base64 stream of the binary encrypted files and also of the source file so to make sure it is reproducable on a binary accurate level on other machines.

Thanks for any hints.

@dguerri
Copy link
Author

dguerri commented Aug 3, 2021

It's very hard to tell what's going on...
I need to do some testing. One thing that looks different is that I am doing a sync job, with encryption, while you are doing a backup.
The "external" header seems to match. But there is an additional header, from which I extract key and iv, which may be different...

Will look into it later :)

@dguerri
Copy link
Author

dguerri commented Aug 3, 2021

@dguerri
Copy link
Author

dguerri commented Aug 4, 2021

I did some testing.
I think that the encryption key used by QNAP HSB Backup is derived from the user password with a different algorithm.
From Sync jobs, the password used to decrypt the header is a 64 bytes long concatenation of the user password.

Maybe the backup job concatenates something to the user password... but honestly is hard to tell!

@ceelian
Copy link

ceelian commented Aug 20, 2021

@dguerry thank you, I was 2 weeks AFK. Will try soon and let you know. Thank you a lot for the investigations.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment