git.iko.soy/typeable/nixpkgs
on master help sign in
signal-desktop: Add a Python wrapper to re-encrypt DBs

This is super hacky... :o But then again it should at least prevent data loss. Note: At least this isn't required for NixOS 21.05.

commit45bd7b39a444c904986324b5f7c46ba867612575 authorMichael Weiss <dev.primeos@gmail.com> dateFri 14 May 2021, 21:59 (6 years ago) parent940dfa9
2 files changed+106−1
pkgs/applications/networking/instant-messengers/signal-desktop/db-reencryption-wrapper.py+92 pkgs/applications/networking/instant-messengers/signal-desktop/default.nix+14−1
pkgs/applications/networking/instant-messengers/signal-desktop/db-reencryption-wrapper.pynew file+92
@@ -0,0 +1,92 @@
1+#!@PYTHON@
2+
3+import json
4+import os
5+import re
6+import shlex
7+import sqlite3
8+import subprocess
9+import sys
10+
11+
12+DB_PATH = os.path.join(os.environ['HOME'], '.config/Signal/sql/db.sqlite')
13+DB_COPY = os.path.join(os.environ['HOME'], '.config/Signal/sql/db.tmp')
14+CONFIG_PATH = os.path.join(os.environ['HOME'], '.config/Signal/config.json')
15+
16+
17+def zenity_askyesno(title, text):
18+ args = [
19+ '@ZENITY@',
20+ '--question',
21+ '--title',
22+ shlex.quote(title),
23+ '--text',
24+ shlex.quote(text)
25+ ]
26+ return subprocess.run(args).returncode == 0
27+
28+
29+def start_signal():
30+ os.execvp('@SIGNAL-DESKTOP@', ['@SIGNAL-DESKTOP@'] + sys.argv[1:])
31+
32+
33+def copy_pragma(name):
34+ result = subprocess.run([
35+ '@SQLCIPHER@',
36+ DB_PATH,
37+ f"PRAGMA {name};"
38+ ], check=True, capture_output=True).stdout
39+ result = re.search(r'[0-9]+', result.decode()).group(0)
40+ subprocess.run([
41+ '@SQLCIPHER@',
42+ DB_COPY,
43+ f"PRAGMA key = \"x'{key}'\"; PRAGMA {name} = {result};"
44+ ], check=True, capture_output=True)
45+
46+
47+try:
48+ # Test if DB is encrypted:
49+ con = sqlite3.connect(f'file:{DB_PATH}?mode=ro', uri=True)
50+ cursor = con.cursor()
51+ cursor.execute("SELECT name FROM sqlite_master WHERE type='table';")
52+ con.close()
53+except:
54+ # DB is encrypted, everything ok:
55+ start_signal()
56+
57+
58+# DB is unencrypted!
59+answer = zenity_askyesno(
60+ "Error: Signal-Desktop database is not encrypted",
61+ "Should we try to fix this automatically?"
62+ + "You likely want to backup ~/.config/Signal/ first."
63+)
64+if not answer:
65+ answer = zenity_askyesno(
66+ "Launch Signal-Desktop",
67+ "DB is unencrypted, should we still launch Signal-Desktop?"
68+ + "Warning: This could result in data loss!"
69+ )
70+ if not answer:
71+ print('Aborted')
72+ sys.exit(0)
73+ start_signal()
74+
75+# Re-encrypt the DB:
76+with open(CONFIG_PATH) as json_file:
77+ key = json.load(json_file)['key']
78+result = subprocess.run([
79+ '@SQLCIPHER@',
80+ DB_PATH,
81+ f" ATTACH DATABASE '{DB_COPY}' AS signal_db KEY \"x'{key}'\";"
82+ + " SELECT sqlcipher_export('signal_db');"
83+ + " DETACH DATABASE signal_db;"
84+]).returncode
85+if result != 0:
86+ print('DB encryption failed')
87+ sys.exit(1)
88+# Need to copy user_version and schema_version manually:
89+copy_pragma('user_version')
90+copy_pragma('schema_version')
91+os.rename(DB_COPY, DB_PATH)
92+start_signal()
pkgs/applications/networking/instant-messengers/signal-desktop/default.nix+14−1
@@ -10,6 +10,9 @@
1010, hunspellDicts, spellcheckerLanguage ? null # E.g. "de_DE"
1111# For a full list of available languages:
1212# $ cat pkgs/development/libraries/hunspell/dictionaries.nix | grep "dictFileName =" | awk '{ print $3 }'
13+, python3
14+, gnome
15+, sqlcipher
1316}:
1417
1518let
@@ -112,7 +115,7 @@ in stdenv.mkDerivation rec {
112115
113116 # Symlink to bin
114117 mkdir -p $out/bin
115− ln -s $out/lib/Signal/signal-desktop $out/bin/signal-desktop
118+ ln -s $out/lib/Signal/signal-desktop $out/bin/signal-desktop-unwrapped
116119
117120 runHook postInstall
118121 '';
@@ -137,6 +140,16 @@ in stdenv.mkDerivation rec {
137140 patchelf --add-needed ${libpulseaudio}/lib/libpulse.so $out/lib/Signal/resources/app.asar.unpacked/node_modules/ringrtc/build/linux/libringrtc.node
138141 '';
139142
143+ postFixup = ''
144+ # This hack is temporarily required to avoid data-loss for users:
145+ cp ${./db-reencryption-wrapper.py} $out/bin/signal-desktop
146+ substituteInPlace $out/bin/signal-desktop \
147+ --replace '@PYTHON@' '${python3}/bin/python3' \
148+ --replace '@ZENITY@' '${gnome.zenity}/bin/zenity' \
149+ --replace '@SQLCIPHER@' '${sqlcipher}/bin/sqlcipher' \
150+ --replace '@SIGNAL-DESKTOP@' "$out/bin/signal-desktop-unwrapped"
151+ '';
152+
140153 # Tests if the application launches and waits for "Link your phone to Signal Desktop":
141154 passthru.tests.application-launch = nixosTests.signal-desktop;
142155