List of changes since the fork of Apprentice Harper's repository:
+## Fixes in v10.0.0 (2021-11-17):
+
- CI testing / linting removed as that always failed anyways. The CI now "just" packages the plugin.
- Support for the Readium LCP DRM (also known as "CARE DRM" or "TEA DRM"). This supports EPUB and PDF files. It does not yet support Readium LCPDF/LPF/LCPA/LCPAU/LCPDI files, as I don't have access to any of these. If you have an LCP-protected file in one of these formats that this plugin does not work with, please open [an issue](https://github.com/noDRM/DeDRM_tools/issues) and attach the file to the report.
- Add new Github issue report form which forces the user to include stuff like their Calibre version to hopefully increase the quality of bug reports.
- Add a more verbose error message when trying to remove DRM from a book with the new, not-yet-cracked version of the Adobe ADEPT DRM.
- Added back support for Python2 (Calibre 2.0+). Only tested with ADEPT (PDF & EPUB) and Readium LCP so far, please open an issue if there's errors with other book types.
- Begin work on removing some kinds of watermarks from files after DRM removal. This isn't tested a lot, and is disabled by default. You can enable it in the plugin settings.
-- If you're using the [ACSM Input Plugin / DeACSM](https://www.mobileread.com/forums/showthread.php?t=341975), the encryption key will automatically be extracted from that plugin if necessary.
\ No newline at end of file
+- If you're using the [ACSM Input Plugin / DeACSM](https://www.mobileread.com/forums/showthread.php?t=341975), the encryption key will automatically be extracted from that plugin if necessary.
+
+## Fixes in v10.0.1 (2021-11-19):
+
+- Hotfix update to fix broken EPUB DRM removal due to a typo.
+
+## Fixes in v10.0.2 (2021-11-29):
+
+- Fix Kindle for Mac key retrieval (merged [apprenticeharper/DeDRM_tools#1936](https://github.com/apprenticeharper/DeDRM_tools/pull/1936) ), fixing #1.
+- Fix Adobe key retrieval in case the username has been changed (merged [apprenticeharper/DeDRM_tools#1946](https://github.com/apprenticeharper/DeDRM_tools/pull/1946) ). This should fix the error "failed to decrypt user key key".
+- Fix small issue with elibri watermark removal.
+- Adobe key name will now contain account email.
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
-# adobekey.pyw, version 6.0
-# Copyright © 2009-2020 i♥cabbages, Apprentice Harper et al.
+# adobekey.pyw, version 7.1
+# Copyright © 2009-2021 i♥cabbages, Apprentice Harper et al.
# Released under the terms of the GNU General Public Licence, version 3
# <http://www.gnu.org/licenses/>
# 5.9 - moved unicode_argv call inside main for Windows DeDRM compatibility
# 6.0 - Work if TkInter is missing
# 7.0 - Python 3 for calibre 5
+# 7.1 - Fix "failed to decrypt user key key" error (read username from registry)
"""
Retrieve Adobe ADEPT user key.
"""
__license__ = 'GPL v3'
-__version__ = '7.0'
+__version__ = '7.1'
import sys, os, struct, getopt
from base64 import b64decode
def __del__(self):
if self._buf is not None:
- VirtualFree(self._buf)
- self._buf = None
+ try:
+ VirtualFree(self._buf)
+ self._buf = None
+ except TypeError:
+ # Apparently this sometimes gets cleared on application exit
+ # Causes a useless exception in the log, so let's just catch and ignore that.
+ pass
if struct.calcsize("P") == 4:
CPUID0_INSNS = (
ktype = winreg.QueryValueEx(plkparent, None)[0]
if ktype != 'credentials':
continue
- uuid_name = "Unknown"
+ uuid_name = ""
for j in range(0, 16):
try:
plkkey = winreg.OpenKey(plkparent, "%04d" % (j,))
break
ktype = winreg.QueryValueEx(plkkey, None)[0]
if ktype == 'user':
- uuid_name = winreg.QueryValueEx(plkkey, 'value')[0]
- if ktype != 'privateLicenseKey':
- continue
- userkey = winreg.QueryValueEx(plkkey, 'value')[0]
- userkey = b64decode(userkey)
- aes = AES(keykey)
- userkey = aes.decrypt(userkey)
- userkey = userkey[26:-ord(userkey[-1:])]
- # print ("found " + uuid_name + " key: " + str(userkey))
- keys.append(userkey)
- names.append(uuid_name[9:])
+ # Add Adobe UUID to key name
+ uuid_name = uuid_name + winreg.QueryValueEx(plkkey, 'value')[0][9:] + "_"
+ if ktype == 'username':
+ # Add account type & email to key name, if present
+ try:
+ uuid_name = uuid_name + winreg.QueryValueEx(plkkey, 'method')[0] + "_"
+ except:
+ pass
+ try:
+ uuid_name = uuid_name + winreg.QueryValueEx(plkkey, 'value')[0] + "_"
+ except:
+ pass
+ if ktype == 'privateLicenseKey':
+ userkey = winreg.QueryValueEx(plkkey, 'value')[0]
+ userkey = b64decode(userkey)
+ aes = AES(keykey)
+ userkey = aes.decrypt(userkey)
+ userkey = userkey[26:-ord(userkey[-1:])]
+ # print ("found " + uuid_name + " key: " + str(userkey))
+ keys.append(userkey)
+
+ if uuid_name == "":
+ names.append("Unknown")
+ else:
+ names.append(uuid_name[:-1])
+
if len(keys) == 0:
raise ADEPTError('Could not locate privateLicenseKey')
print("Found {0:d} keys".format(len(keys)))
tree = etree.parse(actpath)
adept = lambda tag: '{%s}%s' % (NSMAP['adept'], tag)
expr = '//%s/%s' % (adept('credentials'), adept('privateLicenseKey'))
- exprUUID = '//%s/%s' % (adept('credentials'), adept('user'))
userkey = tree.findtext(expr)
- userUUID = "Unknown"
+
+ exprUUID = '//%s/%s' % (adept('credentials'), adept('user'))
+ keyName = ""
try:
- userUUID = tree.findtext(exprUUID)
+ keyName = tree.findtext(exprUUID)[9:] + "_"
except:
pass
+
+ try:
+ exprMail = '//%s/%s' % (adept('credentials'), adept('username'))
+ keyName = keyName + tree.find(exprMail).attrib["method"] + "_"
+ keyName = keyName + tree.findtext(exprMail) + "_"
+ except:
+ pass
+
+ if keyName == "":
+ keyName = "Unknown"
+ else:
+ keyName = keyName[:-1]
+
+
+
userkey = b64decode(userkey)
userkey = userkey[26:]
- return [userkey], [userUUID[9:]]
+ return [userkey], [keyName]
else:
def adeptkeys():