Make signalDesktopDecrypt configurable
This commit is contained in:
@@ -5,17 +5,24 @@ from Crypto.Util import Padding
|
|||||||
from Crypto.Hash import HMAC, SHA256
|
from Crypto.Hash import HMAC, SHA256
|
||||||
import sys
|
import sys
|
||||||
from getpass import getpass
|
from getpass import getpass
|
||||||
|
from docopt import docopt
|
||||||
|
from os import listdir
|
||||||
|
|
||||||
IV_LENGTH = 16
|
IV_LENGTH = 16
|
||||||
NONCE_LENGTH = 16
|
NONCE_LENGTH = 16
|
||||||
MAC_LENGTH = 16
|
MAC_LENGTH = 16
|
||||||
|
|
||||||
|
iv = bytearray(IV_LENGTH)
|
||||||
|
|
||||||
FORMAT_STRING = 'window.Signal.Backup.exportToDirectory(\'{0}\', {{\'key\':new Uint8Array({1})}});'
|
FORMAT_STRING = 'window.Signal.Backup.exportToDirectory(\'{0}\', {{\'key\':new Uint8Array({1})}});'
|
||||||
|
|
||||||
def read_file(path):
|
USAGE_STRING = """
|
||||||
with open(path, 'rb') as fh:
|
Usage:
|
||||||
return fh.read()
|
signalDesktopDecrypt generate --path <path>
|
||||||
|
signalDesktopDecrypt decrypt --path <path>
|
||||||
|
"""
|
||||||
|
|
||||||
def decrypt(cipherkey, iv, ciphertext):
|
def decrypt(cipherkey, ciphertext):
|
||||||
cipher = AES.new(cipherkey, AES.MODE_CBC, iv)
|
cipher = AES.new(cipherkey, AES.MODE_CBC, iv)
|
||||||
return Padding.unpad(cipher.decrypt(ciphertext), AES.block_size)
|
return Padding.unpad(cipher.decrypt(ciphertext), AES.block_size)
|
||||||
|
|
||||||
@@ -29,29 +36,52 @@ def generate_key(password):
|
|||||||
m.update(password)
|
m.update(password)
|
||||||
return m.digest()
|
return m.digest()
|
||||||
|
|
||||||
def main():
|
def extract_info(filepath):
|
||||||
password = getpass()
|
data = ''
|
||||||
key = generate_key(password.encode('utf-8'))
|
try:
|
||||||
|
with open(filepath, 'rb') as fh:
|
||||||
# generate string to be pasted in Signal-Desktop
|
data = fh.read()
|
||||||
if len(sys.argv) == 1:
|
except FileNotFoundError:
|
||||||
print(FORMAT_STRING.format('/tmp/signal/', [elem for elem in key]))
|
print(filepath + ' was not found, please check --path argument')
|
||||||
return
|
sys.exit(1)
|
||||||
|
|
||||||
# read encrypted file from disk
|
|
||||||
data = read_file(sys.argv[1])
|
|
||||||
|
|
||||||
# crypto foo
|
|
||||||
iv = bytearray(IV_LENGTH) # IV is just 16 zeros
|
|
||||||
|
|
||||||
|
# extract none
|
||||||
nonce = data[:NONCE_LENGTH]
|
nonce = data[:NONCE_LENGTH]
|
||||||
|
# extract ciphertext
|
||||||
ciphertext = data[NONCE_LENGTH:-MAC_LENGTH]
|
ciphertext = data[NONCE_LENGTH:-MAC_LENGTH]
|
||||||
|
|
||||||
cipherkey = generate_cipherkey(key, nonce)
|
return nonce, ciphertext
|
||||||
|
|
||||||
# save decrypted file to 'decrypted'
|
def main():
|
||||||
with open('decrypted', 'wb') as fh:
|
params = docopt(USAGE_STRING)
|
||||||
fh.write(decrypt(cipherkey, iv, ciphertext))
|
|
||||||
|
if params['generate']:
|
||||||
|
# ask for password
|
||||||
|
password = getpass()
|
||||||
|
key = generate_key(password.encode('utf-8'))
|
||||||
|
|
||||||
|
# generate string to be pasted in Signal-Desktop
|
||||||
|
print('Use ctrl+i to open the developer tools in the signal desktop app, switch to console and paste the following text:\n')
|
||||||
|
print(FORMAT_STRING.format(params['<path>'], [elem for elem in key]))
|
||||||
|
|
||||||
|
return
|
||||||
|
elif params['decrypt']:
|
||||||
|
# ask for password
|
||||||
|
password = getpass()
|
||||||
|
key = generate_key(password.encode('utf-8'))
|
||||||
|
|
||||||
|
# extract messages.zip
|
||||||
|
nonce, ciphertext = extract_info(params['<path>'] + '/messages.zip')
|
||||||
|
cipherkey = generate_cipherkey(key, nonce)
|
||||||
|
with open(params['<path>'] + '/messages.zip', 'wb') as fh:
|
||||||
|
fh.write(decrypt(cipherkey, ciphertext))
|
||||||
|
|
||||||
|
# extract attachments
|
||||||
|
for filename in listdir(params['<path>'] + '/attachments/'):
|
||||||
|
nonce, ciphertext = extract_info(params['<path>'] + '/attachments/' + filename)
|
||||||
|
cipherkey = generate_cipherkey(key, nonce)
|
||||||
|
with open(params['<path>'] + '/attachments/' + filename, 'wb') as fh:
|
||||||
|
fh.write(decrypt(cipherkey, ciphertext))
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
main()
|
main()
|
||||||
|
|||||||
Reference in New Issue
Block a user