Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Producing printable QR codes for persistent storage of GPG private keys
# Heavily depends on:
# libqrencode (fukuchi.org/works/qrencode/)
# paperkey (jabberwocky.com/software/paperkey/)
# zbar (zbar.sourceforge.net)
# Producing the QR codes:
# Split over 4 codes to ensure the data per image is not too large.
gpg --export-secret-key KEYIDGOESHERE | paperkey --output-type raw | base64 > temp
split temp -n 4 IMG
for f in IMG*; do cat $f | qrencode -o $f.png; done
# Importing the QR codes:
# Note that, when making scans or photographs, you do not produce large images.
# If zbar does not recognise your QR code, try downscaling the image.
for f in IMG*.png; do zbarimg --raw $f | head -c -1 > $f.out ; done
cat *.out | base64 -d | paperkey --pubring ~/.gnupg/pubring.gpg | gpg --import
@stueja

This comment has been minimized.

Copy link

commented Oct 5, 2015

Dear joostrijneveld,
thank you very much for providing this genius method of splitting and qr-ing the key.
I hacked around your export functionality and added rather dirty hacks to

  • export the whole key to pdf
  • export textual and QR key to pdf
  • cross check QR codes with original
    to directly print it and put it into a safe location.
    Maybe others might also want to use that.
#!/bin/bash
# Main credit goes to joostrijneveld on github:
# Ref: https://gist.github.com/joostrijneveld/59ab61faa21910c8434c
# adopted to "I want to have a pdf with a textual AND QR key to directly
# print it and put it in the bank safe" needs by Jan Stuehler,
#2015-10-05. 

if [ $# -lt 2 ]
then
   echo "Please specify [Key ID] and an arbitrary [Name]"
   exit 1
fi

TEMPDIR=gpg2qrtmp
KEYID=$1
KEYNAME=$2

echo "Creating temporary directory $TEMPDIR"
mkdir $TEMPDIR
echo "Changing directory to $TEMPDIR"
cd $TEMPDIR

# Ref: http://stackoverflow.com/a/677212
command -v gpg >/dev/null 2>&1 || { echo >&2 "I require gpg but it's not installed.  Aborting."; exit 1; }
command -v paperkey >/dev/null 2>&1 || { echo >&2 "I require paperkey but it's not installed.  Aborting."; exit 1; }
command -v qrencode >/dev/null 2>&1 || { echo >&2 "I require qrencode but it's not installed.  Aborting."; exit 1; }
command -v convert >/dev/null 2>&1 || { echo >&2 "I require convert (ImageMagick) but it's not installed.  Aborting."; exit 1; }
command -v zbarimg >/dev/null 2>&1 || { echo >&2 "I require zbarimg (zbar) but it's not installed.  Aborting."; exit 1; }
command -v a2ps >/dev/null 2>&1 || { echo >&2 "I require a2ps but it's not installed.  Aborting."; exit 1; }
command -v ps2pdf >/dev/null 2>&1 || { echo >&2 "I require ps2pdf but it's not installed.  Aborting."; exit 1; }


### EXPORT KEY
gpg --export-secret-key $KEYID | paperkey --output-type raw | base64 > $KEYNAME

### GENERATE TITLE PAGE
echo "$KEYNAME:\n" > titlepage.txt
cat $KEYNAME >> titlepage.txt

### GENERATE SCRIPT PAGE
echo "This output was generated by the following code:" > scriptpage.txt
cat ../${0} >> scriptpage.txt


### SPLIT KEY INTO PARTS
# Ref: https://gist.github.com/joostrijneveld/59ab61faa21910c8434c
split -l 12 -a 2 -d --additional-suffix=.txt $KEYNAME


### GENERATE QR CODES FROM KEY PARTS
# qrencode -l H and qrencode -l Q caused problems when reading with zbarimg
for f in x*; do cat $f | head -c -1 | qrencode -o qr-$f.png; done

### CROSS CHECK QR CODES
echo "Cross checking QR codes:"
for f in x*; do
    echo "Reading QR code qr-$f.png:"
    zbarimg --raw qr-$f.png > temp
    echo "Diff-comparing output of qr-$f.png with $f:"
    # Ref: http://stackoverflow.com/a/23497594
    diff temp $f 2>&1
    if [ $? != 0 ]
    then
        echo "Uh oh... difference found in qr-$f.png... exiting.\n"
        exit 1
    fi
done


### CONVERT TEXT KEYS TO PNG FOR PAGE GENERATION
# Ref: http://www.imagemagick.org/script/command-line-options.php#family
echo "Converting textual key parts to png:"
for f in x*.txt; do convert -family Courier $f txt-$f.png; done

### PAGE GENERATION
# Ref: http://www.imagemagick.org/Usage/annotating/#gravity_image
# convert hintergrundtext -gravity vordergrundqr -geometry platz ...

# find files without extension
# Ref: http://unix.stackexchange.com/a/144209
# for f in `find . -type f ! -name "*.*"`; do echo $f; done
# Ref: http://unix.stackexchange.com/a/87665
# find . -maxdepth 1 ! -name "*.*" -o -name ".*[^.]*"
echo "Generate single pages"
i=1
for f in x*; do
    echo "Preparing page $i: $f"
    convert txt-$f.png -gravity north -annotate +10+10 "$f" \
    -gravity South -annotate +10+35 "$f" \
    -gravity South qr-$f.png -geometry +10+40 -compose Bumpmap -composite \
    -annotate +10+10 "Page $i" \
    out$i-$f.png
    i=$(($i + 1))
done


### PDF COMPOSITION
echo "Compose pages to ps"
a2ps -1 -o $KEYNAME.ps titlepage.txt scriptpage.txt `find . -name "out*" | sort`
echo "Converting to pdf"
ps2pdf $KEYNAME.ps

### CROSS CHECK PDF
echo "Cross checking QR codes in pdf with original key"
zbarimg --raw $KEYNAME.pdf > temp
diff temp $KEYNAME 2>&1
if [ $? != 0 ]
then
    echo "Uh oh... difference found in $KEYNAME.pdf... exiting.\n"
    exit 1
fi

echo "Moving $KEYNAME.pdf to script folder"
mv $KEYNAME.pdf ../
cd ..
echo "Removing temporary directory $TEMPDIR"
rm -r $TEMPDIR

@balos1

This comment has been minimized.

Copy link

commented Jan 7, 2017

Thanks for this... it inspired me to create easy-gpp-to-paper.

@costrouc

This comment has been minimized.

Copy link

commented Feb 1, 2018

Another alternative is a self generating latex document. Run pdflatex --shell-escape gpgbackup.tex. This will produce a pdf that you can print.

gpgbackup.tex

\documentclass{article}

\usepackage{float}
\usepackage{graphicx}
\usepackage{pgffor}

\def\gpgkey{yourkeyname}

\newcommand\gpgtopng{
  \immediate\write18{gpg --export-secret-key \gpgkey | paperkey --output-type raw | base64 > temp}
  \immediate\write18{split temp -n 4 IMG}
  \immediate\write18{for f in IMG*; do cat $f | qrencode -o /tmp/$f.png; done}
  \immediate\write18{rm IMG* temp}
}

\gpgtopng

\begin{document}

\foreach \l in {a, ..., d} {
  \begin{figure}[H]
    \centering
    \includegraphics[width=0.6\textwidth]{/tmp/IMGa\l.png}
    \caption{QR \l}
  \end{figure}
}

To recover run the following command

\begin{verbatim}
for f in IMG*.png; do zbarimg --raw $f | head -c -1 > $f.out ; done
cat *.out | base64 -d | paperkey --pubring ~/.gnupg/pubring.gpg | gpg --import
\end{verbatim}

\end{document}
@nurupo

This comment has been minimized.

Copy link

commented Aug 3, 2018

Here is a bash script that converts any file into a printable PDF with QR codes that you can use to restore the file back https://github.com/nurupo/paper-store.

See PDF examples at https://github.com/nurupo/paper-store#examples.

@jgogstad

This comment has been minimized.

Copy link

commented Aug 25, 2018

What's the reason for passing the output from zbarimg through head -c -1? What's up with the last byte? Is it for dropping newlines?

Edit: Yes it is

@elquimista

This comment has been minimized.

Copy link

commented Nov 12, 2018

head -c -1 should be just head (without any args) in macOS.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.