summaryrefslogtreecommitdiffstats
path: root/DeDRM_plugin/ignoblekeyWindowsStore.py
blob: 29df2045322797eddbd39c1479a4afcbeedaf51f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai

'''
Obtain the user's ccHash from the Barnes & Noble Nook Windows Store app. 
https://www.microsoft.com/en-us/p/nook-books-magazines-newspapers-comics/9wzdncrfj33h
(Requires a recent Windows version in a supported region (US).)
This procedure has been tested with Nook app version 1.11.0.4 under Windows 11.

Based on experimental standalone python script created by fesiwi at 
https://github.com/noDRM/DeDRM_tools/discussions/9
'''

import sys, os
import apsw
import base64
import traceback
try: 
    from Cryptodome.Cipher import AES
except:
    from Crypto.Cipher import AES
import hashlib
from lxml import etree

def unpad(data, padding=16):
    if sys.version_info[0] == 2:
        pad_len = ord(data[-1])
    else:
        pad_len = data[-1]

    return data[:-pad_len]


NOOK_DATA_FOLDER = "%LOCALAPPDATA%\\Packages\\BarnesNoble.Nook_ahnzqzva31enc\\LocalState"
PASS_HASH_SECRET = "9ca588496a1bc4394553d9e018d70b9e"


def dump_keys(print_result=False):
    db_filename = os.path.expandvars(NOOK_DATA_FOLDER + "\\NookDB.db3")


    if not os.path.isfile(db_filename):
        print("Database file not found. Is the Nook Windows Store app installed?")
        return []

    
    # Python2 has no fetchone() so we have to use fetchall() and discard everything but the first result.
    # There should only be one result anyways.
    serial_number = apsw.Connection(db_filename).cursor().execute(
                "SELECT value FROM bn_internal_key_value_table WHERE key = 'serialNumber';").fetchall()[0][0]


    hash_key = hashlib.sha1(bytearray.fromhex(serial_number + PASS_HASH_SECRET)).digest()[:16]

    activation_file_name = os.path.expandvars(NOOK_DATA_FOLDER + "\\settings\\activation.xml")

    if not os.path.isfile(activation_file_name):
        print("Activation file not found. Are you logged in to your Nook account?")
        return []


    activation_xml = etree.parse(activation_file_name)

    decrypted_hashes = []

    for pass_hash in activation_xml.findall(".//{http://ns.adobe.com/adept}passHash"):
        try: 
            encrypted_cc_hash = base64.b64decode(pass_hash.text)
            cc_hash = unpad(AES.new(hash_key, AES.MODE_CBC, encrypted_cc_hash[:16]).decrypt(encrypted_cc_hash[16:]), 16)
            decrypted_hashes.append((base64.b64encode(cc_hash).decode("ascii")))
            if print_result:
                print("Nook ccHash is %s" % (base64.b64encode(cc_hash).decode("ascii")))
        except: 
            traceback.print_exc()
    
    return decrypted_hashes

if __name__ == "__main__":
    dump_keys(True)