Based on
Kazkaz27's topic (
and challenge), I created a script to print QR-codes for addresses and their private keys in bulk.
ChallengeThat $100 is still up for grabs (layout has to be good, keys must align). Maybe you can do it. I don’t doubt that you can. But I’ll tell you, if you do it correctly, securely and make it easy that would make you a much more capable person then most people in regards to this. I still say it’s not easy. I’d love to see someone complete this challenge. I’ve left a few comments like this in different posts of mine in the past. No one ever actually takes me up on the challenge, so I guess something is up with that😅. I’d love to send someone the $100. 🙌
ResultsThe QR-codes I created are for testnet4 (and all addresses on the first page have 1 testnet coin each).
PDF:
loyce.club/other/print_two-sided.pdf (anyone who needs testnet4 coins: take some, but leave some for someone else)Address list:
loyce.club/other/addresses.txt (note: the last 200 addresses are
not in the PDF, and the keys are lost)

This was printed on a 600 dpi laser printer on normal Xerox paper. If I'd do it again, I'd make the text a bit larger, maybe find a better font, and place it a bit higher above the QR-code.
ScriptI'm not sure how useful this is going to be, but I'll publish how I did it. I used testnet, but for a real application you'll need to take proper security measures to make absolutely sure there are no traces left anywhere on the system you use. Running Live Linux from RAM without storage is ideal, but you may need to install some packages before you can take away it's physical internet cable. There shouldn't be a Wifi connection, curtains should be closed and phone cameras shouldn't even be in the room. Wipe the system when you're done.
I didn't optimize this script for readability or performance. It's not meant for people who don't know what they're doing. Read the comments:
#!/bin/bash
# Inspiration: https://bitcointalk.org/index.php?topic=5543341.0
#sudo swapoff -a
#sudo apt install qrencode imagemagick img2pdf
#Install everything before going offline
echo "Don't just run a script you found on the internet! Check each line and see what it does!"; exit
mkdir /dev/shm/bitcoin; chmod 700 /dev/shm/bitcoin; cd /dev/shm # I use /dev/shm so nothing gets written to disk
~/bitcoin-26.1/bin/bitcoind -testnet -noconnect -deprecatedrpc=create_bdb -datadir=/dev/shm/bitcoin > /dev/null 2> /dev/null &
sleep 5 #wait a few seconds
~/bitcoin-26.1/bin/bitcoin-cli -named -testnet -datadir=/dev/shm/bitcoin createwallet qr descriptors=false # Note: I use an older version of Bitcoin Core so I don't have to deal with a descriptor wallet
for i in {1..2001}
do addy[$i]=$(~/bitcoin-26.1/bin/bitcoin-cli -testnet -datadir=/dev/shm/bitcoin getnewaddress addy_$i legacy)
privkey[$i]=$(~/bitcoin-26.1/bin/bitcoin-cli -testnet -datadir=/dev/shm/bitcoin dumpprivkey ${addy[$i]})
done
~/bitcoin-26.1/bin/bitcoin-cli -testnet -datadir=/dev/shm/bitcoin stop
rm -r /dev/shm/bitcoin
#Test:
echo ${addy[2001]}
echo ${privkey[2001]}
# You now have 2000 unseen legacy testnet addresses and private keys stored as shell variables.
mkdir -p /dev/shm/bitcoin/addy/horizontal /dev/shm/bitcoin/privkey/horizontal; chmod 700 /dev/shm/bitcoin; cd /dev/shm/bitcoin
for i in {1..2000}
do qrencode -o addy.png ${addy[$i]}
convert addy.png -pointsize 12 -fill black -draw 'text 35,10 '\"addy\ $i\"'' -background white -gravity center -extent 175x175 addy/$i.png # Each QR-code gets a number printed, to confirm the address matches the private key on the other side
echo ${addy[$i]} >> addresses.txt
qrencode -o privkey.png ${privkey[$i]}
convert privkey.png -pointsize 12 -fill black -draw 'text 30,10 '\"privkey\ $i\"'' -background white -gravity center -extent 175x175 privkey/$i.png # Note: size 12 is a bit small after printing, and a different font may help too. Also: print the text a bit further from the QR-code
rm addy.png privkey.png
done
# You now have 2000 QR-codes for addresses and their corresponding private keys.
horizontal=15
vertical=20
pages=$((2000/horizontal/vertical))
head -n $((horizontal*vertical*pages)) addresses.txt > tmp; mv tmp addresses.txt # I added this so the list of addresses isn't longer than the list of QR-codes
page=1
while [ $page -le $pages ]
do line=1
while [ $line -le $vertical ]
do j=$((1+horizontal*(line-1)+horizontal*vertical*(page-1)))
convert +append $(while [ $j -le $((horizontal*line+horizontal*vertical*(page-1))) ]; do echo -n "addy/$j.png "; j=$((j+1)); done) addy/horizontal/$page\_$line.png
j=$((horizontal*line+horizontal*vertical*(page-1)))
convert +append $(while [ $j -ge $((1+horizontal*(line-1)+horizontal*vertical*(page-1))) ]; do echo -n "privkey/$j.png "; j=$((j-1)); done) privkey/horizontal/$page\_$line.png
line=$((line+1))
done
line=1; convert -append $(while [ $line -le $vertical ]; do echo -n "addy/horizontal/$page""_$line.png "; line=$((line+1)); done) addy_$page.png
line=1; convert -append $(while [ $line -le $vertical ]; do echo -n "privkey/horizontal/$page""_$line.png "; line=$((line+1)); done) privkey_$page.png
page=$((page+1))
done
img2pdf --pagesize A4 $(page=1; while [ $page -le $pages ]; do echo -n "addy_$((page)).png privkey_$((page)).png "; page=$((page+1)); done) > print_two-sided.pdf
rm -r /dev/shm/bitcoin/addy /dev/shm/bitcoin/privkey /dev/shm/bitcoin/addy_*.png /dev/shm/bitcoin/privkey_*.png
exit # the keys were still in shell memory
#Only 2 files remaining: the list of addresses, and the file to print (2-sided). Both are only stored on /dev/shm (a RAM drive)
#Note: while printing, the .ps-file probably gets written to /var/spool/cups. This is a risk for disk recovery software.
#Be aware of compromised QR-software. Both creator and verifier can give a different address. Check a few QR-codes to make sure they produce the desired key and address (then consider the scanned ones compromised).