Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Not a database error when running sigtop db #48

Closed
sylasabdullahnguyen opened this issue Jul 26, 2024 · 13 comments
Closed

Not a database error when running sigtop db #48

sylasabdullahnguyen opened this issue Jul 26, 2024 · 13 comments

Comments

@sylasabdullahnguyen
Copy link

sylasabdullahnguyen commented Jul 26, 2024

Hello,

I am getting the following error when running sigtop db signal.db, sigtop check and sigtop query pragma user_version:

sigtop: cannot verify key: cannot execute SQL statement: file is not a database

I am on a MacBook M1 Pro with Ventura 13.6.3. I have the following versions of sqlite and sqlcipher:

3.41.2 2023-03-22 11:56:21 0d1fc92f94cb6b76bffe3ec34d69cffde2924203304e8ffc4155597af0c191da

or

3.46.0 2024-05-23 13:25:27 96c92aba00c8375bc32fafcdf12429c58bd8aabfcadab6683e35bbb9cdebf19e (64-bit)

after running

echo 'export PATH="/usr/local/opt/sqlite/bin:$PATH"' >> \~/.zshrc
source ~/.zshrc

and

3.45.3 2024-04-15 13:34:05 8653b758870e6ef0c98d46b3ace27849054af85da891eb121e9aaa537f1ealt1 (64-bit) (SQLCipher 4.6.0 community)

From what I've found googling, the "not a database" issue generally means that the file is corrupted--but the Signal app itself seems to be functioning fine (for now, anyway). This is the output of hexdump -C db.sqlite | head -1:

00000000  22 45 77 04 d3 ae 7f d1  28 01 17 ca 87 9b 7e 93  |"Ew.....(.....~.|

This seems to be a bad sign according to what I read here, except that my Signal app starts up without an error. I've tried accessing the db.sqlite file (copied over from the /sql folder of the Signal app) directly in:

  • DB Browser for SQLite (v3.13.0),
  • SQLite Studio (v3.4.4),
  • using node and @signalapp/better-sqlite3 in a JS script,
  • sqlcipher from terminal, and
  • sqlite3 from terminal

with no success. I have also updated sigtop to the latest release. Would you happen to have an idea as to what is going on?

@flatz
Copy link

flatz commented Jul 26, 2024

The key format for SQLite was changed in latest versions of desktop Signal. It's now stored in encrypted form in JSON under key encryptedKey, e.g. on MacOS: ~/Library/Application Support/Signal/config.json

To decrypt it the special OS mechanism for safe storage is used, like Keychain on MacOS. First, you need to extract it from safe storage (for example, manually or via some API), it's Base64 encoded and used as input to PBKDF2 HMAC SHA-1 algorithm with salt set to saltysalt, number of iterations set to 1003 and derived key length set to 128 bit. The resulting 128-bit key is our key encryption key (KEK) which will be used later.

Then you should take hexadecimal string of encrypted key from Signal's JSON config, decode it as bytes and strip leading prefix v10. Then apply the result to AES-128 CBC algorithm with KEK and IV consisted of 16 bytes of space characters, unpad it using block size of 16 bytes. You should get ASCII text with hexadecimal character which is your key for SQLite database. It can be used with modifications to sigtop or by crafting old-style JSON config with key parameter that have value of this hexadecimal string.

PoC: https://gist.github.com/flatz/3f242ab3c550d361f8c6d031b07fb6b1

tbvdm pushed a commit that referenced this issue Jul 27, 2024
@tbvdm
Copy link
Owner

tbvdm commented Jul 27, 2024

As @flatz explained, Signal Desktop recently started to encrypt the database key in config.json. The old unencrypted key would continue to be available as a temporary fallback, but this fallback was removed sooner than I had expected.

I have pushed a commit that should make it possible to decrypt the database key on macOS and Linux (GNOME). For the time being, you will have to fetch the encryption password manually.

@sylasabdullahnguyen, could you please try the following:

brew upgrade --fetch-HEAD sigtop
security find-generic-password -ws "Signal Safe Storage" >passfile
sigtop check -p passfile
sigtop db -p passfile signal.db

Note that passfile will contain the password used to encrypt the database key. Be careful.

@sylasabdullahnguyen
Copy link
Author

sylasabdullahnguyen commented Jul 27, 2024

I've managed to do what @flatz suggested and also ran the commands you've suggested successfully with a working signal.db file created and queryable. Thanks to you both!

I am not very familiar with security technology--would storing the encryption password in passfile be any less secure than what Signal Desktop was doing before this update?

@tbvdm
Copy link
Owner

tbvdm commented Jul 28, 2024

It's not less secure. Before the Signal update, you had an unencrypted key in config.json. Now you have an unencrypted key in passfile.

Nevertheless, it's a good idea either to delete passfile when you no longer need it or to store it somewhere safe. Note that you can always recreate passfile using the security command above.

@tbvdm
Copy link
Owner

tbvdm commented Jul 28, 2024

sigtop can now also read the password from standard input so you won't have to create a passfile. For example:

security find-generic-password -ws "Signal Safe Storage" | sigtop db -p - signal.db

@sadsirko
Copy link

any tips for windows users?

tbvdm pushed a commit that referenced this issue Jul 29, 2024
@tbvdm
Copy link
Owner

tbvdm commented Jul 29, 2024

sigtop should now be able to decrypt the database key on Windows. No extra steps are needed.

@tbvdm
Copy link
Owner

tbvdm commented Jul 29, 2024

Here are provisional instructions for Linux.

If you are using GNOME or any other desktop that uses GNOME Keyring, use secret-tool to fetch the encryption password. For example:

secret-tool lookup application Signal >passfile
sigtop export-messages -p passfile messages
sigtop export-attachments -p passfile attachments

(If you are using Signal Beta, replace Signal with "Signal Beta" in the secret-tool command above.)

Note that passfile will contain the password used to encrypt the database key. Be careful. Delete the file when you no longer need it.

If you are using KDE, use kwallet-query to fetch the encryption password. For example:

kwallet-query -f "Chromium Keys" -r "Chromium Safe Storage" kdewallet >passfile
sigtop export-messages -p passfile messages
sigtop export-attachments -p passfile attachments

Again, note that passfile will contain the password used to encrypt the database key. Be careful. Delete the file when you no longer need it.

sigtop can also read the password from standard input so you won't have to create a passfile. For example:

secret-tool lookup application Signal | sigtop export-messages -p - messages

@stefanputz
Copy link

sigtop should now be able to decrypt the database key on Windows. No extra steps are needed.

but how? could you please give some more details? would be much appreciated!

@tbvdm
Copy link
Owner

tbvdm commented Jul 31, 2024

sigtop should now be able to get the encryption key from the keychain on macOS. You no longer have to run the security command and provide a passfile.

@sylasabdullahnguyen, or anyone else on macOS, it would be great if you could give this a try. The following commands should run without problems:

brew upgrade --fetch-HEAD sigtop
sigtop check

@flatz
Copy link

flatz commented Jul 31, 2024

sigtop should now be able to get the encryption key from the keychain on macOS. You no longer have to run the security command and provide a passfile.

@sylasabdullahnguyen, or anyone else on macOS, it would be great if you could give this a try. The following commands should run without problems:

brew upgrade --fetch-HEAD sigtop
sigtop check

The latest version does work on MacOS without manual keychain access. Thanks.

@tbvdm
Copy link
Owner

tbvdm commented Jul 31, 2024

@flatz Great, thanks very much!

@stefanputz The database key is encrypted with the encryption key in the file Local State in your Signal directory. The encryption key, in turn, is encrypted with DPAPI (a Windows API). The point of using DPAPI is that, in principle, data can be encrypted and decrypted only by the same user (or rather any program running as that user), and only on the same computer.

So sigtop first decrypts the encryption key with DPAPI. It then uses the (decrypted) encryption key to decrypt the database key. Finally, it uses the (decrypted) database key to decrypt the database.

@branneman
Copy link

@sylasabdullahnguyen, or anyone else on macOS, it would be great if you could give this a try. The following commands should run without problems:

brew upgrade --fetch-HEAD sigtop
sigtop check

Works great for me, it solved the problem! I've tried 2 different machines:

  • MacBook Pro, M2, Sonoma 14.6.1
  • MacBook Pro, Intel i7, Sonoma 14.5

Thanks a lot!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants