Skip to content

Commit 6b3117f

Browse files
committed
Upload necessary files to verify build
1 parent 897832a commit 6b3117f

File tree

3 files changed

+332
-0
lines changed

3 files changed

+332
-0
lines changed

arms.py

Lines changed: 321 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,321 @@
1+
try:
2+
import os
3+
import hashlib
4+
import hmac
5+
import binascii
6+
import unicodedata
7+
import ctypes
8+
ctypes.windll.kernel32.SetConsoleTitleA("Check MPK Against Armory Seed to Recover BTC")
9+
10+
os.system("mode con: cols=100 lines=35")
11+
12+
__all__ = ['new', 'digest_size']
13+
14+
__revision__ = "$Id$"
15+
16+
import struct
17+
18+
def u32(n):
19+
return n & 0xFFFFffffL
20+
21+
rho = [7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8]
22+
23+
pi = [(9*i + 5) & 15 for i in range(16)]
24+
25+
rl = [range(16)]
26+
rl += [[rho[j] for j in rl[-1]]]
27+
rl += [[rho[j] for j in rl[-1]]]
28+
rl += [[rho[j] for j in rl[-1]]]
29+
rl += [[rho[j] for j in rl[-1]]]
30+
31+
rr = [list(pi)]
32+
rr += [[rho[j] for j in rr[-1]]]
33+
rr += [[rho[j] for j in rr[-1]]]
34+
rr += [[rho[j] for j in rr[-1]]]
35+
rr += [[rho[j] for j in rr[-1]]]
36+
37+
f1 = lambda x, y, z: x ^ y ^ z
38+
39+
f2 = lambda x, y, z: (x & y) | (~x & z)
40+
41+
f3 = lambda x, y, z: (x | ~y) ^ z
42+
43+
f4 = lambda x, y, z: (x & z) | (y & ~z)
44+
45+
f5 = lambda x, y, z: x ^ (y | ~z)
46+
47+
fl = [f1, f2, f3, f4, f5]
48+
49+
fr = [f5, f4, f3, f2, f1]
50+
51+
_shift1 = [11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8]
52+
_shift2 = [12, 13, 11, 15, 6, 9, 9, 7, 12, 15, 11, 13, 7, 8, 7, 7]
53+
_shift3 = [13, 15, 14, 11, 7, 7, 6, 8, 13, 14, 13, 12, 5, 5, 6, 9]
54+
_shift4 = [14, 11, 12, 14, 8, 6, 5, 5, 15, 12, 15, 14, 9, 9, 8, 6]
55+
_shift5 = [15, 12, 13, 13, 9, 5, 8, 6, 14, 11, 12, 11, 8, 6, 5, 5]
56+
57+
sl = [[_shift1[rl[0][i]] for i in range(16)]]
58+
sl.append([_shift2[rl[1][i]] for i in range(16)])
59+
sl.append([_shift3[rl[2][i]] for i in range(16)])
60+
sl.append([_shift4[rl[3][i]] for i in range(16)])
61+
sl.append([_shift5[rl[4][i]] for i in range(16)])
62+
63+
sr = [[_shift1[rr[0][i]] for i in range(16)]]
64+
sr.append([_shift2[rr[1][i]] for i in range(16)])
65+
sr.append([_shift3[rr[2][i]] for i in range(16)])
66+
sr.append([_shift4[rr[3][i]] for i in range(16)])
67+
sr.append([_shift5[rr[4][i]] for i in range(16)])
68+
69+
_kg = lambda x, y: int(2**30 * (y ** (1.0 / x)))
70+
71+
KL = [
72+
0,
73+
_kg(2, 2),
74+
_kg(2, 3),
75+
_kg(2, 5),
76+
_kg(2, 7),
77+
]
78+
79+
KR = [
80+
_kg(3, 2),
81+
_kg(3, 3),
82+
_kg(3, 5),
83+
_kg(3, 7),
84+
0,
85+
]
86+
87+
def rol(s, n):
88+
assert 0 <= s <= 31
89+
assert 0 <= n <= 0xFFFFffffL
90+
return u32((n << s) | (n >> (32-s)))
91+
92+
initial_h = tuple(struct.unpack("<5L", "0123456789ABCDEFFEDCBA9876543210F0E1D2C3".decode('hex')))
93+
94+
def box(h, f, k, x, r, s):
95+
assert len(s) == 16
96+
assert len(x) == 16
97+
assert len(r) == 16
98+
(a, b, c, d, e) = h
99+
for word in range(16):
100+
T = u32(a + f(b, c, d) + x[r[word]] + k)
101+
T = u32(rol(s[word], T) + e)
102+
(b, c, d, e, a) = (T, b, rol(10, c), d, e)
103+
return (a, b, c, d, e)
104+
105+
def _compress(h, x):
106+
hl = hr = h
107+
108+
for round in range(5):
109+
hl = box(hl, fl[round], KL[round], x, rl[round], sl[round])
110+
hr = box(hr, fr[round], KR[round], x, rr[round], sr[round])
111+
112+
h = (u32(h[1] + hl[2] + hr[3]),
113+
u32(h[2] + hl[3] + hr[4]),
114+
u32(h[3] + hl[4] + hr[0]),
115+
u32(h[4] + hl[0] + hr[1]),
116+
u32(h[0] + hl[1] + hr[2]))
117+
118+
return h
119+
120+
def compress(h, s):
121+
assert len(s) % 64 == 0
122+
p = 0
123+
while p < len(s):
124+
h = _compress(h, struct.unpack("<16L", s[p:p+64]))
125+
p += 64
126+
assert p == len(s)
127+
return h
128+
129+
class RIPEMD160(object):
130+
131+
digest_size = 20
132+
133+
def __init__(self, data=""):
134+
self.h = initial_h
135+
self.bytes = 0
136+
self.buf = ""
137+
self.update(data)
138+
139+
def update(self, data):
140+
self.buf += data
141+
self.bytes += len(data)
142+
143+
p = len(self.buf) & ~63
144+
if p > 0:
145+
self.h = compress(self.h, self.buf[:p])
146+
self.buf = self.buf[p:]
147+
assert len(self.buf) < 64
148+
149+
def digest(self):
150+
151+
length = (self.bytes << 3) & (2**64-1)
152+
153+
assert len(self.buf) < 64
154+
data = self.buf + "\x80"
155+
if len(data) <= 56:
156+
assert len(data) <= 56
157+
data = struct.pack("<56sQ", data, length)
158+
else:
159+
assert len(data) <= 120
160+
data = struct.pack("<120sQ", data, length)
161+
162+
h = compress(self.h, data)
163+
return struct.pack("<5L", *h)
164+
165+
def hexdigest(self):
166+
return self.digest().encode('hex')
167+
168+
def copy(self):
169+
obj = self.__class__()
170+
obj.h = self.h
171+
obj.bytes = self.bytes
172+
obj.buf = self.buf
173+
return obj
174+
175+
def ripenew(data=""):
176+
return RIPEMD160(data)
177+
178+
digest_size = 20
179+
180+
Pcurve = 2**256 - 2**32 - 2**9 - 2**8 - 2**7 - 2**6 - 2**4 -1
181+
N=0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141
182+
Acurve = 0; Bcurve = 7
183+
Gx = 55066263022277343669578718895168534326250603453777594175500187360389116729240
184+
Gy = 32670510020758816978083085130507043184471273380659243275938904335757337482424
185+
GPoint = (Gx,Gy)
186+
187+
def modinv(a,n=Pcurve):
188+
lm, hm = 1,0
189+
low, high = a%n,n
190+
while low > 1:
191+
ratio = high/low
192+
nm, new = hm-lm*ratio, high-low*ratio
193+
lm, low, hm, high = nm, new, lm, low
194+
return lm % n
195+
196+
def ECadd(a,b):
197+
LamAdd = ((b[1]-a[1]) * modinv(b[0]-a[0],Pcurve)) % Pcurve
198+
x = (LamAdd*LamAdd-a[0]-b[0]) % Pcurve
199+
y = (LamAdd*(a[0]-x)-a[1]) % Pcurve
200+
return (x,y)
201+
202+
def ECdouble(a):
203+
Lam = ((3*a[0]*a[0]+Acurve) * modinv((2*a[1]),Pcurve)) % Pcurve
204+
x = (Lam*Lam-2*a[0]) % Pcurve
205+
y = (Lam*(a[0]-x)-a[1]) % Pcurve
206+
return (x,y)
207+
208+
def EccMultiply(GenPoint,ScalarHex):
209+
if ScalarHex == 0 or ScalarHex >= N: raise Exception("Invalid Scalar/Private Key")
210+
ScalarBin = str(bin(ScalarHex))[2:]
211+
Q=GenPoint
212+
for i in range (1, len(ScalarBin)):
213+
Q=ECdouble(Q);
214+
if ScalarBin[i] == "1":
215+
Q=ECadd(Q,GenPoint);
216+
return (Q)
217+
218+
__b58chars = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'
219+
__b58base = len(__b58chars)
220+
221+
def b58encode(v):
222+
223+
long_value = 0L
224+
for (i, c) in enumerate(v[::-1]):
225+
long_value += (256**i) * ord(c)
226+
227+
result = ''
228+
while long_value >= __b58base:
229+
div, mod = divmod(long_value, __b58base)
230+
result = __b58chars[mod] + result
231+
long_value = div
232+
result = __b58chars[long_value] + result
233+
234+
nPad = 0
235+
for c in v:
236+
if c == '\0': nPad += 1
237+
else: break
238+
239+
return (__b58chars[0]*nPad) + result
240+
241+
HEXCODE = '0123 4567 89ab cdef'.replace(' ','')
242+
LETCODE = 'asdf ghjk wert uion'.replace(' ','')
243+
244+
def seed_to_bin(seed):
245+
lines = seed.replace(' ', '').split('<>')
246+
newlines = []
247+
new = ''
248+
for i in range(2):
249+
for j in range(len(lines[i])):
250+
new += HEXCODE[LETCODE.find(lines[i][j])]
251+
newlines.append(new)
252+
new = ''
253+
newseed = newlines[0][:32] + newlines[1][:32]
254+
chk1 = hashlib.sha256(hashlib.sha256(newlines[0][:32].decode('hex')).digest()).hexdigest()[:4]
255+
chk2 = hashlib.sha256(hashlib.sha256(newlines[1][:32].decode('hex')).digest()).hexdigest()[:4]
256+
assert chk1 == newlines[0][32:], "Invalid Checksum: Check to make sure you typed your Backup in right."
257+
assert chk2 == newlines[1][32:], "Invalid Checksum: Check to make sure you typed your Backup in right."
258+
return newseed
259+
260+
261+
def gen_addy_priv(MPK, secret, n, c=0):
262+
index = int(hashlib.sha256(hashlib.sha256("%d:%d:"%(n,c) + MPK.decode('hex')).digest()).hexdigest(),16)
263+
addy_pt = ECadd(EccMultiply(GPoint,index),(int(MPK[:64],16),int(MPK[64:],16)))
264+
privsec = (secret + index) % N
265+
assert EccMultiply(GPoint,privsec) == addy_pt, "Private Key and Generated Public Key don't match!"
266+
h160 = ripenew(hashlib.sha256(("04" + ("%064x" % addy_pt[0]) + ("%064x" % addy_pt[1])).decode('hex')).digest()).digest()
267+
h160chk = hashlib.sha256(hashlib.sha256(chr(0) + h160).digest()).digest()[:4]
268+
addy = b58encode(chr(0) + h160 + h160chk)
269+
270+
privchk = hashlib.sha256(hashlib.sha256(chr(128) + ("%064x" % privsec).decode('hex')).digest()).digest()[:4]
271+
wifpriv = b58encode(chr(128) + ("%064x" % privsec).decode('hex') + privchk)
272+
273+
return addy, wifpriv
274+
275+
276+
##############################################################################################
277+
#
278+
print "Please type in your \"Paper Backup Phrase\" from Armory."
279+
print "Type in the first line, then the second line. It will ask for each line separately."
280+
print
281+
print "Also, for the second input, please paste in the \"Master Public Key\" from Electrum."
282+
print "We must check and make sure Electrum has the correct MPK that matches your Backup Phrase"
283+
print "from Armory, so open the watch-only wallet in Electrum, and \"Wallet\" > \"Master Public Key\""
284+
print "and paste that long number into the MPK input line."
285+
print
286+
print "Windows command window can only paste by right clicking the bar at the top, clicking \"Edit\","
287+
print "then clicking paste."
288+
print
289+
#
290+
bckup = raw_input("Armory Backup Phrase? (1st Line) ")
291+
bckup2 = raw_input("Armory Backup Phrase? (2nd Line) ")
292+
bckup = bckup + " <> " + bckup2
293+
print
294+
#'aagh hjfj sihk ietj giik wwai awtd uodh hnji <> soss uaku egod utai itos fijj ihgi jhau jtoo'
295+
#'aaghhjfjsihkietjgiikwwaiawtduodhhnji <> sossuakuegodutaiitosfijjihgijhaujtoo'
296+
#
297+
chkMPK = raw_input("Electrum MPK? ")
298+
#'5a09a3286873a72f164476bde9d1d8e5c2bc044e35aa47eb6e798e325a86417f7c35b61d9905053533e0b4f2a26eca0330aadf21c638969e45aaace50e4c0c87'
299+
#
300+
##############################################################################################
301+
302+
303+
secpriv = int(seed_to_bin(bckup),16)
304+
pt = EccMultiply(GPoint,secpriv)
305+
MPK = ("%064x" % pt[0]) + ("%064x" % pt[1])
306+
assert MPK == chkMPK, "Your MPK and the backup phrase MPK don't match."
307+
308+
print
309+
print "Receive Address + Private Key"
310+
for i in range(5):
311+
addy, wifpriv = gen_addy_priv(MPK, secpriv, i)
312+
print addy, wifpriv
313+
print
314+
print "Change Address + Private Key"
315+
for i in range(3):
316+
addy, wifpriv = gen_addy_priv(MPK, secpriv, i, 1)
317+
print addy, wifpriv
318+
raw_input()
319+
except Exception,e:
320+
print "ERROR: " + str(e)
321+
raw_input()

electrum.ico

283 KB
Binary file not shown.

setup.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
from distutils.core import setup
2+
import py2exe, sys, os
3+
4+
sys.argv.append('py2exe')
5+
6+
setup(
7+
options = {'py2exe': {'bundle_files': 1, 'compressed': True}},
8+
console = [{'script': "arms.py",
9+
'icon_resources':[(1,'electrum.ico')]}],
10+
zipfile = None,
11+
)

0 commit comments

Comments
 (0)