#!/usr/bin/perl -w # # gpg-key2ps: convert a PGP/GnuPG key into paper slips. # Copyright (C) 2001-2005 Simon Richter # Copyright (C) 2005-2008 Thijs Kinkhorst # Copyright (C) 2005-2008 Christoph Berg # Licenced under the GNU General Public License, # version 2 or later. # # $Id$ use strict; use Getopt::Long; my $version = '$Rev$'; $version =~ s/\$Rev:\s*(\d+)\s*\$/$1/; my $showsubkeys = 0; my $revokestyle = "hide"; my $columns = 2; my $creationdate = scalar(localtime); sub version($) { my $fd = shift; print $fd "gpg-key2ps $version - (c) 2001-2008 Simon Richter, Thijs Kinkhorst, Christoph Berg\n"; } sub usage($$) { my ($fd, $exitcode) = @_; version ($fd); print $fd < \$opts->{help}, '--help' => \$opts->{help}, '-v' => \$opts->{version}, '--version' => \$opts->{version}, '-s' => \$opts->{showsubkeys}, '--show-subkeys' => \$opts->{showsubkeys}, '-p=s' => \$opts->{papersize}, '--paper-size=s' => \$opts->{papersize}, '-r=s' => \$opts->{revokestyle}, '--revoked-style=s' => \$opts->{revokestyle}, '-1' => \$opts->{1}, )) { usage(\*STDERR, 1); } if ($opts->{help}) { usage (\*STDOUT, 0); } if ($opts->{version}) { version (\*STDOUT); exit 0; } if ( $opts->{papersize} ) { $ENV{'PAPERSIZE'} = $opts->{papersize}; } if ( $opts->{showsubkeys} ) { $showsubkeys = 1; } if ( $opts->{revokestyle} ) { $revokestyle = $opts->{revokestyle}; } if ( $revokestyle !~ /^(grey|hide|note|show|strike)$/ ) { print STDERR "Unknown revoked-style \"$revokestyle\".\n"; usage (\*STDERR, 1); } if ( $opts->{1} ) { $columns = 1; } usage(\*STDERR, 1) unless scalar @ARGV >= 1; # determine the paper size through the paperconf tool my $w; my $h; if ( `which paperconf` && $? == 0 ) { $w=`paperconf -w`; $h=`paperconf -h`; chomp($w); chomp($h); } else { # Default to A4. print STDERR "Warning: libpaper-utils is not installed, defaulting to A4.\n"; $w=596; $h=842; } # open a gpg process we'll be reading from below map { s/'/'\\''/g; } @ARGV; # quote single quotes # --list-key due to #382794 open(GPG, "gpg --list-key --with-fingerprint --with-colons '". (join "' '", @ARGV) ."' |"); sub start_postscript { # start the PostScript output print <> exch get show } def /pub { condhline 50 y moveto (pub) show 70 y moveto show showAlgorithm (/) show show 150 y moveto show 200 y moveto show newline needhline } def /fpr { 70 y moveto (Key fingerprint = ) show show newline } def /uid { 50 y moveto (uid) show 200 y moveto show newline } def /sbk { 50 y moveto (sub) show 70 y moveto show showAlgorithm (/) show show 150 y moveto show newline } def EOF # output the desired display for revoked uids if ( $revokestyle eq "grey" ) { print <) { # we don't use these if ( /^(tru|uat):/ ) { next; } # every primary uid causes an extra line because of the separator if ( /^pub:/ ) { start_postscript() unless $started; $started = 1; $numlines++; } # primary uid s/^pub:[^:]*:([^:]*):([0-9]*):.{8,8}(.{8,8}):([^:]*):[^:]*:[^:]*:[^:]*:([^:]*):[^:]*:[^:]*:.*/ ($5) ($4) ($3) $2 ($1) pub/; # fingerprint, format it nicely with spaces if ( /^fpr:[^:]*:[^:]*:[^:]*:[^:]*:[^:]*:[^:]*:[^:]*:[^:]*:([^:]*):.*/ ) { my $fpr = $1; # v4 key $fpr =~ s/(\w{4})(\w{4})(\w{4})(\w{4})(\w{4})(\w{4})(\w{4})(\w{4})(\w{4})(\w{4})/$1 $2 $3 $4 $5 $6 $7 $8 $9 $10/; # v3 key $fpr =~ s/(\w{2})(\w{2})(\w{2})(\w{2})(\w{2})(\w{2})(\w{2})(\w{2})(\w{2})(\w{2})(\w{2})(\w{2})(\w{2})(\w{2})(\w{2})(\w{2})/$1 $2 $3 $4 $5 $6 $7 $8 $9 $10 $11 $12 $13 $14 $15 $16/g; $_ = " ($fpr) fpr\n"; } # user ids s/\\x([0-9a-f][0-9a-f])/ chr(hex($1)) /gie; $_ = `echo "$_" | iconv -c -f utf-8 -t latin1`; s/^uid:[^:r]*:[^:]*:[^:]*:[^:]*:[^:]*:[^:]*:[^:]*:[^:]*:([^:]*):.*/ ($1) uid/; # revoked user id if (s/^uid:r[^:]*:[^:]*:[^:]*:[^:]*:[^:]*:[^:]*:[^:]*:[^:]*:([^:]*):.*/ ($1) revuid/) { next if $revokestyle eq "hide"; } # subkey if (s/^sub:[^r:]*:([^:]*):([0-9]*):.{8,8}(.{8,8}):([^:]*):[^:]*:[^:]*:[^:]*:[^:]*:[^:]*:[^:]*:.*/ ($4) ($3) $2 ($1) sbk/) { next if ! $showsubkeys; } if (s/^sub:r[^:]*:([^:]*):([0-9]*):.{8,8}(.{8,8}):([^:]*):[^:]*:[^:]*:[^:]*:[^:]*:[^:]*:[^:]*:.*/ ($4) ($3) $2 ($1) revsbk/) { next if (!$showsubkeys) || $revokestyle eq "hide"; } $numlines++; # print this line print; } close(GPG); unless ($started) { print STDERR "No public key found.\n"; exit 1; } # output the remaining postscript print < - generates a PS file from a GnuPG keyring =head1 SYNOPSIS B [B<-r> I] [B<-p> I] [B<-1>] [B<-s>] I [ I<...> ] =head1 DESCRIPTION gpg-key2ps generates a PostScript file with your OpenPGP key fingerprint (repeated as often as it fits) useful for keysigning parties. The only argument is the same as you would pass to GPG's list-keys command, either a key-id or a (partial) name. The PS data is written to stdout. =head1 OPTIONS =over =item B<-p> B<--paper-size> I Select the output paper size. Default is to look into /etc/papersize or A4 if libpaper isn't installed. =item B<-s> B<--show-subkeys> Enable subkey information to be printed on the slips. Subkey information is normally not relevant to the key signing process. =item B<-r> B<--revoked-style> I Select how to mark revoked UIDs and subkeys. Five styles are available: B don't show at all (default), B show normally, B display in 50% grey, B add "[revoked]", and B strike through. =item B<-1> Print only one column of paper slips instead of the default two. Useful for keys with long UIDs that otherwise won't fit. =item I Keyids to print. Multiple can be separated by spaces. =item B<-h> B<--help> Print usage and exit. =item B<-v> B<--version> Print version and exit. =back =head1 SEE ALSO =over =item gpg(1) GNU Privacy Guard. =item http://pgp-tools.alioth.debian.org/ The homepage of B and the other tools bundled in B. =item http://www.debian.org/events/materials/business-cards/ B prints plain fingerprint slips. If you are looking for something more stylish, look at these latex templates for business cards that also include fingerprints. =back =head1 AUTHORS AND COPYRIGHT =over =item (c) 2001-2005 Simon Richter =item (c) 2005-2008 Thijs Kinkhorst =item (c) 2005-2008 Christoph Berg =back