-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Upload necessary files to verify build
- Loading branch information
Showing
3 changed files
with
332 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,321 @@ | ||
try: | ||
import os | ||
import hashlib | ||
import hmac | ||
import binascii | ||
import unicodedata | ||
import ctypes | ||
ctypes.windll.kernel32.SetConsoleTitleA("Check MPK Against Armory Seed to Recover BTC") | ||
|
||
os.system("mode con: cols=100 lines=35") | ||
|
||
__all__ = ['new', 'digest_size'] | ||
|
||
__revision__ = "$Id$" | ||
|
||
import struct | ||
|
||
def u32(n): | ||
return n & 0xFFFFffffL | ||
|
||
rho = [7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8] | ||
|
||
pi = [(9*i + 5) & 15 for i in range(16)] | ||
|
||
rl = [range(16)] | ||
rl += [[rho[j] for j in rl[-1]]] | ||
rl += [[rho[j] for j in rl[-1]]] | ||
rl += [[rho[j] for j in rl[-1]]] | ||
rl += [[rho[j] for j in rl[-1]]] | ||
|
||
rr = [list(pi)] | ||
rr += [[rho[j] for j in rr[-1]]] | ||
rr += [[rho[j] for j in rr[-1]]] | ||
rr += [[rho[j] for j in rr[-1]]] | ||
rr += [[rho[j] for j in rr[-1]]] | ||
|
||
f1 = lambda x, y, z: x ^ y ^ z | ||
|
||
f2 = lambda x, y, z: (x & y) | (~x & z) | ||
|
||
f3 = lambda x, y, z: (x | ~y) ^ z | ||
|
||
f4 = lambda x, y, z: (x & z) | (y & ~z) | ||
|
||
f5 = lambda x, y, z: x ^ (y | ~z) | ||
|
||
fl = [f1, f2, f3, f4, f5] | ||
|
||
fr = [f5, f4, f3, f2, f1] | ||
|
||
_shift1 = [11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8] | ||
_shift2 = [12, 13, 11, 15, 6, 9, 9, 7, 12, 15, 11, 13, 7, 8, 7, 7] | ||
_shift3 = [13, 15, 14, 11, 7, 7, 6, 8, 13, 14, 13, 12, 5, 5, 6, 9] | ||
_shift4 = [14, 11, 12, 14, 8, 6, 5, 5, 15, 12, 15, 14, 9, 9, 8, 6] | ||
_shift5 = [15, 12, 13, 13, 9, 5, 8, 6, 14, 11, 12, 11, 8, 6, 5, 5] | ||
|
||
sl = [[_shift1[rl[0][i]] for i in range(16)]] | ||
sl.append([_shift2[rl[1][i]] for i in range(16)]) | ||
sl.append([_shift3[rl[2][i]] for i in range(16)]) | ||
sl.append([_shift4[rl[3][i]] for i in range(16)]) | ||
sl.append([_shift5[rl[4][i]] for i in range(16)]) | ||
|
||
sr = [[_shift1[rr[0][i]] for i in range(16)]] | ||
sr.append([_shift2[rr[1][i]] for i in range(16)]) | ||
sr.append([_shift3[rr[2][i]] for i in range(16)]) | ||
sr.append([_shift4[rr[3][i]] for i in range(16)]) | ||
sr.append([_shift5[rr[4][i]] for i in range(16)]) | ||
|
||
_kg = lambda x, y: int(2**30 * (y ** (1.0 / x))) | ||
|
||
KL = [ | ||
0, | ||
_kg(2, 2), | ||
_kg(2, 3), | ||
_kg(2, 5), | ||
_kg(2, 7), | ||
] | ||
|
||
KR = [ | ||
_kg(3, 2), | ||
_kg(3, 3), | ||
_kg(3, 5), | ||
_kg(3, 7), | ||
0, | ||
] | ||
|
||
def rol(s, n): | ||
assert 0 <= s <= 31 | ||
assert 0 <= n <= 0xFFFFffffL | ||
return u32((n << s) | (n >> (32-s))) | ||
|
||
initial_h = tuple(struct.unpack("<5L", "0123456789ABCDEFFEDCBA9876543210F0E1D2C3".decode('hex'))) | ||
|
||
def box(h, f, k, x, r, s): | ||
assert len(s) == 16 | ||
assert len(x) == 16 | ||
assert len(r) == 16 | ||
(a, b, c, d, e) = h | ||
for word in range(16): | ||
T = u32(a + f(b, c, d) + x[r[word]] + k) | ||
T = u32(rol(s[word], T) + e) | ||
(b, c, d, e, a) = (T, b, rol(10, c), d, e) | ||
return (a, b, c, d, e) | ||
|
||
def _compress(h, x): | ||
hl = hr = h | ||
|
||
for round in range(5): | ||
hl = box(hl, fl[round], KL[round], x, rl[round], sl[round]) | ||
hr = box(hr, fr[round], KR[round], x, rr[round], sr[round]) | ||
|
||
h = (u32(h[1] + hl[2] + hr[3]), | ||
u32(h[2] + hl[3] + hr[4]), | ||
u32(h[3] + hl[4] + hr[0]), | ||
u32(h[4] + hl[0] + hr[1]), | ||
u32(h[0] + hl[1] + hr[2])) | ||
|
||
return h | ||
|
||
def compress(h, s): | ||
assert len(s) % 64 == 0 | ||
p = 0 | ||
while p < len(s): | ||
h = _compress(h, struct.unpack("<16L", s[p:p+64])) | ||
p += 64 | ||
assert p == len(s) | ||
return h | ||
|
||
class RIPEMD160(object): | ||
|
||
digest_size = 20 | ||
|
||
def __init__(self, data=""): | ||
self.h = initial_h | ||
self.bytes = 0 | ||
self.buf = "" | ||
self.update(data) | ||
|
||
def update(self, data): | ||
self.buf += data | ||
self.bytes += len(data) | ||
|
||
p = len(self.buf) & ~63 | ||
if p > 0: | ||
self.h = compress(self.h, self.buf[:p]) | ||
self.buf = self.buf[p:] | ||
assert len(self.buf) < 64 | ||
|
||
def digest(self): | ||
|
||
length = (self.bytes << 3) & (2**64-1) | ||
|
||
assert len(self.buf) < 64 | ||
data = self.buf + "\x80" | ||
if len(data) <= 56: | ||
assert len(data) <= 56 | ||
data = struct.pack("<56sQ", data, length) | ||
else: | ||
assert len(data) <= 120 | ||
data = struct.pack("<120sQ", data, length) | ||
|
||
h = compress(self.h, data) | ||
return struct.pack("<5L", *h) | ||
|
||
def hexdigest(self): | ||
return self.digest().encode('hex') | ||
|
||
def copy(self): | ||
obj = self.__class__() | ||
obj.h = self.h | ||
obj.bytes = self.bytes | ||
obj.buf = self.buf | ||
return obj | ||
|
||
def ripenew(data=""): | ||
return RIPEMD160(data) | ||
|
||
digest_size = 20 | ||
|
||
Pcurve = 2**256 - 2**32 - 2**9 - 2**8 - 2**7 - 2**6 - 2**4 -1 | ||
N=0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 | ||
Acurve = 0; Bcurve = 7 | ||
Gx = 55066263022277343669578718895168534326250603453777594175500187360389116729240 | ||
Gy = 32670510020758816978083085130507043184471273380659243275938904335757337482424 | ||
GPoint = (Gx,Gy) | ||
|
||
def modinv(a,n=Pcurve): | ||
lm, hm = 1,0 | ||
low, high = a%n,n | ||
while low > 1: | ||
ratio = high/low | ||
nm, new = hm-lm*ratio, high-low*ratio | ||
lm, low, hm, high = nm, new, lm, low | ||
return lm % n | ||
|
||
def ECadd(a,b): | ||
LamAdd = ((b[1]-a[1]) * modinv(b[0]-a[0],Pcurve)) % Pcurve | ||
x = (LamAdd*LamAdd-a[0]-b[0]) % Pcurve | ||
y = (LamAdd*(a[0]-x)-a[1]) % Pcurve | ||
return (x,y) | ||
|
||
def ECdouble(a): | ||
Lam = ((3*a[0]*a[0]+Acurve) * modinv((2*a[1]),Pcurve)) % Pcurve | ||
x = (Lam*Lam-2*a[0]) % Pcurve | ||
y = (Lam*(a[0]-x)-a[1]) % Pcurve | ||
return (x,y) | ||
|
||
def EccMultiply(GenPoint,ScalarHex): | ||
if ScalarHex == 0 or ScalarHex >= N: raise Exception("Invalid Scalar/Private Key") | ||
ScalarBin = str(bin(ScalarHex))[2:] | ||
Q=GenPoint | ||
for i in range (1, len(ScalarBin)): | ||
Q=ECdouble(Q); | ||
if ScalarBin[i] == "1": | ||
Q=ECadd(Q,GenPoint); | ||
return (Q) | ||
|
||
__b58chars = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz' | ||
__b58base = len(__b58chars) | ||
|
||
def b58encode(v): | ||
|
||
long_value = 0L | ||
for (i, c) in enumerate(v[::-1]): | ||
long_value += (256**i) * ord(c) | ||
|
||
result = '' | ||
while long_value >= __b58base: | ||
div, mod = divmod(long_value, __b58base) | ||
result = __b58chars[mod] + result | ||
long_value = div | ||
result = __b58chars[long_value] + result | ||
|
||
nPad = 0 | ||
for c in v: | ||
if c == '\0': nPad += 1 | ||
else: break | ||
|
||
return (__b58chars[0]*nPad) + result | ||
|
||
HEXCODE = '0123 4567 89ab cdef'.replace(' ','') | ||
LETCODE = 'asdf ghjk wert uion'.replace(' ','') | ||
|
||
def seed_to_bin(seed): | ||
lines = seed.replace(' ', '').split('<>') | ||
newlines = [] | ||
new = '' | ||
for i in range(2): | ||
for j in range(len(lines[i])): | ||
new += HEXCODE[LETCODE.find(lines[i][j])] | ||
newlines.append(new) | ||
new = '' | ||
newseed = newlines[0][:32] + newlines[1][:32] | ||
chk1 = hashlib.sha256(hashlib.sha256(newlines[0][:32].decode('hex')).digest()).hexdigest()[:4] | ||
chk2 = hashlib.sha256(hashlib.sha256(newlines[1][:32].decode('hex')).digest()).hexdigest()[:4] | ||
assert chk1 == newlines[0][32:], "Invalid Checksum: Check to make sure you typed your Backup in right." | ||
assert chk2 == newlines[1][32:], "Invalid Checksum: Check to make sure you typed your Backup in right." | ||
return newseed | ||
|
||
|
||
def gen_addy_priv(MPK, secret, n, c=0): | ||
index = int(hashlib.sha256(hashlib.sha256("%d:%d:"%(n,c) + MPK.decode('hex')).digest()).hexdigest(),16) | ||
addy_pt = ECadd(EccMultiply(GPoint,index),(int(MPK[:64],16),int(MPK[64:],16))) | ||
privsec = (secret + index) % N | ||
assert EccMultiply(GPoint,privsec) == addy_pt, "Private Key and Generated Public Key don't match!" | ||
h160 = ripenew(hashlib.sha256(("04" + ("%064x" % addy_pt[0]) + ("%064x" % addy_pt[1])).decode('hex')).digest()).digest() | ||
h160chk = hashlib.sha256(hashlib.sha256(chr(0) + h160).digest()).digest()[:4] | ||
addy = b58encode(chr(0) + h160 + h160chk) | ||
|
||
privchk = hashlib.sha256(hashlib.sha256(chr(128) + ("%064x" % privsec).decode('hex')).digest()).digest()[:4] | ||
wifpriv = b58encode(chr(128) + ("%064x" % privsec).decode('hex') + privchk) | ||
|
||
return addy, wifpriv | ||
|
||
|
||
############################################################################################## | ||
# | ||
print "Please type in your \"Paper Backup Phrase\" from Armory." | ||
print "Type in the first line, then the second line. It will ask for each line separately." | ||
print "Also, for the second input, please paste in the \"Master Public Key\" from Electrum." | ||
print "We must check and make sure Electrum has the correct MPK that matches your Backup Phrase" | ||
print "from Armory, so open the watch-only wallet in Electrum, and \"Wallet\" > \"Master Public Key\"" | ||
print "and paste that long number into the MPK input line." | ||
print "Windows command window can only paste by right clicking the bar at the top, clicking \"Edit\"," | ||
print "then clicking paste." | ||
# | ||
bckup = raw_input("Armory Backup Phrase? (1st Line) ") | ||
bckup2 = raw_input("Armory Backup Phrase? (2nd Line) ") | ||
bckup = bckup + " <> " + bckup2 | ||
#'aagh hjfj sihk ietj giik wwai awtd uodh hnji <> soss uaku egod utai itos fijj ihgi jhau jtoo' | ||
#'aaghhjfjsihkietjgiikwwaiawtduodhhnji <> sossuakuegodutaiitosfijjihgijhaujtoo' | ||
# | ||
chkMPK = raw_input("Electrum MPK? ") | ||
#'5a09a3286873a72f164476bde9d1d8e5c2bc044e35aa47eb6e798e325a86417f7c35b61d9905053533e0b4f2a26eca0330aadf21c638969e45aaace50e4c0c87' | ||
# | ||
############################################################################################## | ||
|
||
|
||
secpriv = int(seed_to_bin(bckup),16) | ||
pt = EccMultiply(GPoint,secpriv) | ||
MPK = ("%064x" % pt[0]) + ("%064x" % pt[1]) | ||
assert MPK == chkMPK, "Your MPK and the backup phrase MPK don't match." | ||
|
||
print "Receive Address + Private Key" | ||
for i in range(5): | ||
addy, wifpriv = gen_addy_priv(MPK, secpriv, i) | ||
print addy, wifpriv | ||
print "Change Address + Private Key" | ||
for i in range(3): | ||
addy, wifpriv = gen_addy_priv(MPK, secpriv, i, 1) | ||
print addy, wifpriv | ||
raw_input() | ||
except Exception,e: | ||
print "ERROR: " + str(e) | ||
raw_input() |
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
from distutils.core import setup | ||
import py2exe, sys, os | ||
|
||
sys.argv.append('py2exe') | ||
|
||
setup( | ||
options = {'py2exe': {'bundle_files': 1, 'compressed': True}}, | ||
console = [{'script': "arms.py", | ||
'icon_resources':[(1,'electrum.ico')]}], | ||
zipfile = None, | ||
) |