Menu
Mark o%27meara witb. # 5.0 - Extraction of info from Kindle for PC/Mac moved into kindlekey.py # - tweaked GetDecryptedBook interface to leave passed parameters unchanged # 5.1 - moved unicodeargv call inside main for Windows DeDRM compatibility.
- DRM removal must be accomplished using a separate calibre plugin. (See the Installation instructions below.) DRM removal for KFX format only works with books downloaded using old versions of the Kindle for PC/Mac apps (versions 1.19 through 1.26) and e-ink Kindle device firmware (versions 5.6.5 through 5.12.1).
- Want to drop Amazon's DRM from a Kindle eBook you've purchased? As the saying goes, where there's a will, there's a way. And, in this case, there are actually a couple of ways: One method uses Calibre and works for both Windows and Mac users, the other uses an AppleScript and is Mac exclusive. To maximize the usefulness of this guide, we've chosen to excerpt a tutorial that uses the OS.
Version 6.8.0 of the tools is now available. Please update to the latest version if you are having issues. To leave a comment, see the previous post: DRM Removal Tools for eBooks.
DeDRM_tools_6.8.0.zip can be downloaded from
https://github.com/apprenticeharper/DeDRM_tools/releases/tag/v6.8.0
https://github.com/apprenticeharper/DeDRM_tools/releases/tag/v6.8.0
Release Notes
This release adds full support for the new .kinf2018 key files and the new KFX encryption. Many thanks to Apprentice Sakuya for their work on this.
This means that this release now works with the latest (1.28) version of Kindle for PC and Kindle for Mac.
***Update: Amazon has made changes to the KFX encryption since this release which affect Kindle for PC/Mac versions 1.27 and later. This release should work on all books downloaded with Kindle for PC/Mac version 1.26 or earlier. Ni license activator 1.1 file download. Books which require the later versions of Kindle for PC/Mac will not be able to be decrypted at this time.***
A script to remove DRM from B&N PDFs has been included but not integrated into the plugin, nor tested. The testament of sherlock holmes keygen crack serial number.
This release DOES NOT work with the latest calibre beta that requires Python 3 for plugins.
Decrypting KFX
Thanks to work by several people, the DeDRM calibre plugin can decrypt KFX format ebooks from Amazon as long as they are downloaded with Kindle for Mac/PC prior to version 1.27. https://hereafil123.weebly.com/mod-manager-for-mac.html.
Install the KFX Input plugin to automatically locate all of the files that make up a KFX format book and gather them into a KFX-ZIP. After the DeDRM plugin removes the DRM, then the KFX Input plugin will package it into a single KFX file.
Anbe en anbe un vizhi mp3 song free download. See this post at the MobileRead calibre forum for more information on dealing with the KFX format.
Nov 8th, 2014
Never
Not a member of Pastebin yet?Sign Up, it unlocks many cool features!
- +++ __init__.py Sat Nov 08 00:59:56 2014
- pids = dedrmprefs['pids']
- kindleDatabases = dedrmprefs['kindlekeys'].items()
- - book = k4mobidedrm.GetDecryptedBook(path_to_ebook,kindleDatabases,serials,pids,self.starttime)
- + book = k4mobidedrm.GetDecryptedBook(path_to_ebook,kindleDatabases,serials,fireKeys,pids,self.starttime)
- decoded = False
- # perhaps we need to get a new default Kindle for Mac/PC key
- if len(newkeys) > 0:
- print u'{0} v{1}: Found {2} new {3}'.format(PLUGIN_NAME, PLUGIN_VERSION, len(newkeys), u'key' if len(newkeys)1 else u'keys')
- - book = k4mobidedrm.GetDecryptedBook(path_to_ebook,newkeys.items(),[],[],self.starttime)
- + book = k4mobidedrm.GetDecryptedBook(path_to_ebook,newkeys.items(),[],[],[],self.starttime)
- # store the new successful keys in the defaults
- print u'{0} v{1}: Saving {2} new {3}'.format(PLUGIN_NAME, PLUGIN_VERSION, len(newkeys), u'key' if len(newkeys)1 else u'keys')
- +++ config.py Sat Nov 08 00:59:56 2014
- self.tempdedrmprefs['adeptkeys'] = self.dedrmprefs['adeptkeys'].copy()
- self.tempdedrmprefs['ereaderkeys'] = self.dedrmprefs['ereaderkeys'].copy()
- self.tempdedrmprefs['kindlekeys'] = self.dedrmprefs['kindlekeys'].copy()
- + self.tempdedrmprefs['firekeys'] = self.dedrmprefs['firekeys'].copy()
- self.tempdedrmprefs['pids'] = list(self.dedrmprefs['pids'])
- self.tempdedrmprefs['serials'] = list(self.dedrmprefs['serials'])
- self.tempdedrmprefs['adobewineprefix'] = self.dedrmprefs['adobewineprefix']
- self.tempdedrmprefs['kindlewineprefix'] = self.dedrmprefs['kindlewineprefix']
- + self.tempdedrmprefs['firewineprefix'] = self.dedrmprefs['firewineprefix']
- # Start Qt Gui dialog layout
- @@ -91,6 +93,10 @@
- self.kindle_key_button.setToolTip(_(u'Click to manage keys for Kindle for Mac/PC ebooks'))
- self.kindle_key_button.setText(u'Kindle for Mac/PC ebooks')
- self.kindle_key_button.clicked.connect(self.kindle_keys)
- + self.fire_key_button.setToolTip(_(u'Click to manage keys for Kindle Fire ebooks'))
- + self.fire_key_button.setText(u'Kindle Fire ebooks')
- + self.fire_key_button.clicked.connect(self.fire_keys)
- self.adept_button.setToolTip(_(u'Click to manage keys for Adobe Digital Editions ebooks'))
- self.adept_button.setText(u'Adobe Digital Editions ebooks')
- button_layout.addWidget(self.ereader_button)
- button_layout.addWidget(self.kindle_key_button)
- d = ManageKeysDialog(self,u'EInk Kindle Serial Number',self.tempdedrmprefs['serials'], AddSerialDialog)
- + if isosx or iswindows:
- + d = ManageKeysDialog(self,u'Kindle Fire Key',self.tempdedrmprefs['firekeys'], AddFireDialog, 'fire')
- + # linux
- + d = ManageKeysDialog(self,u'Kindle Fire Key',self.tempdedrmprefs['firekeys'], AddFireDialog, 'fire', self.tempdedrmprefs['firewineprefix'])
- + self.tempdedrmprefs['firewineprefix'] = d.getwineprefix()
- def kindle_keys(self):
- d = ManageKeysDialog(self,u'Kindle for Mac and PC Key',self.tempdedrmprefs['kindlekeys'], AddKindleDialog, 'k4i')
- self.dedrmprefs.set('adeptkeys', self.tempdedrmprefs['adeptkeys'])
- self.dedrmprefs.set('ereaderkeys', self.tempdedrmprefs['ereaderkeys'])
- self.dedrmprefs.set('kindlekeys', self.tempdedrmprefs['kindlekeys'])
- + self.dedrmprefs.set('firekeys', self.tempdedrmprefs['firekeys'])
- self.dedrmprefs.set('pids', self.tempdedrmprefs['pids'])
- self.dedrmprefs.set('serials', self.tempdedrmprefs['serials'])
- self.dedrmprefs.set('adobewineprefix', self.tempdedrmprefs['adobewineprefix'])
- self.dedrmprefs.set('kindlewineprefix', self.tempdedrmprefs['kindlewineprefix'])
- + self.dedrmprefs.set('firewineprefix', self.tempdedrmprefs['firewineprefix'])
- self.dedrmprefs.writeprefs()
- @@ -812,6 +830,68 @@
- errmsg = u'Key name must be at <i>least</i> 4 characters long!'
- return error_dialog(None, '{0}{1}'.format(PLUGIN_NAME, PLUGIN_VERSION), errmsg, show=True, show_copy_button=False)
- +
- +class AddFireDialog(QDialog):
- + QDialog.__init__(self, parent)
- + self.setWindowTitle(u'{0}{1}: Add New Kindle Fire Keys'.format(PLUGIN_NAME, PLUGIN_VERSION))
- + self.setLayout(layout)
- + data_group_box = QGroupBox(u', self)
- + data_group_box_layout = QVBoxLayout()
- +
- + data_group_box_layout.addLayout(key_group)
- + key_group.addWidget(QLabel(u'Kindle Fire Serial Number:', self))
- + self.key_ledit.setToolTip(u'Enter a Kindle Fire serial number.')
- +
- + value_group = QHBoxLayout()
- + value_group.addWidget(QLabel(u'Account Secrets:', self))
- + self.value_ledit.setToolTip(u'Enter Account Secrets.')
- +
- + key_label.setAlignment(Qt.AlignHCenter)
- +
- + self.button_box = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
- + self.button_box.rejected.connect(self.reject)
- +
- +
- + def key_name(self):
- +
- + def key_value(self):
- + value['deviceserialnumber'] = unicode(self.key_ledit.text()).strip()
- + value['account_secrets'] = unicode(self.value_ledit.text()).strip()
- +
- + if len(self.key_name) 0 or self.key_name.isspace():
- + return error_dialog(None, '{0}{1}'.format(PLUGIN_NAME, PLUGIN_VERSION), errmsg, show=True, show_copy_button=False)
- + for i in value:
- + errmsg = u'All fields are required!'
- + return error_dialog(None, '{0}{1}'.format(PLUGIN_NAME, PLUGIN_VERSION), errmsg, show=True, show_copy_button=False)
- --- k4mobidedrm.py Wed Oct 02 03:41:10 2013
- @@ -187,7 +187,7 @@
- return re.sub(u'&#?w+;', fixup, text)
- -def GetDecryptedBook(infile, kDatabases, serials, pids, starttime = time.time()):
- +def GetDecryptedBook(infile, kDatabases, serials, fireKeys, pids, starttime = time.time()):
- if not os.path.isfile(infile):
- raise DrmException(u'Input file does not exist.')
- totalpids = list(pids)
- md1, md2 = mb.getPIDMetaInfo()
- - totalpids.extend(kgenpids.getPidList(md1, md2, serials, kDatabases))
- + totalpids.extend(kgenpids.getPidList(md1, md2, serials, kDatabases, fireKeys))
- print u'Found {1:d} keys to try after {0:.1f} seconds'.format(time.time()-starttime, len(totalpids))
- try:
- # kDatabaseFiles is a list of files created by kindlekey
- -def decryptBook(infile, outdir, kDatabaseFiles, serials, pids):
- +def decryptBook(infile, outdir, kDatabaseFiles, serials, fireKeys, pids):
- kDatabases = []
- @@ -239,7 +239,7 @@
- - book = GetDecryptedBook(infile, kDatabases, serials, pids, starttime)
- + book = GetDecryptedBook(infile, kDatabases, serials, fireKeys, pids, starttime)
- print u'Error decrypting book after {1:.1f} seconds: {0}'.format(e.args[0],time.time()-starttime)
- @@ -298,6 +298,7 @@
- outdir = args[1]
- + fireKeys = []
- pids = []
- @@ -306,6 +307,14 @@
- raise DrmException('Invalid parameter for -k')
- + if o '-f':
- + raise DrmException('Invalid parameter for -f')
- + fireKey = {}
- + fireKey['account_secrets'] = param[1]
- if o '-p':
- raise DrmException('Invalid parameter for -p')
- # try with built in Kindle Info files if not on Linux
- - return decryptBook(infile, outdir, kDatabaseFiles, serials, pids)
- + return decryptBook(infile, outdir, kDatabaseFiles, serials, fireKeys, pids)
- --- kgenpids.py Sun Apr 21 07:18:02 2013
- @@ -35,6 +35,11 @@
- return ctx.digest()
- +def SHA256Hex(message):
- + ctx.update(message)
- +
- # Encode the bytes in data with the characters in map
- @@ -159,6 +164,55 @@
- +# Parse the EXTH header records and use the Kindle Fire serial number and account secrets to calculate the book pid.
- + pids=[]
- + # Pulled from KindleForOtter.apk
- + CUSTOM_PID_FOR_BUNDLED_DICTIONARY_DRM = '-3891337692'
- + try:
- + # Get the device serial number
- + serial = (fireKeys[1])['deviceserialnumber'].encode('ascii')
- + # Get the account secrets
- + secrets = (fireKeys[1])['account_secrets'].encode('ascii')
- + # Split account secrets if there are more than one
- +
- + print u'Keys not found in the database {0}.'.format(kindleDatabase[0])
- +
- + pidHash = SHA256Hex(serial)
- +
- + for i in xrange(len(secrets)):
- + bookPID = encodePID(pidHash)
- +
- + pidHash = SHA1(serial+secrets[i]+rec209+token)
- + pids.append(bookPID)
- + # variant 2
- + pidHash = SHA1(secrets[i]+rec209+token)
- + pids.append(bookPID)
- + # Get bundled PID
- + pids.append(CUSTOM_PID_FOR_BUNDLED_DICTIONARY_DRM)
- + return pids
- +
- # Parse the EXTH header records and use the Kindle serial number to calculate the book pid.
- pids=[]
- -def getPidList(md1, md2, serials=[], kDatabases=[]):
- +def getPidList(md1, md2, serials=[], kDatabases=[], fireKeys=[]):
- kDatabases = []
- serials = []
- + fireKeys = []
- for kDatabase in kDatabases:
- @@ -262,6 +318,13 @@
- pidlst.extend(getKindlePids(md1, md2, serialnum))
- print u'Error getting PIDs from serial number {0}: {1}'.format(serialnum ,e.args[0])
- +
- + try:
- + except Exception, e:
- + print u'Error getting PIDs from Kindle Fire Key {0}: {1}'.format(kDatabase[0],e.args[0])
- --- prefs.py Mon Apr 22 02:44:05 2013
- @@ -23,10 +23,12 @@
- self.dedrmprefs.defaults['ereaderkeys'] = {}
- + self.dedrmprefs.defaults['firekeys'] = {}
- self.dedrmprefs.defaults['serials'] = []
- self.dedrmprefs.defaults['kindlewineprefix'] = '
- # we must actually set the prefs that are dictionaries and lists
- self.dedrmprefs['ereaderkeys'] = {}
- self.dedrmprefs['kindlekeys'] = {}
- + self.dedrmprefs['firekeys'] = {}
- self.dedrmprefs['pids'] = []
- @@ -282,6 +286,7 @@
- if 'wineprefix' in kindleprefs and kindleprefs['wineprefix'] != ':
- dedrmprefs.set('adobewineprefix',kindleprefs['wineprefix'])
- dedrmprefs.set('kindlewineprefix',kindleprefs['wineprefix'])
- + dedrmprefs.set('firewineprefix',kindleprefs['wineprefix'])
- print u'{0} v{1}: WINEPREFIX ‘(2)’ imported from Kindle plugin preferences'.format(PLUGIN_NAME, PLUGIN_VERSION, kindleprefs['wineprefix'])
- traceback.print_exc()