Python 3 fixes

This commit is contained in:
Aldo Bleeker 2020-11-22 16:03:45 +01:00
parent a74f37c79e
commit 74bcf33591
6 changed files with 62 additions and 57 deletions

35
DeDRM_plugin/androidkindlekey.py Normal file → Executable file
View File

@ -136,7 +136,7 @@ class AndroidObfuscationV2(AndroidObfuscation):
''' '''
count = 503 count = 503
password = 'Thomsun was here!' password = b'Thomsun was here!'
def __init__(self, salt): def __init__(self, salt):
key = self.password + salt key = self.password + salt
@ -182,7 +182,7 @@ def get_serials1(path=STORAGE1):
obfuscation = AndroidObfuscation() obfuscation = AndroidObfuscation()
def get_value(key): def get_value(key):
encrypted_key = obfuscation.encrypt(key) encrypted_key = obfuscation.encrypt(a2b_hex(key))
encrypted_value = storage.get(encrypted_key) encrypted_value = storage.get(encrypted_key)
if encrypted_value: if encrypted_value:
return obfuscation.decrypt(encrypted_value) return obfuscation.decrypt(encrypted_value)
@ -217,15 +217,14 @@ def get_serials2(path=STORAGE2):
import sqlite3 import sqlite3
connection = sqlite3.connect(path) connection = sqlite3.connect(path)
cursor = connection.cursor() cursor = connection.cursor()
cursor.execute('''select userdata_value from userdata where userdata_key like '%/%token.device.deviceserialname%' ''') cursor.execute('''select device_data_value from device_data where device_data_key like '%serial.number%' ''')
userdata_keys = cursor.fetchall() device_data_keys = cursor.fetchall()
dsns = [] dsns = []
for userdata_row in userdata_keys: for device_data_row in device_data_keys:
try: try:
if userdata_row and userdata_row[0]: if device_data_row and device_data_row[0]:
userdata_utf8 = userdata_row[0].encode('utf8') if len(device_data_row[0]) > 0:
if len(userdata_utf8) > 0: dsns.append(device_data_row[0])
dsns.append(userdata_utf8)
except: except:
print("Error getting one of the device serial name keys") print("Error getting one of the device serial name keys")
traceback.print_exc() traceback.print_exc()
@ -238,9 +237,12 @@ def get_serials2(path=STORAGE2):
for userdata_row in userdata_keys: for userdata_row in userdata_keys:
try: try:
if userdata_row and userdata_row[0]: if userdata_row and userdata_row[0]:
userdata_utf8 = userdata_row[0].encode('utf8') if len(userdata_row[0]) > 0:
if len(userdata_utf8) > 0: if ',' in userdata_row[0]:
tokens.append(userdata_utf8) splits = userdata_row[0].split(',')
for split in splits:
tokens.append(split)
tokens.append(userdata_row[0])
except: except:
print("Error getting one of the account token keys") print("Error getting one of the account token keys")
traceback.print_exc() traceback.print_exc()
@ -249,11 +251,10 @@ def get_serials2(path=STORAGE2):
serials = [] serials = []
for x in dsns: for x in dsns:
for y in tokens:
serials.append(x) serials.append(x)
for y in tokens:
serials.append('%s%s' % (x, y))
for y in tokens:
serials.append(y) serials.append(y)
serials.append(x+y)
return serials return serials
def get_serials(path=STORAGE): def get_serials(path=STORAGE):
@ -275,7 +276,7 @@ def get_serials(path=STORAGE):
try : try :
read = open(path, 'rb') read = open(path, 'rb')
head = read.read(24) head = read.read(24)
if head[:14] == 'ANDROID BACKUP': if head[:14] == b'ANDROID BACKUP':
output = StringIO(zlib.decompress(read.read())) output = StringIO(zlib.decompress(read.read()))
except Exception: except Exception:
pass pass
@ -313,7 +314,7 @@ def getkey(outfile, inpath):
if len(keys) > 0: if len(keys) > 0:
with open(outfile, 'w') as keyfileout: with open(outfile, 'w') as keyfileout:
for key in keys: for key in keys:
keyfileout.write(key) keyfileout.write(b2a_hex(key))
keyfileout.write("\n") keyfileout.write("\n")
return True return True
return False return False

View File

@ -6,7 +6,7 @@ __license__ = 'GPL v3'
# Python 3, September 2020 # Python 3, September 2020
# Standard Python modules. # Standard Python modules.
import os, traceback, json, binascii import os, traceback, json, codecs
from PyQt5.Qt import (Qt, QWidget, QHBoxLayout, QVBoxLayout, QLabel, QLineEdit, from PyQt5.Qt import (Qt, QWidget, QHBoxLayout, QVBoxLayout, QLabel, QLineEdit,
QGroupBox, QPushButton, QListWidget, QListWidgetItem, QGroupBox, QPushButton, QListWidget, QListWidgetItem,
@ -378,7 +378,7 @@ class ManageKeysDialog(QDialog):
with open(fpath,'rb') as keyfile: with open(fpath,'rb') as keyfile:
new_key_value = keyfile.read() new_key_value = keyfile.read()
if self.binary_file: if self.binary_file:
new_key_value = binascii.b2a_hex(new_key_value) new_key_value = codecs.encode(new_key_value,'hex')
elif self.json_file: elif self.json_file:
new_key_value = json.loads(new_key_value) new_key_value = json.loads(new_key_value)
elif self.android_file: elif self.android_file:
@ -433,18 +433,18 @@ class ManageKeysDialog(QDialog):
if filename: if filename:
if self.binary_file: if self.binary_file:
with open(filename, 'wb') as fname: with open(filename, 'wb') as fname:
fname.write(binascii.a2b_hex(self.plugin_keys[keyname])) fname.write(codecs.decode(self.plugin_keys[keyname],'hex'))
elif self.json_file: elif self.json_file:
with open(filename, 'w') as fname: with open(filename, 'w') as fname:
fname.write(json.dumps(self.plugin_keys[keyname])) fname.write(json.dumps(self.plugin_keys[keyname]))
elif self.android_file: elif self.android_file:
with open(filename, 'w') as fname: with open(filename, 'w') as fname:
for key in self.plugin_keys[keyname]: for key in self.plugin_keys[keyname]:
fname.write(key.decode('utf-8')) fname.write(key)
fname.write('\n') fname.write('\n')
else: else:
with open(filename, 'w') as fname: with open(filename, 'w') as fname:
fname.write(self.plugin_keys[keyname].decode('utf-8')) fname.write(self.plugin_keys[keyname])
@ -673,7 +673,7 @@ class AddEReaderDialog(QDialog):
@property @property
def key_value(self): def key_value(self):
from calibre_plugins.dedrm.erdr2pml import getuser_key as generate_ereader_key from calibre_plugins.dedrm.erdr2pml import getuser_key as generate_ereader_key
return binascii.b2a_hex(generate_ereader_key(self.user_name, self.cc_number)) return codecs.encode(generate_ereader_key(self.user_name, self.cc_number),'hex')
@property @property
def user_name(self): def user_name(self):
@ -755,7 +755,7 @@ class AddAdeptDialog(QDialog):
@property @property
def key_value(self): def key_value(self):
return binascii.b2a_hex(self.default_key) return codecs.encode(self.default_key,'hex')
def accept(self): def accept(self):

View File

@ -542,7 +542,7 @@ def usage():
print(" It's enough to enter the last 8 digits of the credit card number") print(" It's enough to enter the last 8 digits of the credit card number")
return return
def getuser_key(name, cc): def getuser_key(name,cc):
newname = "".join(c for c in name.lower() if c >= 'a' and c <= 'z' or c >= '0' and c <= '9') newname = "".join(c for c in name.lower() if c >= 'a' and c <= 'z' or c >= '0' and c <= '9')
cc = cc.replace(" ","") cc = cc.replace(" ","")
return struct.pack('>LL', binascii.crc32(bytes(newname.encode('utf-8'))) & 0xffffffff, binascii.crc32(bytes(cc[-8:].encode('utf-8'))) & 0xffffffff) return struct.pack('>LL', binascii.crc32(bytes(newname.encode('utf-8'))) & 0xffffffff, binascii.crc32(bytes(cc[-8:].encode('utf-8'))) & 0xffffffff)
@ -580,9 +580,9 @@ def cli_main():
elif len(args)==4: elif len(args)==4:
infile, outpath, name, cc = args infile, outpath, name, cc = args
print(binascii.b2a_hex(getuser_key(name, cc))) print(binascii.b2a_hex(getuser_key(name,cc)))
return decryptBook(infile, outpath, make_pmlz, getuser_key(name, cc)) return decryptBook(infile, outpath, make_pmlz, getuser_key(name,cc))
if __name__ == "__main__": if __name__ == "__main__":

46
DeDRM_plugin/ineptepub.py Normal file → Executable file
View File

@ -203,6 +203,7 @@ def _load_crypto_libcrypto():
def _load_crypto_pycrypto(): def _load_crypto_pycrypto():
from Crypto.Cipher import AES as _AES from Crypto.Cipher import AES as _AES
from Crypto.PublicKey import RSA as _RSA from Crypto.PublicKey import RSA as _RSA
from Crypto.Cipher import PKCS1_v1_5 as _PKCS1_v1_5
# ASN.1 parsing code from tlslite # ASN.1 parsing code from tlslite
class ASN1Error(Exception): class ASN1Error(Exception):
@ -294,14 +295,14 @@ def _load_crypto_pycrypto():
class AES(object): class AES(object):
def __init__(self, key): def __init__(self, key):
self._aes = _AES.new(key, _AES.MODE_CBC, '\x00'*16) self._aes = _AES.new(key, _AES.MODE_CBC, b'\x00'*16)
def decrypt(self, data): def decrypt(self, data):
return self._aes.decrypt(data) return self._aes.decrypt(data)
class RSA(object): class RSA(object):
def __init__(self, der): def __init__(self, der):
key = ASN1Parser([ord(x) for x in der]) key = ASN1Parser([x for x in der])
key = [key.getChild(x).value for x in range(1, 4)] key = [key.getChild(x).value for x in range(1, 4)]
key = [self.bytesToNumber(v) for v in key] key = [self.bytesToNumber(v) for v in key]
self._rsa = _RSA.construct(key) self._rsa = _RSA.construct(key)
@ -313,7 +314,7 @@ def _load_crypto_pycrypto():
return total return total
def decrypt(self, data): def decrypt(self, data):
return self._rsa.decrypt(data) return _PKCS1_v1_5.new(self._rsa).decrypt(data, 172)
return (AES, RSA) return (AES, RSA)
@ -410,11 +411,14 @@ def decryptBook(userkey, inpath, outpath):
return 1 return 1
bookkey = rsa.decrypt(codecs.decode(bookkey.encode('ascii'), 'base64')) bookkey = rsa.decrypt(codecs.decode(bookkey.encode('ascii'), 'base64'))
# Padded as per RSAES-PKCS1-v1_5 # Padded as per RSAES-PKCS1-v1_5
if len(bookkey) != 16:
if bookkey[-17] != '\x00' and bookkey[-17] != 0: if bookkey[-17] != '\x00' and bookkey[-17] != 0:
print("Could not decrypt {0:s}. Wrong key".format(os.path.basename(inpath))) print("Could not decrypt {0:s}. Wrong key".format(os.path.basename(inpath)))
return 2 return 2
else:
bookkey = bookkey[-16:]
encryption = inf.read('META-INF/encryption.xml') encryption = inf.read('META-INF/encryption.xml')
decryptor = Decryptor(bookkey[-16:], encryption) decryptor = Decryptor(bookkey, encryption)
kwds = dict(compression=ZIP_DEFLATED, allowZip64=False) kwds = dict(compression=ZIP_DEFLATED, allowZip64=False)
with closing(ZipFile(open(outpath, 'wb'), 'w', **kwds)) as outf: with closing(ZipFile(open(outpath, 'wb'), 'w', **kwds)) as outf:
zi = ZipInfo('mimetype') zi = ZipInfo('mimetype')
@ -475,9 +479,9 @@ def cli_main():
def gui_main(): def gui_main():
try: try:
import tkinter import tkinter
import tkinter_constants import tkinter.constants
import tkinter_filedialog import tkinter.filedialog
import tkinter_messagebox import tkinter.messagebox
import traceback import traceback
except: except:
return cli_main() return cli_main()
@ -486,10 +490,10 @@ def gui_main():
def __init__(self, root): def __init__(self, root):
tkinter.Frame.__init__(self, root, border=5) tkinter.Frame.__init__(self, root, border=5)
self.status = tkinter.Label(self, text="Select files for decryption") self.status = tkinter.Label(self, text="Select files for decryption")
self.status.pack(fill=tkinter_constants.X, expand=1) self.status.pack(fill=tkinter.constants.X, expand=1)
body = tkinter.Frame(self) body = tkinter.Frame(self)
body.pack(fill=tkinter_constants.X, expand=1) body.pack(fill=tkinter.constants.X, expand=1)
sticky = tkinter_constants.E + tkinter_constants.W sticky = tkinter.constants.E + tkinter.constants.W
body.grid_columnconfigure(1, weight=2) body.grid_columnconfigure(1, weight=2)
tkinter.Label(body, text="Key file").grid(row=0) tkinter.Label(body, text="Key file").grid(row=0)
self.keypath = tkinter.Entry(body, width=30) self.keypath = tkinter.Entry(body, width=30)
@ -512,41 +516,41 @@ def gui_main():
buttons.pack() buttons.pack()
botton = tkinter.Button( botton = tkinter.Button(
buttons, text="Decrypt", width=10, command=self.decrypt) buttons, text="Decrypt", width=10, command=self.decrypt)
botton.pack(side=tkinter_constants.LEFT) botton.pack(side=tkinter.constants.LEFT)
tkinter.Frame(buttons, width=10).pack(side=tkinter_constants.LEFT) tkinter.Frame(buttons, width=10).pack(side=tkinter.constants.LEFT)
button = tkinter.Button( button = tkinter.Button(
buttons, text="Quit", width=10, command=self.quit) buttons, text="Quit", width=10, command=self.quit)
button.pack(side=tkinter_constants.RIGHT) button.pack(side=tkinter.constants.RIGHT)
def get_keypath(self): def get_keypath(self):
keypath = tkinter_filedialog.askopenfilename( keypath = tkinter.filedialog.askopenfilename(
parent=None, title="Select Adobe Adept \'.der\' key file", parent=None, title="Select Adobe Adept \'.der\' key file",
defaultextension=".der", defaultextension=".der",
filetypes=[('Adobe Adept DER-encoded files', '.der'), filetypes=[('Adobe Adept DER-encoded files', '.der'),
('All Files', '.*')]) ('All Files', '.*')])
if keypath: if keypath:
keypath = os.path.normpath(keypath) keypath = os.path.normpath(keypath)
self.keypath.delete(0, tkinter_constants.END) self.keypath.delete(0, tkinter.constants.END)
self.keypath.insert(0, keypath) self.keypath.insert(0, keypath)
return return
def get_inpath(self): def get_inpath(self):
inpath = tkinter_filedialog.askopenfilename( inpath = tkinter.filedialog.askopenfilename(
parent=None, title="Select ADEPT-encrypted ePub file to decrypt", parent=None, title="Select ADEPT-encrypted ePub file to decrypt",
defaultextension=".epub", filetypes=[('ePub files', '.epub')]) defaultextension=".epub", filetypes=[('ePub files', '.epub')])
if inpath: if inpath:
inpath = os.path.normpath(inpath) inpath = os.path.normpath(inpath)
self.inpath.delete(0, tkinter_constants.END) self.inpath.delete(0, tkinter.constants.END)
self.inpath.insert(0, inpath) self.inpath.insert(0, inpath)
return return
def get_outpath(self): def get_outpath(self):
outpath = tkinter_filedialog.asksaveasfilename( outpath = tkinter.filedialog.asksaveasfilename(
parent=None, title="Select unencrypted ePub file to produce", parent=None, title="Select unencrypted ePub file to produce",
defaultextension=".epub", filetypes=[('ePub files', '.epub')]) defaultextension=".epub", filetypes=[('ePub files', '.epub')])
if outpath: if outpath:
outpath = os.path.normpath(outpath) outpath = os.path.normpath(outpath)
self.outpath.delete(0, tkinter_constants.END) self.outpath.delete(0, tkinter.constants.END)
self.outpath.insert(0, outpath) self.outpath.insert(0, outpath)
return return
@ -576,13 +580,13 @@ def gui_main():
if decrypt_status == 0: if decrypt_status == 0:
self.status['text'] = "File successfully decrypted" self.status['text'] = "File successfully decrypted"
else: else:
self.status['text'] = "The was an error decrypting the file." self.status['text'] = "There was an error decrypting the file."
root = tkinter.Tk() root = tkinter.Tk()
root.title("Adobe Adept ePub Decrypter v.{0}".format(__version__)) root.title("Adobe Adept ePub Decrypter v.{0}".format(__version__))
root.resizable(True, False) root.resizable(True, False)
root.minsize(300, 0) root.minsize(300, 0)
DecryptionDialog(root).pack(fill=tkinter_constants.X, expand=1) DecryptionDialog(root).pack(fill=tkinter.constants.X, expand=1)
root.mainloop() root.mainloop()
return 0 return 0

6
DeDRM_plugin/prefs.py Normal file → Executable file
View File

@ -6,7 +6,7 @@ __license__ = 'GPL v3'
# Standard Python modules. # Standard Python modules.
import os, sys, re, hashlib import os, sys, re, hashlib
import json import codecs, json
import traceback import traceback
from calibre.utils.config import dynamic, config_dir, JSONConfig from calibre.utils.config import dynamic, config_dir, JSONConfig
@ -116,7 +116,7 @@ def convertprefs(always = False):
name, cc = keystring.split(',') name, cc = keystring.split(',')
# Generate eReader user key from name and credit card number. # Generate eReader user key from name and credit card number.
keyname = "{0}_{1}".format(name.strip(),cc.strip()[-4:]) keyname = "{0}_{1}".format(name.strip(),cc.strip()[-4:])
keyvalue = getuser_key(name,cc).encode('hex') keyvalue = codecs.encode(getuser_key(name,cc),'hex')
userkeys.append([keyname,keyvalue]) userkeys.append([keyname,keyvalue])
except Exception as e: except Exception as e:
traceback.print_exc() traceback.print_exc()
@ -146,7 +146,7 @@ def convertprefs(always = False):
key = os.path.splitext(filename)[0] key = os.path.splitext(filename)[0]
value = open(fpath, 'rb').read() value = open(fpath, 'rb').read()
if encoding is not None: if encoding is not None:
value = value.encode(encoding) value = codecs.encode(value,encoding)
userkeys.append([key,value]) userkeys.append([key,value])
except: except:
traceback.print_exc() traceback.print_exc()

4
DeDRM_plugin/zipfilerugged.py Normal file → Executable file
View File

@ -286,8 +286,8 @@ class ZipInfo (object):
# This is used to ensure paths in generated ZIP files always use # This is used to ensure paths in generated ZIP files always use
# forward slashes as the directory separator, as required by the # forward slashes as the directory separator, as required by the
# ZIP format specification. # ZIP format specification.
if os.sep != "/" and os.sep in filename: if os.sep != "/" and os.sep.encode('utf-8') in filename:
filename = filename.replace(os.sep, "/") filename = filename.replace(os.sep.encode('utf-8'), b"/")
self.filename = filename # Normalized file name self.filename = filename # Normalized file name
self.date_time = date_time # year, month, day, hour, min, sec self.date_time = date_time # year, month, day, hour, min, sec