mirror of
https://github.com/Isaacdelly/Plutus.git
synced 2025-03-17 21:31:46 +01:00
151 lines
5.9 KiB
Python
151 lines
5.9 KiB
Python
# 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(private_key)
|
|
return '04' + pk.publicKey().toString().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:
|
|
with open('plutus.txt', 'a') as file:
|
|
file.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')
|
|
|
|
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
|
|
|
|
|
|
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.''')
|
|
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': False
|
|
}
|
|
if platform.system() in ['Linux', 'Darwin']:
|
|
args['fastecdsa'] = True
|
|
|
|
for arg in sys.argv[1:]:
|
|
command = arg.split('=')[0]
|
|
if command == 'help':
|
|
print_help()
|
|
elif command == 'time':
|
|
timer(args)
|
|
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: ' + arg.split('=')[0] + '\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()
|
|
database.add(address[-args['substring']:])
|
|
print('DONE')
|
|
|
|
print('database size: ' + str(len(database)))
|
|
print('processes spawned: ' + str(multiprocessing.cpu_count()))
|
|
|
|
for cpu in range(multiprocessing.cpu_count()):
|
|
multiprocessing.Process(target = main, args = (database, args)).start()
|