add option to let user add password to decrypt db key

main
Paul Feitzinger 5 months ago
parent 4e3066be0f
commit c9d326e926

@ -5,6 +5,8 @@ import logging
from dataclasses import dataclass from dataclasses import dataclass
from collections import defaultdict from collections import defaultdict
from utils import decrypt_encrypted_key
import pandas as pd import pandas as pd
from pandas import DataFrame from pandas import DataFrame
from sklearn.feature_extraction import DictVectorizer from sklearn.feature_extraction import DictVectorizer
@ -28,20 +30,22 @@ class Message:
body: str body: str
def get_decryption_key(path): def get_decryption_key(path, password=None):
with open(path) as fh: with open(path) as fh:
config = json.load(fh) config = json.load(fh)
key = None
if 'key' in config and 'encryptedKey' in config: if 'key' in config and 'encryptedKey' in config:
raise Exception('config has both key and encryptedKey in it') raise Exception('config has both `key` and `encryptedKey` in it')
if 'key' in config: if 'key' in config:
key = 'key' if password is not None:
raise Exception('you cannot use the -p option with your signal config')
return config['key']
elif 'encryptedKey' in config: elif 'encryptedKey' in config:
key = 'encryptedKey' if password is None:
raise Exception('you must use the -p option to pass the password in for your signal db')
return decrypt_encrypted_key(password, config['encryptedKey'])
else: else:
dict_keys = ', '.join(str(x) for x in config.keys()) dict_keys = ', '.join(str(x) for x in config.keys())
raise Exception(f'no key found for db in config.json, only saw: {dict_keys}') raise Exception(f'no `key` or `encryptedKey` found for db in config.json, only saw: {dict_keys}')
return config[key]
def query_signal_db(db, key, query): def query_signal_db(db, key, query):

@ -8,6 +8,7 @@ table = subparsers.add_parser('table')
table.set_defaults(func=dump_message_count_table) table.set_defaults(func=dump_message_count_table)
table.add_argument('--filter_file', '-f') table.add_argument('--filter_file', '-f')
table.add_argument('--output', '-o', default='table.csv') table.add_argument('--output', '-o', default='table.csv')
table.add_argument('--password', '-p')
user = subparsers.add_parser('user') user = subparsers.add_parser('user')
user.add_argument('regex') user.add_argument('regex')
@ -21,10 +22,12 @@ parser.add_argument('--db',
default=expanduser('~/.config/Signal/sql/db.sqlite')) default=expanduser('~/.config/Signal/sql/db.sqlite'))
parser.add_argument('--config', parser.add_argument('--config',
default=expanduser('~/.config/Signal/config.json')) default=expanduser('~/.config/Signal/config.json'))
if __name__ == "__main__": if __name__ == "__main__":
args = parser.parse_args() args = parser.parse_args()
key = get_decryption_key(args.config)
args = vars(args) args = vars(args)
password = args.pop('password')
key = get_decryption_key(args['config'], password)
args.pop('config') args.pop('config')
func = args.pop('func') func = args.pop('func')
func(**args, key=key) func(**args, key=key)

@ -1,2 +1,3 @@
pandas pandas
pycryptodome
scikit-learn scikit-learn

@ -0,0 +1,28 @@
# from https://gist.github.com/flatz/3f242ab3c550d361f8c6d031b07fb6b1
import os
import json
from Crypto.Protocol.KDF import PBKDF2
from Crypto.Hash import SHA1
from Crypto.Cipher import AES
from Crypto.Util.Padding import unpad
def aes_decrypt_cbc(key, iv, data):
cipher = AES.new(key, AES.MODE_CBC, iv)
return cipher.decrypt(data)
prefix = b'v11'
salt = 'saltysalt'
derived_key_len = 128 // 8
num_iterations = 1003
iv = b' ' * 16
def decrypt_encrypted_key(password, encrypted_key):
encrypted_key = bytes.fromhex(encrypted_key)
assert encrypted_key.startswith(prefix)
encrypted_key = encrypted_key[len(prefix):]
kek = PBKDF2(password, salt, dkLen = derived_key_len, count = num_iterations, hmac_hash_module = SHA1)
decrypted_key = unpad(aes_decrypt_cbc(kek, iv, encrypted_key), block_size = 16).decode('ascii')
print('0x' + decrypted_key)

@ -1,9 +1,10 @@
#/usr/bin/sh #/usr/bin/sh
FILTER=0 FILTER=0
while getopts "c:f" flag; do while getopts "c:p:f" flag; do
case "$flag" in case "$flag" in
c) SIGNAL_DIR=$OPTARG;; c) SIGNAL_DIR=$OPTARG;;
p) PASSWORD=$OPTARG;;
f) FILTER=1; f) FILTER=1;
esac esac
done done
@ -16,8 +17,17 @@ fi
OUTDIR="$(pwd)/output" OUTDIR="$(pwd)/output"
if [ $FILTER -eq 1 ]; then # TODO: learn how to use getopts and rewrite this. this is dumb.
docker run -it -v "$SIGNAL_DIR":/root/.config/Signal -v "$OUTDIR":/output -v "$(pwd)/config":/config sigint -f /config/chat_list.txt if [ -z "${PASSWORD+x}" ]; then
if [ $FILTER -eq 1 ]; then
docker run -it -v "$SIGNAL_DIR":/root/.config/Signal -v "$OUTDIR":/output -v "$(pwd)/config":/config sigint -f /config/chat_list.txt
else
docker run -it -v "$SIGNAL_DIR":/root/.config/Signal -v "$OUTDIR":/output sigint
fi
else else
docker run -it -v "$SIGNAL_DIR":/root/.config/Signal -v "$OUTDIR":/output sigint if [ $FILTER -eq 1 ]; then
docker run -it -v "$SIGNAL_DIR":/root/.config/Signal -v "$OUTDIR":/output -v "$(pwd)/config":/config sigint -f /config/chat_list.txt --password "$PASSWORD"
else
docker run -it -v "$SIGNAL_DIR":/root/.config/Signal -v "$OUTDIR":/output sigint --password "$PASSWORD"
fi
fi fi

Loading…
Cancel
Save