Skip to content

Commit 940d03e

Browse files
author
neocogent
committed
add partial xprv and parse wallet file support
1 parent 738974c commit 940d03e

File tree

1 file changed

+29
-17
lines changed

1 file changed

+29
-17
lines changed

scripts/pwscanx

+29-17
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
# Electrum password scanner (multi-processing)
44
#
55

6-
import sys, time, base64, hashlib, multiprocessing
6+
import sys, time, base64, hashlib, multiprocessing, json
77
from Crypto.Cipher import AES
88

99
wildchar = '?'
@@ -32,9 +32,10 @@ def test(pwd):
3232
pass
3333
else:
3434
if the_xprv[:4] == "xprv":
35-
the_xprv = AES.new(sha256(sha256(pwd)), AES.MODE_CBC, xprv[:16]).decrypt(xprv[16:]).decode("utf8")
3635
print "\nPWD:", pwd
37-
print "XPRV:", the_xprv[:-ord(the_xprv[-1])]
36+
if len(xprv) > 33:
37+
the_xprv = AES.new(sha256(sha256(pwd)), AES.MODE_CBC, xprv[:16]).decrypt(xprv[16:]).decode("utf8")
38+
print "XPRV:", the_xprv[:-ord(the_xprv[-1])]
3839
print "Took %.1f seconds" % (time.time() - started,)
3940
sys.exit(2)
4041

@@ -96,31 +97,41 @@ if __name__ == '__main__':
9697
done = False
9798

9899
if len(sys.argv) < 3:
99-
print "Electrum wallet password scanner (multiprocessing)"
100-
print "Default wild char is: %s" % wildchar
101-
print "Default charset is: %s" % pwd_chars
102-
print "Example template: myPwd%s%s123" % (wildchar,wildchar)
103-
print "\n@ template prefix means load templates (one per line) from file and scan each"
104-
print "If charset provided then first char is wild char; if - then value skipped and default is used"
105-
print "If depth is provided then templates from file are used as tokens combined to that depth"
106-
print "Tokens can contain wild chars but when combined will greatly increase search time"
107-
print "A wild char followed by ':' uses char groups, ':' ends, where:"
108-
print "\tu=upper case, l=lowercase, a=alpha (u+l), n=numeric, s=symbols"
109-
print "\teg. myPwd%s:ls:123 scans only lower case and symbols" % wildchar
110-
print "\nUsage: %s <pwd template> <xprv from wallet file> [charset] [depth]\n" % sys.argv[0]
100+
print "\nElectrum wallet password scanner (multiprocessing)\n"
101+
print " Supports only wallets created pre Electrum 2.8.0"
102+
print " As few as 44 chars from xprv allows finding pwd without exposing xprv to theft"
103+
print "\nUsage: %s <pwd template> <xprv or @wallet-file> [charset] [depth]\n" % sys.argv[0]
104+
print " Default wild char is: %s" % wildchar
105+
print " Default charset is: %s" % pwd_chars
106+
print " Example pwd template: myPwd%s%s123" % (wildchar,wildchar)
107+
print "\n @ template prefix means load templates (one per line) from file, iterates all wild chars"
108+
print " @ xprv prefix means load wallet file and parse to get xprv"
109+
110+
print " If charset provided then first char is wild char; if - then charset skipped and default is used\n"
111+
print " If depth is provided then templates from file are used as tokens combined to that depth"
112+
print " Tokens can contain wild chars but when combined will multiply search time\n"
113+
print " A wild char followed by ':' uses char groups, ':' ends, where:"
114+
print " \tu=upper case, l=lowercase, a=alpha (u+l), n=numeric, s=symbols"
115+
print " \teg. myPwd%s:ls:123 scans only lower case and symbols" % wildchar
116+
print
117+
111118
sys.exit(0)
112119

113120
if sys.argv[1][0] != '@' and sys.argv[1].count(wildchar) == 0:
114121
print "Need at least one %s in template" % wildchar
115122
sys.exit(0)
116123

124+
if sys.argv[2][0] == '@':
125+
with open(sys.argv[2][1:]) as f:
126+
xprv = base64.b64decode(json.load(f)['keystore']['xprv'])
127+
else:
128+
xprv = base64.b64decode(sys.argv[2])
129+
117130
if len(sys.argv) > 3 and sys.argv[3][0] != '-':
118131
wildchar = sys.argv[3][0]
119132
pwd_chars = sys.argv[3][1:]
120133

121134
depth = int(sys.argv[4]) if len(sys.argv) > 4 else 0
122-
123-
xprv = base64.b64decode(sys.argv[2])
124135
started = time.time()
125136

126137
if sys.argv[1][0] != '@':
@@ -142,6 +153,7 @@ if __name__ == '__main__':
142153

143154
if not done:
144155
print "Password not found"
156+
print "Took %.1f seconds" % (time.time() - started,)
145157

146158

147159

0 commit comments

Comments
 (0)