Bitcoin Forum
October 18, 2024, 06:28:08 AM *
News: Latest Bitcoin Core release: 28.0 [Torrent]
 
   Home   Help Search Login Register More  
Pages: [1]
  Print  
Author Topic: Code to generate wallets and print them on a thermal printer  (Read 88 times)
rhog (OP)
Newbie
*
Offline Offline

Activity: 11
Merit: 3


View Profile
October 13, 2024, 07:55:52 PM
Last edit: October 14, 2024, 02:34:24 AM by rhog
Merited by ABCbits (2)
 #1

Hello, I'm going to present this code I made, I hope it can be useful for you.

This code is not something innovative, but it can enhance your security.

Basically, it generates a private key with the possibility of a randint from 2^204 to 2^256 for some cryptocurrency and prints it on your receipt printer, without saving any of the key data on the computer

Code:
import random
import binascii
import ecdsa
import hashlib
import sys
import json
import requests
from requests.auth import HTTPBasicAuth

from base58 import b58encode
def secret_to_address(secret, pfv,legacy=False):
    pubk_pair = from_secret_pubk_point(secret)
    compressed_pubk, pubk = _pubk_to_compressed_pubk(*pubk_pair)
    address = _pubk_to_address(pubk,pfv) if legacy else _pubk_to_address(compressed_pubk,pfv)

    return address


def from_secret_pubk_point(secret):
    CURVE = ecdsa.SECP256k1

    sk = ecdsa.SigningKey.from_secret_exponent(secret, curve=CURVE)
    pubk_vk = sk.verifying_key  # the point
    pubk = binascii.b2a_hex(pubk_vk.to_string()).decode('ascii')

    pubk_x = pubk[:64]
    pubk_y = pubk[64:]

    return pubk_x, pubk_y


def _pubk_to_compressed_pubk(pubk_x, pubk_y):
    EVEN_PREFIX = '02'
    UNEVEN_PREFIX = '03'
    LEGACY_PREFIX = '04'
    y_parity = ord(bytearray.fromhex(pubk_y[-2:])) % 2
    prefix = EVEN_PREFIX if y_parity==0 else UNEVEN_PREFIX
    compressed_pubk = prefix + pubk_x

    pubk = LEGACY_PREFIX + pubk_x + pubk_y

    return compressed_pubk, pubk


def _pubk_to_address(pubk,prf):
    pubk_array = bytearray.fromhex(pubk)

    sha = hashlib.sha256()  
    sha.update(pubk_array)
    rip = hashlib.new('ripemd160')
    rip.update(sha.digest())
    if prf=="0":
        PREFIX = "00"
    elif prf=="1":
        PREFIX="30"
    elif prf=="2":
        PREFIX = "1e"
    key_hash = PREFIX + rip.hexdigest()
    sha = hashlib.sha256()
    sha.update(bytearray.fromhex(key_hash))
    checksum = sha.digest()
    sha = hashlib.sha256()
    sha.update(checksum)
    checksum = sha.hexdigest()[0:8]
    address_hex = key_hash + checksum
    
    bs = bytes(bytearray.fromhex(address_hex))
    address = b58encode(bs).decode('utf-8')

    return address


def secret_to_wif(secret,prf):
    if prf=="0":
        PREFIX="80"
    elif prf=="1":
        PREFIX="B0"
    elif prf=="2":
        PREFIX="9e"
    
    hex_string = hex(secret)[2:].zfill(64)
    pre_hash = PREFIX + hex_string

    hash_1 = hashlib.sha256(binascii.unhexlify(pre_hash)).hexdigest()
    hash_2 = hashlib.sha256(binascii.unhexlify(hash_1)).hexdigest()
    checksum = hash_2[:8]

    pre_hash_checksum = pre_hash + checksum
    from_hex_string = int(pre_hash_checksum, 16)
    def _get(idx):
        ALPHABET = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'
        m = 58**idx
        idx = from_hex_string // m % 58
        return ALPHABET[idx]
    IDXS = range(51)
    wif_str = "".join(map(_get, IDXS))

    # Reverse
    rev_wif_str = wif_str[::-1].lstrip('1')

    return rev_wif_str
if __name__ == "__main__":
    txF=""
    arrtxt=[]
    def tryx():
        s=input("Choose one of the options\nBitcoin: 0\nLitecoin: 1\nDogecoin: 2\n")
        if s!="0" and s!="1" and s!="2":
            print("Invalid option, type a number between 1 and 3")
            return ""
        return s
    def chkZ():
        z=input("----\nAmount of private keys\n")
        try:
            if int(z)>25:
                print("Maximum 25 private keys at a time")
                return ""
            return z
        except:
            print("input must be integer")
            return ""
    def qxA():
        d=input("type y or n if you want save public addresses in a json file\n")
        if d.lower()=="y":
            return "y"        
    sv=False
    r=""
    while True:
        s=tryx()
        if s!="":
            z=chkZ()
            if z!="":
                w=qxA()
                if w!="y":
                    break
                r=input("Type name to json eg: dogeAdrs\n")
                sv=True
                break
    for _ in range(int(z)):
        random_number = random.randrange(2**204,115792089237316195423570985008687907852837564279074904382605163141518161494335)
        address_legacy = secret_to_address(random_number,s,True)
        address = secret_to_address(random_number,s)
        wif = secret_to_wif(random_number,s)
        l=0
        js={"wif":wif,"address_legacy":address_legacy,"random_numb":random_number}
        js0={"Address uncompressed":address_legacy,"Address compressed":address}
        arrtxt.append(js0)
        txF+=f'Wif: {wif}\nAdr Unc: {address_legacy}\nAdr: {address}\nRandom: {random_number}\n\n'
    if sv:
        with open(f"{r}.json","w") as e:
            json.dump(arrtxt,e)
    import subprocess
    command = f'echo "{txF}" > /dev/usb/lp0'
    subprocess.run(command, shell=True)


If you found this funny, say it here =D
Demo video
https://www.youtube.com/watch?v=E7q0ITuXCyk

My doge wallet 🤪
DMPeovrJCxyDoBH2n7bHsThsSejoHKFKPF

BlackHatCoiner
Legendary
*
Offline Offline

Activity: 1680
Merit: 8247


Bitcoin is a royal fork


View Profile WWW
October 13, 2024, 08:13:59 PM
 #2

without saving any of the key data on the computer
Do you mean "without storing any data on the disk", instead? When the computer generates a private key, it temporarily stores it in memory, and can be accessed by any software with elevated privileges at that time.

It does not enhance security, apart from malware with read access to the disk space. You're still transmitting a private key into a printer with (most often) closed-source firmware, all of which usually have network access.

█▀▀▀











█▄▄▄
▀▀▀▀▀▀▀▀▀▀▀
e
▄▄▄▄▄▄▄▄▄▄▄
█████████████
████████████▄███
██▐███████▄█████▀
█████████▄████▀
███▐████▄███▀
████▐██████▀
█████▀█████
███████████▄
████████████▄
██▄█████▀█████▄
▄█████████▀█████▀
███████████▀██▀
████▀█████████
▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
c.h.
▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
▀▀▀█











▄▄▄█
▄██████▄▄▄
█████████████▄▄
███████████████
███████████████
███████████████
███████████████
███░░█████████
███▌▐█████████
█████████████
███████████▀
██████████▀
████████▀
▀██▀▀
rhog (OP)
Newbie
*
Offline Offline

Activity: 11
Merit: 3


View Profile
October 13, 2024, 08:43:00 PM
 #3

without saving any of the key data on the computer
Do you mean "without storing any data on the disk", instead? When the computer generates a private key, it temporarily stores it in memory, and can be accessed by any software with elevated privileges at that time.

It does not enhance security, apart from malware with read access to the disk space. You're still transmitting a private key into a printer with (most often) closed-source firmware, all of which usually have network access.

That's not something I would worry about. If you don't know the equipment you're using, you're at risk, and that wouldn't necessarily be because of the code used. If someone wants to read your PC's memory maliciously, they could access anything on it including banking data Roll Eyes






Cricktor
Legendary
*
Offline Offline

Activity: 924
Merit: 1422


Crypto Swap Exchange


View Profile
October 13, 2024, 11:01:26 PM
 #4

I would worry more about that your code as far as I see it can at least in theory generate private keys outside the valid range.

To my knowledge private keys for Bitcoin must be in the range [1...n-1] with n being the generator point in hex
Code:
FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE BAAEDCE6 AF48A03B BFD25E8C D0364141

Chances are miniscule that your random generator produces a value above the maximum allowed value, but anyway it's possible if I read (and understand) your code properly.

Likely such an out-of-valid-bounds condition will be caught when you try to generate the public key from the private key. But who knows how well the imported library functions handle this.

Worst case: you have addresses that burn coins.

And the way you use the range bounds for random number generation looks somewhat odd to me, too. I don't code in Python, I can somewhat read and mostly understand Python code OKish. I wouldn't trust the way you generate random numbers as private keys here.

█▀▀▀











█▄▄▄
▀▀▀▀▀▀▀▀▀▀▀
e
▄▄▄▄▄▄▄▄▄▄▄
█████████████
████████████▄███
██▐███████▄█████▀
█████████▄████▀
███▐████▄███▀
████▐██████▀
█████▀█████
███████████▄
████████████▄
██▄█████▀█████▄
▄█████████▀█████▀
███████████▀██▀
████▀█████████
▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
c.h.
▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
▀▀▀█











▄▄▄█
▄██████▄▄▄
█████████████▄▄
███████████████
███████████████
███████████████
███████████████
███░░█████████
███▌▐█████████
█████████████
███████████▀
██████████▀
████████▀
▀██▀▀
rhog (OP)
Newbie
*
Offline Offline

Activity: 11
Merit: 3


View Profile
October 13, 2024, 11:27:15 PM
 #5

I would worry more about that your code as far as I see it can at least in theory generate private keys outside the valid range.

To my knowledge private keys for Bitcoin must be in the range [1...n-1] with n being the generator point in hex
Code:
FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE BAAEDCE6 AF48A03B BFD25E8C D0364141

Chances are miniscule that your random generator produces a value above the maximum allowed value, but anyway it's possible if I read (and understand) your code properly.

Likely such an out-of-valid-bounds condition will be caught when you try to generate the public key from the private key. But who knows how well the imported library functions handle this.

Worst case: you have addresses that burn coins.

And the way you use the range bounds for random number generation looks somewhat odd to me, too. I don't code in Python, I can somewhat read and mostly understand Python code OKish. I wouldn't trust the way you generate random numbers as private keys here.

As long as secp256k1 is secure, I believe this code will also be. The smallest wallet it could generate would have at least
2²⁰⁴ and if you compare it to the most famous and true Bitcoin puzzle, its largest wallet is 2¹⁶⁰

The way I know to protect your cryptos from future quantum computers is to always keep the assets in a wallet where you have never sent a transaction. This way you protect your public key. In other words, if you send funds to someone the unspent should be sent to a new virgin privkey that you have access to.
Cricktor
Legendary
*
Offline Offline

Activity: 924
Merit: 1422


Crypto Swap Exchange


View Profile
October 13, 2024, 11:47:05 PM
 #6

secp256k1 is secure for more than 15 years, I've not seen any proof of the opposite so far. Your code doesn't prevent the generation of a random number for a private key that is out-of-bounds making the private key invalid.

You can believe what you want, lets hope other used library functions catch such edge cases.

I'm too lazy to calculate the probability that your used random generator will produce a value above the generator point value. We might not see it in our lifetime. I don't like conditionals very much when there could be certainty.

Anyway, lets hope nobody looses coins inspired by your code.

█▀▀▀











█▄▄▄
▀▀▀▀▀▀▀▀▀▀▀
e
▄▄▄▄▄▄▄▄▄▄▄
█████████████
████████████▄███
██▐███████▄█████▀
█████████▄████▀
███▐████▄███▀
████▐██████▀
█████▀█████
███████████▄
████████████▄
██▄█████▀█████▄
▄█████████▀█████▀
███████████▀██▀
████▀█████████
▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
c.h.
▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
▀▀▀█











▄▄▄█
▄██████▄▄▄
█████████████▄▄
███████████████
███████████████
███████████████
███████████████
███░░█████████
███▌▐█████████
█████████████
███████████▀
██████████▀
████████▀
▀██▀▀
rhog (OP)
Newbie
*
Offline Offline

Activity: 11
Merit: 3


View Profile
October 14, 2024, 02:12:33 AM
Last edit: October 14, 2024, 02:24:16 AM by rhog
Merited by Cricktor (1)
 #7

secp256k1 is secure for more than 15 years, I've not seen any proof of the opposite so far. Your code doesn't prevent the generation of a random number for a private key that is out-of-bounds making the private key invalid.

You can believe what you want, lets hope other used library functions catch such edge cases.

I'm too lazy to calculate the probability that your used random generator will produce a value above the generator point value. We might not see it in our lifetime. I don't like conditionals very much when there could be certainty.

Anyway, lets hope nobody looses coins inspired by your code.

About generate private keys out of range, I just fixed this possible issue, thanks for the warn. However, when this happens, it basically generates an error, but prevention is never too much. I changed this line from:
Code:
random_number = random.randrange(2**204,2**265)
to
Code:
random_number = random.randrange(2**204,115792089237316195423570985008687907852837564279074904382605163141518161494335)
ABCbits
Legendary
*
Offline Offline

Activity: 3038
Merit: 7950


Crypto Swap Exchange


View Profile
October 14, 2024, 09:12:58 AM
Merited by Cricktor (1)
 #8

This code is not something innovative, but it can enhance your security.

Basically, it generates a private key with the possibility of a randint from 2^204 to 2^256 for some cryptocurrency and prints it on your receipt printer, without saving any of the key data on the computer

If you care about security, you should replace random with secrets (https://docs.python.org/3/library/secrets.html).

█▀▀▀











█▄▄▄
▀▀▀▀▀▀▀▀▀▀▀
e
▄▄▄▄▄▄▄▄▄▄▄
█████████████
████████████▄███
██▐███████▄█████▀
█████████▄████▀
███▐████▄███▀
████▐██████▀
█████▀█████
███████████▄
████████████▄
██▄█████▀█████▄
▄█████████▀█████▀
███████████▀██▀
████▀█████████
▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
c.h.
▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
▀▀▀█











▄▄▄█
▄██████▄▄▄
█████████████▄▄
███████████████
███████████████
███████████████
███████████████
███░░█████████
███▌▐█████████
█████████████
███████████▀
██████████▀
████████▀
▀██▀▀
Pages: [1]
  Print  
 
Jump to:  

Powered by MySQL Powered by PHP Powered by SMF 1.1.19 | SMF © 2006-2009, Simple Machines Valid XHTML 1.0! Valid CSS!