Skip to content

Commit

Permalink
Mostly Mac fixes. mobidedrm.py now works, and k4mobidedrm for at leas…
Browse files Browse the repository at this point in the history
…t some input. kindlekey.py should be working too. But lots more changes and testing to do.
  • Loading branch information
apprenticeharper committed Oct 4, 2020
1 parent 2eb31c8 commit e31752e
Show file tree
Hide file tree
Showing 17 changed files with 248 additions and 220 deletions.
60 changes: 29 additions & 31 deletions DeDRM_plugin/androidkindlekey.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,10 +95,8 @@ def unicode_argv():
# this should never happen
return ["kindlekey.py"]
else:
argvencoding = sys.stdin.encoding
if argvencoding == None:
argvencoding = "utf-8"
return argv
argvencoding = sys.stdin.encoding or "utf-8"
return [arg if isinstance(arg, str) else str(arg, argvencoding) for arg in sys.argv]

class DrmException(Exception):
pass
Expand Down Expand Up @@ -336,7 +334,7 @@ def cli_main():
sys.stderr=SafeUnbuffered(sys.stderr)
argv=unicode_argv()
progname = os.path.basename(argv[0])
print("{0} v{1}\nCopyright © 2010-2015 Thom, some_updates, Apprentice Alf and Apprentice Harper".format(progname,__version__))
print("{0} v{1}\nCopyright © 2010-2020 Thom, Apprentice Harper et al.".format(progname,__version__))

try:
opts, args = getopt.getopt(argv[1:], "hb:")
Expand Down Expand Up @@ -386,48 +384,48 @@ def cli_main():

def gui_main():
try:
import Tkinter
import Tkconstants
import tkMessageBox
import tkFileDialog
import tkinter
import tkinter.constants
import tkinter.messagebox
import tkinter.filedialog
except:
print("Tkinter not installed")
print("tkinter not installed")
return cli_main()

class DecryptionDialog(Tkinter.Frame):
class DecryptionDialog(tkinter.Frame):
def __init__(self, root):
Tkinter.Frame.__init__(self, root, border=5)
self.status = Tkinter.Label(self, text="Select backup.ab file")
self.status.pack(fill=Tkconstants.X, expand=1)
body = Tkinter.Frame(self)
body.pack(fill=Tkconstants.X, expand=1)
sticky = Tkconstants.E + Tkconstants.W
tkinter.Frame.__init__(self, root, border=5)
self.status = tkinter.Label(self, text="Select backup.ab file")
self.status.pack(fill=tkinter.constants.X, expand=1)
body = tkinter.Frame(self)
body.pack(fill=tkinter.constants.X, expand=1)
sticky = tkinter.constants.E + tkinter.constants.W
body.grid_columnconfigure(1, weight=2)
Tkinter.Label(body, text="Backup file").grid(row=0, column=0)
self.keypath = Tkinter.Entry(body, width=40)
tkinter.Label(body, text="Backup file").grid(row=0, column=0)
self.keypath = tkinter.Entry(body, width=40)
self.keypath.grid(row=0, column=1, sticky=sticky)
self.keypath.insert(2, "backup.ab")
button = Tkinter.Button(body, text="...", command=self.get_keypath)
button = tkinter.Button(body, text="...", command=self.get_keypath)
button.grid(row=0, column=2)
buttons = Tkinter.Frame(self)
buttons = tkinter.Frame(self)
buttons.pack()
button2 = Tkinter.Button(
button2 = tkinter.Button(
buttons, text="Extract", width=10, command=self.generate)
button2.pack(side=Tkconstants.LEFT)
Tkinter.Frame(buttons, width=10).pack(side=Tkconstants.LEFT)
button3 = Tkinter.Button(
button2.pack(side=tkinter.constants.LEFT)
tkinter.Frame(buttons, width=10).pack(side=tkinter.constants.LEFT)
button3 = tkinter.Button(
buttons, text="Quit", width=10, command=self.quit)
button3.pack(side=Tkconstants.RIGHT)
button3.pack(side=tkinter.constants.RIGHT)

def get_keypath(self):
keypath = tkFileDialog.askopenfilename(
keypath = tkinter.filedialog.askopenfilename(
parent=None, title="Select backup.ab file",
defaultextension=".ab",
filetypes=[('adb backup com.amazon.kindle', '.ab'),
('All Files', '.*')])
if keypath:
keypath = os.path.normpath(keypath)
self.keypath.delete(0, Tkconstants.END)
self.keypath.delete(0, tkinter.constants.END)
self.keypath.insert(0, keypath)
return

Expand All @@ -447,19 +445,19 @@ def generate(self):
with open(outfile, 'w') as keyfileout:
keyfileout.write(key)
success = True
tkMessageBox.showinfo(progname, "Key successfully retrieved to {0}".format(outfile))
tkinter.messagebox.showinfo(progname, "Key successfully retrieved to {0}".format(outfile))
except Exception as e:
self.status['text'] = "Error: {0}".format(e.args[0])
return
self.status['text'] = "Select backup.ab file"

argv=unicode_argv()
progpath, progname = os.path.split(argv[0])
root = Tkinter.Tk()
root = tkinter.Tk()
root.title("Kindle for Android Key Extraction v.{0}".format(__version__))
root.resizable(True, False)
root.minsize(300, 0)
DecryptionDialog(root).pack(fill=Tkconstants.X, expand=1)
DecryptionDialog(root).pack(fill=tkinter.constants.X, expand=1)
root.mainloop()
return 0

Expand Down
15 changes: 12 additions & 3 deletions DeDRM_plugin/convert2xml.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,25 @@
# For use with Topaz Scripts Version 2.6
# Python 3, September 2020

class Unbuffered:
# Wrap a stream so that output gets flushed immediately
# and also make sure that any unicode strings get
# encoded using "replace" before writing them.
class SafeUnbuffered:
def __init__(self, stream):
self.stream = stream
self.encoding = stream.encoding
if self.encoding == None:
self.encoding = "utf-8"
def write(self, data):
if isinstance(data, str):
data = data.encode(self.encoding,"replace")
self.stream.buffer.write(data)
self.stream.buffer.flush()

def __getattr__(self, attr):
return getattr(self.stream, attr)

import sys
sys.stdout=Unbuffered(sys.stdout)

import csv
import os
import getopt
Expand Down Expand Up @@ -834,6 +841,8 @@ def usage():
#

def main(argv):
sys.stdout=SafeUnbuffered(sys.stdout)
sys.stderr=SafeUnbuffered(sys.stderr)
dictFile = ""
pageFile = ""
debug = False
Expand Down
8 changes: 3 additions & 5 deletions DeDRM_plugin/erdr2pml.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,10 +128,8 @@ def unicode_argv():
# this should never happen
return ["mobidedrm.py"]
else:
argvencoding = sys.stdin.encoding
if argvencoding == None:
argvencoding = "utf-8"
return argv
argvencoding = sys.stdin.encoding or "utf-8"
return [arg if isinstance(arg, str) else str(arg, argvencoding) for arg in sys.argv]

Des = None
if iswindows:
Expand Down Expand Up @@ -516,7 +514,7 @@ def decryptBook(infile, outpath, make_pmlz, user_key):
# remove temporary directory
shutil.rmtree(outdir, True)
print("Output is {0}".format(pmlzname))
else:
else:
print("Output is in {0}".format(outdir))
print("done")
except ValueError as e:
Expand Down
15 changes: 12 additions & 3 deletions DeDRM_plugin/genbook.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,25 @@
# Python 3 for calibre 5.0
from __future__ import print_function

class Unbuffered:
# Wrap a stream so that output gets flushed immediately
# and also make sure that any unicode strings get
# encoded using "replace" before writing them.
class SafeUnbuffered:
def __init__(self, stream):
self.stream = stream
self.encoding = stream.encoding
if self.encoding == None:
self.encoding = "utf-8"
def write(self, data):
if isinstance(data, str):
data = data.encode(self.encoding,"replace")
self.stream.buffer.write(data)
self.stream.buffer.flush()

def __getattr__(self, attr):
return getattr(self.stream, attr)

import sys
sys.stdout=Unbuffered(sys.stdout)

import csv
import os
import getopt
Expand Down Expand Up @@ -687,6 +694,8 @@ def usage():


def main(argv):
sys.stdout=SafeUnbuffered(sys.stdout)
sys.stderr=SafeUnbuffered(sys.stderr)
bookDir = ''
if len(argv) == 0:
argv = sys.argv
Expand Down
6 changes: 2 additions & 4 deletions DeDRM_plugin/ignobleepub.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,10 +95,8 @@ def unicode_argv():
range(start, argc.value)]
return ["ineptepub.py"]
else:
argvencoding = sys.stdin.encoding
if argvencoding == None:
argvencoding = "utf-8"
return argv
argvencoding = sys.stdin.encoding or "utf-8"
return [arg if isinstance(arg, str) else str(arg, argvencoding) for arg in sys.argv]


class IGNOBLEError(Exception):
Expand Down
6 changes: 2 additions & 4 deletions DeDRM_plugin/ignoblekey.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,10 +83,8 @@ def unicode_argv():
# this should never happen
return ["ignoblekey.py"]
else:
argvencoding = sys.stdin.encoding
if argvencoding == None:
argvencoding = "utf-8"
return argv
argvencoding = sys.stdin.encoding or "utf-8"
return [arg if isinstance(arg, str) else str(arg, argvencoding) for arg in sys.argv]

class DrmException(Exception):
pass
Expand Down
22 changes: 9 additions & 13 deletions DeDRM_plugin/ignoblekeyfetch.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,10 +90,8 @@ def unicode_argv():
# this should never happen
return ["ignoblekeyfetch.py"]
else:
argvencoding = sys.stdin.encoding
if argvencoding == None:
argvencoding = "utf-8"
return argv
argvencoding = sys.stdin.encoding or "utf-8"
return [arg if isinstance(arg, str) else str(arg, argvencoding) for arg in sys.argv]


class IGNOBLEError(Exception):
Expand All @@ -109,18 +107,17 @@ def fetch_key(email, password):
import random
random = "%030x" % random.randrange(16**30)

import urllib, urllib2, re
import urllib.parse, urllib.request, re

# try the URL from nook for PC
fetch_url = "https://cart4.barnesandnoble.com/services/service.aspx?Version=2&acctPassword="
fetch_url += urllib.quote(password,'')+"&devID=PC_BN_2.5.6.9575_"+random+"&emailAddress="
fetch_url += urllib.quote(email,"")+"&outFormat=5&schema=1&service=1&stage=deviceHashB"
fetch_url += urllib.parse.quote(password,'')+"&devID=PC_BN_2.5.6.9575_"+random+"&emailAddress="
fetch_url += urllib.parse.quote(email,"")+"&outFormat=5&schema=1&service=1&stage=deviceHashB"
#print fetch_url

found = ''
try:
req = urllib2.Request(fetch_url)
response = urllib2.urlopen(req)
response = urllib.request.urlopen(fetch_url)
the_page = response.read()
#print the_page
found = re.search('ccHash>(.+?)</ccHash', the_page).group(1)
Expand All @@ -129,14 +126,13 @@ def fetch_key(email, password):
if len(found)!=28:
# try the URL from android devices
fetch_url = "https://cart4.barnesandnoble.com/services/service.aspx?Version=2&acctPassword="
fetch_url += urllib.quote(password,'')+"&devID=hobbes_9.3.50818_"+random+"&emailAddress="
fetch_url += urllib.quote(email,"")+"&outFormat=5&schema=1&service=1&stage=deviceHashB"
fetch_url += urllib.parse.quote(password,'')+"&devID=hobbes_9.3.50818_"+random+"&emailAddress="
fetch_url += urllib.parse.quote(email,"")+"&outFormat=5&schema=1&service=1&stage=deviceHashB"
#print fetch_url

found = ''
try:
req = urllib2.Request(fetch_url)
response = urllib2.urlopen(req)
response = urllib.request.urlopen(fetch_url)
the_page = response.read()
#print the_page
found = re.search('ccHash>(.+?)</ccHash', the_page).group(1)
Expand Down
24 changes: 12 additions & 12 deletions DeDRM_plugin/ignoblekeygen.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
import sys
import os
import hashlib
import base64

# Wrap a stream so that output gets flushed immediately
# and also make sure that any unicode strings get
Expand Down Expand Up @@ -99,10 +100,8 @@ def unicode_argv():
# this should never happen
return ["ignoblekeygen.py"]
else:
argvencoding = sys.stdin.encoding
if argvencoding == None:
argvencoding = "utf-8"
return argv
argvencoding = sys.stdin.encoding or "utf-8"
return [arg if isinstance(arg, str) else str(arg, argvencoding) for arg in sys.argv]


class IGNOBLEError(Exception):
Expand Down Expand Up @@ -195,23 +194,24 @@ def normalize_name(name):

def generate_key(name, ccn):
# remove spaces and case from name and CC numbers.
if type(name)==bytes:
name = normalize_name(name)
ccn = normalize_name(ccn)

if type(name)==str:
name = name.encode('utf-8')
if type(ccn)==bytes:
if type(ccn)==str:
ccn = ccn.encode('utf-8')

name = normalize_name(name) + '\x00'
ccn = normalize_name(ccn) + '\x00'
name = name + b'\x00'
ccn = ccn + b'\x00'

name_sha = hashlib.sha1(name).digest()[:16]
ccn_sha = hashlib.sha1(ccn).digest()[:16]
both_sha = hashlib.sha1(name + ccn).digest()
aes = AES(ccn_sha, name_sha)
crypt = aes.encrypt(both_sha + ('\x0c' * 0x0c))
crypt = aes.encrypt(both_sha + (b'\x0c' * 0x0c))
userkey = hashlib.sha1(crypt).digest()
return userkey.encode('base64')


return base64.b64encode(userkey)


def cli_main():
Expand Down
13 changes: 7 additions & 6 deletions DeDRM_plugin/ignoblepdf.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,10 +85,8 @@ def unicode_argv():
xrange(start, argc.value)]
return ["ignoblepdf.py"]
else:
argvencoding = sys.stdin.encoding
if argvencoding == None:
argvencoding = "utf-8"
return [arg if (type(arg) == unicode) else unicode(arg,argvencoding) for arg in sys.argv]
argvencoding = sys.stdin.encoding or "utf-8"
return [arg if isinstance(arg, str) else str(arg, argvencoding) for arg in sys.argv]


class IGNOBLEError(Exception):
Expand Down Expand Up @@ -241,7 +239,10 @@ def _load_crypto():
try:
from cStringIO import StringIO
except ImportError:
from StringIO import StringIO
try:
from StringIO import StringIO
except ImportError:
from io import StringIO


# Do we generate cross reference streams on output?
Expand Down Expand Up @@ -546,7 +547,7 @@ def parse_number(self, s, i):
except ValueError:
pass
return (self.parse_main, j)

def parse_decimal(self, s, i):
m = END_NUMBER.search(s, i)
if not m:
Expand Down
6 changes: 2 additions & 4 deletions DeDRM_plugin/ineptepub.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,10 +102,8 @@ def unicode_argv():
range(start, argc.value)]
return ["ineptepub.py"]
else:
argvencoding = sys.stdin.encoding
if argvencoding == None:
argvencoding = "utf-8"
return argv
argvencoding = sys.stdin.encoding or "utf-8"
return [arg if isinstance(arg, str) else str(arg, argvencoding) for arg in sys.argv]


class ADEPTError(Exception):
Expand Down
Loading

0 comments on commit e31752e

Please sign in to comment.