Bitcoin Forum
May 01, 2024, 07:45:54 AM *
News: Latest Bitcoin Core release: 27.0 [Torrent]
 
   Home   Help Search Login Register More  
Pages: [1]
  Print  
Author Topic: BASH21 - A simple BASH paper wallet generator  (Read 225 times)
apogio (OP)
Sr. Member
****
Online Online

Activity: 420
Merit: 956



View Profile WWW
January 27, 2024, 07:40:31 PM
Last edit: March 13, 2024, 09:41:56 PM by apogio
Merited by LoyceV (12), ABCbits (8), RickDeckard (6), vapourminer (4), seoincorporation (2), TryNinja (2), DdmrDdmr (1), darkv0rt3x (1), Cricktor (1)
 #1

Background:
I have been sick for the past couple of days, so I decided to test my coding skills.

I took some inspiration from this post. To be honest, I don't like paper wallets, but I thought I could learn more about how bitcoin works, through implementing a paper wallet in bash.

Disclaimers:
1. I have no experience in Bash scripting.
2. I will not use this program and I also advise you to use it only for educational purposes.

Prerequisites:
Code:
sudo apt install base58
sudo apt install xxd
sudo apt install qrencode

The script:
Code:
#! /bin/bash

###############################################
################# FUNCTIONS ###################
###############################################

calculate_checksum(){
        prefix=$1
        value=$2
        suffix=$3
        s1=$(echo -n "${prefix}${value}${suffix}" | xxd -r -p | openssl sha256 | awk '{print $2}')
        s2=$(echo -n ${s1} | xxd -r -p | openssl sha256 | awk '{print $2}')
        checksum=$(echo ${s2} | head -c 8)
        echo ${checksum}
}

hash_160(){
        input=$1
        sha=$(echo -n ${input} | xxd -r -p | openssl sha256 | awk '{print $2}')
        echo -n ${sha} | xxd -r -p | openssl ripemd160 | awk '{print $2}'
}

generate_p2pkh(){
        hash160=$1
        checksum=$(calculate_checksum "00" ${hash160} "")
        echo -n "00${hash160}${checksum}" | xxd -r -p | base58
}

generate_p2sh(){
        input=$1
        hash160=$(hash_160 "0014${input}")
        checksum=$(calculate_checksum "05" ${hash160} "")
        echo -n "05${hash160}${checksum}" | xxd -r -p | base58
}

print_keys(){
        echo "Entropy: $1"
        echo "PK: $2"
        echo "WIF: $3"
        echo "Public Key: $4"
        echo "Compressed Public Key: $5"
        echo "HASH160: $6"
        echo "Legacy Address: $7"
        echo "Segwit Address: $8"
}

encrypt_keys(){
        print_keys $1 $2 $3 $4 $5 $6 $7 $8 | gpg -c -o keys.gpg
}

print_qr_codes(){
        qrencode -s 6 -l M -o legacy_address.png $1
        qrencode -s 6 -l M -o segwit_address.png $2
}

print_addresses(){
        echo "Legacy Address: $1"
        echo "Segwit Address: $2"
}

create_addresses_file(){
        print_addresses $1 $2 > addresses.txt
}

###############################################
################# MAIN ########################
###############################################

# CONVERT ENTROPY TO WIF KEY

entropy=$(cat /dev/urandom | tr -dc '[:graph:]' | fold -w 64 | head -n 1)

pk=$(echo -n ${entropy} | openssl sha256 | awk '{print $2}')

checksum=$(calculate_checksum "80" ${pk} "01")

wif=$(echo -n "80${pk}01${checksum}" | xxd -r -p | base58)

# CONVERT PRIVATE KEY TO COMPRESSED PUBLIC KEY USING OPENSSL SECP256K1

public_key=$(openssl ec -inform DER -text -noout -in <(cat <(echo -n "302e0201010420") <(echo -n ${pk}) <(echo -n "a00706052b8104000a") | xxd -r -p) 2>/dev/null | tail -6 | head -5 | sed 's/[ :]//g' | tr -d '\n' && echo)

x_coord=$(printf ${public_key} | cut -c -66 | cut -c 3-)
last_byte=$(printf ${public_key} | cut -c 129-)
last_int=$(printf "%d" 0x${last_byte})
is_odd=$(expr ${last_int} % 2)
if [ "$is_odd" == 1 ]; then
    compressed_public_key=03${x_coord}
else
    compressed_public_key=02${x_coord}
fi

# CONVERTING PUBLIC KEY TO COMPRESSED LEGACY ADDRESS

hash160=$(hash_160 ${compressed_public_key})

legacy_address=$(generate_p2pkh ${hash160})

segwit_address=$(generate_p2sh ${hash160})

# PRINT DATA

encrypt_keys ${entropy} ${pk} ${wif} ${public_key} ${compressed_public_key} ${hash160} ${legacy_address} ${segwit_address}

print_qr_codes ${legacy_address} ${segwit_address}

create_addresses_file ${legacy_address} ${segwit_address}


Usage:
Create a .sh script file anywhere on your computer:
Code:
touch paperwallet.sh

Copy paste the code and save it. The easiest way is with nano:
Code:
nano paperwallet.sh
<paste the code>
Ctrl+o (save)
Ctrl+x (exit)

Make it executable for the current user:
Code:
chmod u+x paperwallet.sh

Run it:
Code:
./paperwallet.sh

Execution results:
1. A file keys.gpg which includes the sensitive data (keys etc.) of the wallet. The file is encrypted with the password that you set at execution time.
2. A file legacy_address.png which displays a QR code for the wallet's legacy (P2PKH) address.
3. A file segwit_address.png which displays a QR code for the wallet's segwit (P2WPKH-P2SH) address.
4. A file addresses.txt which includes the addresses in .txt format.

keys.gpg file format:
Code:
Entropy: D_}L1jJie.'&p~@GS<@/~Yr;?uj69lm!vT^V`h1uxW!nhYU"'D>H@`7NP]#e7<?{
PK: c46b641982fd74f10a1607d01e70e4d4c7a5aed2c01c7b09bd66044ce26f0913
WIF: L3oXPPp62gS6NtxopBGoGDhvs6g4ovGp4oX34nLXa566d6qNSMyJ
Public Key: 048f92eb77547bc8b1f5e1e62b683399d75bfc1e98621fef0e253f36baf27891d8c07e72e095cd5b298bc94182a050e80b66a64d0f76967bd1d44077430289dae4
Compressed Public Key: 028f92eb77547bc8b1f5e1e62b683399d75bfc1e98621fef0e253f36baf27891d8
HASH160: 9ba03f824e7883027d07fb15a627a82a897195ba
Legacy Address: 1FBshy1TaRCoWM2ChiJ6dyDZdPmEfDAHHq
Segwit Address: 37gzjcd6wssRB2igUWDYNB4cp546ksFXXo

Some notes:
  • The entropy is produced from /dev/urandom.
  • The methods I used are included in the openssl library. I have used sha256, ripemd160 and ec.
  • Coding-wise, it sucks, I know... But as I said, it's my first effort with bash scripting.
  • I have tested the results on Ian Coleman's website. I have also imported some of the WIFs in Electrum and made sure it produces the correct addresses.
  • I could have only printed the WIF and the Address, because that's what paper wallets do, but as I said, it's for educational purposes only, so I printed all the steps of the process.


Changelog:
24/01/28 || Adds QR code for legacy address, using qrencode linux command.
24/01/29 || Refactors code. Adds more functions.
24/01/30 || Adds Segwit (p2wpkh-p2sh) address. Minor code changes.


1714549554
Hero Member
*
Offline Offline

Posts: 1714549554

View Profile Personal Message (Offline)

Ignore
1714549554
Reply with quote  #2

1714549554
Report to moderator
1714549554
Hero Member
*
Offline Offline

Posts: 1714549554

View Profile Personal Message (Offline)

Ignore
1714549554
Reply with quote  #2

1714549554
Report to moderator
1714549554
Hero Member
*
Offline Offline

Posts: 1714549554

View Profile Personal Message (Offline)

Ignore
1714549554
Reply with quote  #2

1714549554
Report to moderator
Each block is stacked on top of the previous one. Adding another block to the top makes all lower blocks more difficult to remove: there is more "weight" above each block. A transaction in a block 6 blocks deep (6 confirmations) will be very difficult to remove.
Advertised sites are not endorsed by the Bitcoin Forum. They may be unsafe, untrustworthy, or illegal in your jurisdiction.
1714549554
Hero Member
*
Offline Offline

Posts: 1714549554

View Profile Personal Message (Offline)

Ignore
1714549554
Reply with quote  #2

1714549554
Report to moderator
1714549554
Hero Member
*
Offline Offline

Posts: 1714549554

View Profile Personal Message (Offline)

Ignore
1714549554
Reply with quote  #2

1714549554
Report to moderator
darkv0rt3x
Hero Member
*****
Offline Offline

Activity: 1204
Merit: 658


I rather die on my feet than to live on my knees


View Profile
January 27, 2024, 08:12:19 PM
Merited by vapourminer (1), apogio (1)
 #2

For your first attempt with Bash, it looks like you're already a pro! heheh. At least to my eyes.

I tried something similar but using C and GMP library, just for fun and also to learn. I also know the code could be better, mostly when it comes to the ECDSA math. I used too many variables where I coul have reused old ones but I think the thing works. I didn't know about that site you mentioned to test keys and I just tried one of my generated key and it seemed to work!

I started a post in a local board only to keep track of my work and not lose the drive to get to my goal which was to generate a valid public key from a private key (also generated using only /dev/urandom).
I saved a "copy" of my code in gitlab here (for anyone interested in taking a look at the code):

https://gitlab.com/PsySc0rpi0n/bitcoinexp

It was a good learning experience and also I get to know GMP library that I didn't even know it was needed stuff like that to be able to handle such large numbers as Bitcoin uses!

Of course that I also don't recommend to use my code with anything real. This was just for experimenting / playing and I didn't even got as far as you did!

Bitcoin is energy. Bitcoin is freedom
I rather die on my feet than living on my knees!
apogio (OP)
Sr. Member
****
Online Online

Activity: 420
Merit: 956



View Profile WWW
January 27, 2024, 08:20:36 PM
 #3

I saved a "copy" of my code in gitlab here (for anyone interested in taking a look at the code):

I will definitely check it since I am good in C. I will let you know if I have any suggestions.

I didn't know about that site you mentioned to test keys and I just tried one of my generated key and it seemed to work!

Well I think it is a very reputable website with multiple tools regarding Bitcoin. Take a look at it. Some people use it offline in order to generate wallets too. I don't, but I am just saying.


darkv0rt3x
Hero Member
*****
Offline Offline

Activity: 1204
Merit: 658


I rather die on my feet than to live on my knees


View Profile
January 27, 2024, 11:14:57 PM
 #4

I saved a "copy" of my code in gitlab here (for anyone interested in taking a look at the code):

I will definitely check it since I am good in C. I will let you know if I have any suggestions.

I didn't know about that site you mentioned to test keys and I just tried one of my generated key and it seemed to work!

Well I think it is a very reputable website with multiple tools regarding Bitcoin. Take a look at it. Some people use it offline in order to generate wallets too. I don't, but I am just saying.



I bet you'll find a lot to improve in my code. I did nothing special as the library I used do 99% of the job. The difficult part for me was to understand how to use the library and the terminology they used in docs!

Bitcoin is energy. Bitcoin is freedom
I rather die on my feet than living on my knees!
ABCbits
Legendary
*
Offline Offline

Activity: 2856
Merit: 7430


Crypto Swap Exchange


View Profile
January 28, 2024, 11:56:37 AM
Merited by apogio (1)
 #5

  • The methods I used are included in the openssl library. I have used sha256, ripemd160 and ec.

FYI, Bitcoin Core stopped using OpenSSL due to security concern[1].

  • Coding-wise, it sucks, I know... But as I said, it's my first effort with bash scripting.

Don't be discouraged. I use Linux daily, but i almost never create Bash script. And when i do, it's not as good as yours.

[1] https://bitcoincore.org/en/2016/02/23/release-0.12.0/

█▀▀▀











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











▄▄▄█
▄██████▄▄▄
█████████████▄▄
███████████████
███████████████
███████████████
███████████████
███░░█████████
███▌▐█████████
█████████████
███████████▀
██████████▀
████████▀
▀██▀▀
apogio (OP)
Sr. Member
****
Online Online

Activity: 420
Merit: 956



View Profile WWW
January 28, 2024, 12:02:36 PM
 #6

FYI, Bitcoin Core stopped using OpenSSL due to security concern[1].

[1] https://bitcoincore.org/en/2016/02/23/release-0.12.0/

This is super important! Thanks for notifying me! I will try to find a way to avoid openssl. I can use sha256sum instead of openssl sha256 but I don't know what to use for ripemd160 and ec.

Anyway, good catch!

Edit: From what I read, there hasn't been an event that caused this change, but rather the fact that the attack space against openssl is much larger, due to its huge feature set. I mean, Core devs said that openssl does much more than the validation of the ECDSA signatures and therefore they changed it to something that does "just the validation". I agree with the choice, but perhaps it is an overkill to change it for this simple script I have written which only generates a public key from the private key. Core devs needed 3 years of development to produce libsecp256k1. I will look more into it!

Don't be discouraged. I use Linux daily, but i almost never create Bash script. And when i do, it's not as good as yours.

Very flattering, thanks!


apogio (OP)
Sr. Member
****
Online Online

Activity: 420
Merit: 956



View Profile WWW
January 28, 2024, 02:33:19 PM
Last edit: January 28, 2024, 02:56:01 PM by apogio
 #7

I just added a new section to the OP, for generating the wallet straight into a password encrypted file.

The script asks for a password. If you add the password, it will create a keys.gpg file where the keys are password protected.

Then the script will print the address to the standard output where you can copy it from and use it as you wish.

Essentially, now, the script doesn't expose any key data to the end user. The output is forwarded to gpg and is password encrypted in a file. The only detail that is exposed is the address.

LoyceV
Legendary
*
Offline Offline

Activity: 3290
Merit: 16577


Thick-Skinned Gang Leader and Golden Feather 2021


View Profile WWW
January 28, 2024, 04:00:01 PM
 #8

I like bash, but never looked into how to create a WIF private key. I like it Smiley
If you're bored enough for a challenge: how about using qrencode and ImageMagick to create a really cool looking printable (PDF or high resolution image), ideally with Segwit address and redundancy in printing the keys?

apogio (OP)
Sr. Member
****
Online Online

Activity: 420
Merit: 956



View Profile WWW
January 28, 2024, 04:15:57 PM
 #9

I like bash, but never looked into how to create a WIF private key. I like it Smiley
If you're bored enough for a challenge: how about using qrencode and ImageMagick to create a really cool looking printable (PDF or high resolution image), ideally with Segwit address and redundancy in printing the keys?

Thanks! Well I am sick, so I am really bored. So you would like to have the address printed on a QR code? Or the WIF key too? Also what do you mean by saying redundancy in key printing?

LoyceV
Legendary
*
Offline Offline

Activity: 3290
Merit: 16577


Thick-Skinned Gang Leader and Golden Feather 2021


View Profile WWW
January 28, 2024, 05:01:33 PM
 #10

Well I am sick
Who isn't? Sad

Quote
So you would like to have the address printed on a QR code? Or the WIF key too?
Both. With some cool art work.

Quote
Also what do you mean by saying redundancy in key printing?
Print it more than once, in case part of the paper gets damaged.

There used to be a nice paper wallet website, which unfortunately turned into a scam after it was sold so I won't link it. But the design was nice, and something like it, running from the command line would a very cool thing to have. And with Segwit, of course.

apogio (OP)
Sr. Member
****
Online Online

Activity: 420
Merit: 956



View Profile WWW
January 28, 2024, 05:09:54 PM
 #11

Both. With some cool art work.

Print it more than once, in case part of the paper gets damaged.

There used to be a nice paper wallet website, which unfortunately turned into a scam after it was sold so I won't link it. But the design was nice, and something like it, running from the command line would a very cool thing to have. And with Segwit, of course.

Good idea! I will implement it.

By the way I just implemented the qr code generation for the address.

Now, the script generates:
1. A file keys.gpg which includes the sensitive data (keys etc.) of the wallet. The file is encrypted with the password that you set at execution time.
2. A file address.png which displays a QR code for the wallet's address.
3. A file address.txt which includes the address in text format

seoincorporation
Legendary
*
Offline Offline

Activity: 3136
Merit: 2916


Top Crypto Casino


View Profile
January 28, 2024, 11:00:02 PM
 #12

This is a great work apogio, Bash script was my first coding language, so, i will try it this week and see if a can add some cool stuff to it.

it would be nice to have all the diferent kind off addres for the same Hash160, i know i have that script somewhere, but have to search it.

█████████████████████████
████▐██▄█████████████████
████▐██████▄▄▄███████████
████▐████▄█████▄▄████████
████▐█████▀▀▀▀▀███▄██████
████▐███▀████████████████
████▐█████████▄█████▌████
████▐██▌█████▀██████▌████
████▐██████████▀████▌████
█████▀███▄█████▄███▀█████
███████▀█████████▀███████
██████████▀███▀██████████
█████████████████████████
.
BC.GAME
▄▄░░░▄▀▀▄████████
▄▄▄
██████████████
█████░░▄▄▄▄████████
▄▄▄▄▄▄▄▄▄██▄██████▄▄▄▄████
▄███▄█▄▄██████████▄████▄████
███████████████████████████▀███
▀████▄██▄██▄░░░░▄████████████
▀▀▀█████▄▄▄███████████▀██
███████████████████▀██
███████████████████▄██
▄███████████████████▄██
█████████████████████▀██
██████████████████████▄
.
..CASINO....SPORTS....RACING..
█░░░░░░█░░░░░░█
▀███▀░░▀███▀░░▀███▀
▀░▀░░░░▀░▀░░░░▀░▀
░░░░░░░░░░░░
▀██████████
░░░░░███░░░░
░░█░░░███▄█░░░
░░██▌░░███░▀░░██▌
░█░██░░███░░░█░██
░█▀▀▀█▌░███░░█▀▀▀█▌
▄█▄░░░██▄███▄█▄░░▄██▄
▄███▄
░░░░▀██▄▀


▄▄████▄▄
▄███▀▀███▄
██████████
▀███▄░▄██▀
▄▄████▄▄░▀█▀▄██▀▄▄████▄▄
▄███▀▀▀████▄▄██▀▄███▀▀███▄
███████▄▄▀▀████▄▄▀▀███████
▀███▄▄███▀░░░▀▀████▄▄▄███▀
▀▀████▀▀████████▀▀████▀▀
Cricktor
Hero Member
*****
Offline Offline

Activity: 742
Merit: 1102


Crypto Swap Exchange


View Profile
January 29, 2024, 12:04:29 AM
Last edit: January 29, 2024, 12:18:35 AM by Cricktor
 #13

There used to be a nice paper wallet website, which unfortunately turned into a scam after it was sold so I won't link it. But the design was nice, and something like it, running from the command line would a very cool thing to have. And with Segwit, of course.

Yes, that was the former site of Canton Becker and his original code is preserved in his original Github repo. I also liked Canton Becker's way of folding the paper wallet and his printing templates.

I still have a paper wallet in my family funded which I generated in maybe 2014 or 2015 from Canton Becker's offline code.

As LoyceV said, after Canton Becker sold his website to some scumbag(s), the new owner's site pretends to be as trustworthy as Canton's original, but it is a total scam. The site's Javascript code is crooked and obfuscated and provably doesn't generate random private keys but rather ones that are known to the site owner. There's no wannabee randomness involved even when the site mimics user generated entropy by mouse movement like bitaddress.org does.

You will loose funds if you still dare to create paper wallets from the scammer's site.

To be clear: Canton Becker's original site code didn't scam users, the new site owner changed the paper wallet generator code to a scammy one! And why this scammer can still operate his fraudulent business is beyond my comprehension.

█▀▀▀











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











▄▄▄█
▄██████▄▄▄
█████████████▄▄
███████████████
███████████████
███████████████
███████████████
███░░█████████
███▌▐█████████
█████████████
███████████▀
██████████▀
████████▀
▀██▀▀
apogio (OP)
Sr. Member
****
Online Online

Activity: 420
Merit: 956



View Profile WWW
January 29, 2024, 07:15:55 AM
Last edit: January 29, 2024, 08:48:33 PM by apogio
 #14

This is a great work apogio, Bash script was my first coding language, so, i will try it this week and see if a can add some cool stuff to it.

it would be nice to have all the diferent kind off addres for the same Hash160, i know i have that script somewhere, but have to search it.

Hello and thanks mate. Yeah I can certainly do that. In fact the only thing that changes is the prefix when you create the address.

Instead of using 00 you must use 05. I will certainly try it and update the project. Thanks


ABCbits
Legendary
*
Offline Offline

Activity: 2856
Merit: 7430


Crypto Swap Exchange


View Profile
January 29, 2024, 09:54:13 AM
Last edit: January 29, 2024, 10:15:19 AM by ABCbits
Merited by apogio (1)
 #15

FYI, Bitcoin Core stopped using OpenSSL due to security concern[1].

[1] https://bitcoincore.org/en/2016/02/23/release-0.12.0/

This is super important! Thanks for notifying me! I will try to find a way to avoid openssl. I can use sha256sum instead of openssl sha256 but I don't know what to use for ripemd160 and ec.

Anyway, good catch!

Edit: From what I read, there hasn't been an event that caused this change, but rather the fact that the attack space against openssl is much larger, due to its huge feature set. I mean, Core devs said that openssl does much more than the validation of the ECDSA signatures and therefore they changed it to something that does "just the validation". I agree with the choice, but perhaps it is an overkill to change it for this simple script I have written which only generates a public key from the private key. Core devs needed 3 years of development to produce libsecp256k1. I will look more into it!

Yeah, the main reason was attack space. That's why i used term "concern". It's definitely overkill to replace OpenSSL entirely for your script, especially when it seems there's major change on OpenSSL organization and security after heartbleed[1].

[1] https://www.securityweek.com/evolution-openssl-security-after-heartbleed/

█▀▀▀











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











▄▄▄█
▄██████▄▄▄
█████████████▄▄
███████████████
███████████████
███████████████
███████████████
███░░█████████
███▌▐█████████
█████████████
███████████▀
██████████▀
████████▀
▀██▀▀
apogio (OP)
Sr. Member
****
Online Online

Activity: 420
Merit: 956



View Profile WWW
January 30, 2024, 06:51:24 PM
Merited by seoincorporation (1)
 #16

Hi all.

I just added Nested Segwit addresses.

I also changed the output files to:

1. keys.gpg: encrypted keys directory
2. addresses.txt: file that includes P2PKH and P2SH addresses in text format.
3. segwit_address.png: QR code for the segwit address.
4. legacy_address.png: QR code for the legacy address.

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!