-
Notifications
You must be signed in to change notification settings - Fork 541
/
plutus.py
165 lines (141 loc) · 6.82 KB
/
plutus.py
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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
# Plutus Bitcoin Brute Forcer
# Made by Isaac Delly
# https://github.com/Isaacdelly/Plutus
from fastecdsa import keys, curve
from ellipticcurve.privateKey import PrivateKey
import platform
import multiprocessing
import hashlib
import binascii
import os
import sys
import time
DATABASE = r'database/11_13_2022/'
def generate_private_key():
return binascii.hexlify(os.urandom(32)).decode('utf-8').upper()
def private_key_to_public_key(private_key, fastecdsa):
if fastecdsa:
key = keys.get_public_key(int('0x' + private_key, 0), curve.secp256k1)
return '04' + (hex(key.x)[2:] + hex(key.y)[2:]).zfill(128)
else:
pk = PrivateKey().fromString(bytes.fromhex(private_key))
return '04' + pk.publicKey().toString().hex().upper()
def public_key_to_address(public_key):
output = []
alphabet = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'
var = hashlib.new('ripemd160')
encoding = binascii.unhexlify(public_key.encode())
var.update(hashlib.sha256(encoding).digest())
var_encoded = ('00' + var.hexdigest()).encode()
digest = hashlib.sha256(binascii.unhexlify(var_encoded)).digest()
var_hex = '00' + var.hexdigest() + hashlib.sha256(digest).hexdigest()[0:8]
count = [char != '0' for char in var_hex].index(True) // 2
n = int(var_hex, 16)
while n > 0:
n, remainder = divmod(n, 58)
output.append(alphabet[remainder])
for i in range(count): output.append(alphabet[0])
return ''.join(output[::-1])
def private_key_to_wif(private_key):
digest = hashlib.sha256(binascii.unhexlify('80' + private_key)).hexdigest()
var = hashlib.sha256(binascii.unhexlify(digest)).hexdigest()
var = binascii.unhexlify('80' + private_key + var[0:8])
alphabet = chars = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'
value = pad = 0
result = ''
for i, c in enumerate(var[::-1]): value += 256**i * c
while value >= len(alphabet):
div, mod = divmod(value, len(alphabet))
result, value = chars[mod] + result, div
result = chars[value] + result
for c in var:
if c == 0: pad += 1
else: break
return chars[0] * pad + result
def main(database, args):
while True:
private_key = generate_private_key()
public_key = private_key_to_public_key(private_key, args['fastecdsa'])
address = public_key_to_address(public_key)
if args['verbose']:
print(address)
if address[-args['substring']:] in database:
for filename in os.listdir(DATABASE):
with open(DATABASE + filename) as file:
if address in file.read():
with open('plutus.txt', 'a') as plutus:
plutus.write('hex private key: ' + str(private_key) + '\n' +
'WIF private key: ' + str(private_key_to_wif(private_key)) + '\n'
'public key: ' + str(public_key) + '\n' +
'uncompressed address: ' + str(address) + '\n\n')
break
def print_help():
print('''Plutus homepage: https://github.com/Isaacdelly/Plutus
Plutus QA support: https://github.com/Isaacdelly/Plutus/issues
Speed test:
execute 'python3 plutus.py time', the output will be the time it takes to bruteforce a single address in seconds
Quick start: run command 'python3 plutus.py'
By default this program runs with parameters:
python3 plutus.py verbose=0 substring=8
verbose: must be 0 or 1. If 1, then every bitcoin address that gets bruteforced will be printed to the terminal. This has the potential to slow the program down. An input of 0 will not print anything to the terminal and the bruteforcing will work silently. By default verbose is 0.
substring: to make the program memory efficient, the entire bitcoin address is not loaded from the database. Only the last <substring> characters are loaded. This significantly reduces the amount of RAM required to run the program. if you still get memory errors then try making this number smaller, by default it is set to 8. This opens us up to getting false positives (empty addresses mistaken as funded) with a probability of 1/(16^<substring>), however it does NOT leave us vulnerable to false negatives (funded addresses being mistaken as empty) so this is an acceptable compromise.
cpu_count: number of cores to run concurrently. More cores = more resource usage but faster bruteforcing. Omit this parameter to run with the maximum number of cores''')
sys.exit(0)
def timer(args):
start = time.time()
private_key = generate_private_key()
public_key = private_key_to_public_key(private_key, args['fastecdsa'])
address = public_key_to_address(public_key)
end = time.time()
print(str(end - start))
sys.exit(0)
if __name__ == '__main__':
args = {
'verbose': 0,
'substring': 8,
'fastecdsa': platform.system() in ['Linux', 'Darwin'],
'cpu_count': multiprocessing.cpu_count(),
}
for arg in sys.argv[1:]:
command = arg.split('=')[0]
if command == 'help':
print_help()
elif command == 'time':
timer(args)
elif command == 'cpu_count':
cpu_count = int(arg.split('=')[1])
if cpu_count > 0 and cpu_count <= multiprocessing.cpu_count():
args['cpu_count'] = cpu_count
else:
print('invalid input. cpu_count must be greater than 0 and less than or equal to ' + str(multiprocessing.cpu_count()))
sys.exit(-1)
elif command == 'verbose':
verbose = arg.split('=')[1]
if verbose in ['0', '1']:
args['verbose'] = verbose
else:
print('invalid input. verbose must be 0(false) or 1(true)')
sys.exit(-1)
elif command == 'substring':
substring = int(arg.split('=')[1])
if substring > 0 and substring < 27:
args['substring'] = substring
else:
print('invalid input. substring must be greater than 0 and less than 27')
sys.exit(-1)
else:
print('invalid input: ' + command + '\nrun `python3 plutus.py help` for help')
sys.exit(-1)
print('reading database files...')
database = set()
for filename in os.listdir(DATABASE):
with open(DATABASE + filename) as file:
for address in file:
address = address.strip()
if address.startswith('1'):
database.add(address[-args['substring']:])
print('DONE')
print('database size: ' + str(len(database)))
print('processes spawned: ' + str(args['cpu_count']))
for cpu in range(args['cpu_count']):
multiprocessing.Process(target = main, args = (database, args)).start()