5 # See the pod documentation at the end of this file for author,
6 # copyright, and licence information.
9 # libintl-perl (Locale::Recode)
10 # OR libtext-iconv-perl (Text::Iconv),
11 # OR the "recode" binary
16 # * use the user's normal keyring to find signatures
17 # * support for multiple user keys
18 # * better charset conversion
21 my $VERSION = qq$Rev$;
35 gpgsigs $VERSION- http://pgp-tools.alioth.debian.org/
36 (c) 2004 Uli Martens <uli\@youam.net>
37 (c) 2004, 2005 Peter Palfrader <peter\@palfrader.org>
38 (c) 2004, 2005 Christoph Berg <cb\@df7cb.de>
44 my ($fd, $error) = @_;
49 Usage: $PROGRAM_NAME [-r] [-t <charset>] <keyid> <keytxt> [<outfile>]
51 keyid is a long or short keyid (e.g. DE7AAF6E94C09C7F or 94C09C7F)
52 separate multiple keyids with ','
53 -r call gpg --recv-keys before proceeding
54 -f <charset> convert <keytxt> from charset
55 -t <charset> convert UIDs to charset in output
61 my ($fromcharset, $charset, $recv_keys);
66 help
=> sub { usage
(*STDOUT
, 0); },
67 version
=> sub { version
(*STDOUT
); exit 0;},
68 ) or usage
(*STDERR
, 1);
72 $fromcharset ||= "ISO-8859-1";
73 $charset ||= $ENV{LC_ALL
} || $ENV{LC_CTYPE
} || $ENV{LANG
} || "ISO-8859-1";
74 $charset = "ISO-8859-1" unless $charset =~ /[\.-]/;
78 my ($rf, $rt, $if, $it);
79 if (eval "require Locale::Recode") {
80 $rf = Locale
::Recode
->new (from
=> $fromcharset, to
=> $charset) if $fromcharset;
81 $rt = Locale
::Recode
->new (from
=> 'UTF-8', to
=> $charset);
82 } elsif (eval "require Text::Iconv") {
83 $if = Text
::Iconv
->new($fromcharset, $charset) if $fromcharset;
84 $it = Text
::Iconv
->new("UTF-8", $charset);
93 } elsif (defined $if) {
94 return $if->convert($text);
96 my $pid = open3
(\
*WTRFH
, \
*RDRFH
, \
*ERRFH
, 'recode', "$fromcharset..$charset");
100 my $result = <RDRFH
>;
104 die ("'recode' failed, is it installed?\n") unless defined $result;
115 } elsif (defined $it) {
116 my $result = $it->convert($text);
117 warn ("Could not convert '$text'\n") unless defined $result;
118 return (defined $result) ?
$result : $text
120 my $pid = open3
(\
*WTRFH
, \
*RDRFH
, \
*ERRFH
, 'recode', "utf8..$charset");
124 my $result = <RDRFH
>;
128 warn ("'recode' failed, is it installed?\n") unless defined $result;
129 return (defined $result) ?
$result : $text
135 my $mykey = uc(shift @ARGV);
136 my $keytxt = (shift @ARGV) || usage
(*STDERR
, 1);
137 my $outfile = (shift @ARGV) || '-';
139 my @mykeys = split /,/, $mykey;
140 map { s/^0x//i; } @mykeys;
142 if (!@mykeys || scalar @ARGV) {
145 if (!grep { /^([0-9A-F]{16,16}|[0-9A-F]{8,8})$/ } @mykeys) {
146 print STDERR
"Invalid keyid given\n";
150 -r
$keytxt or die ("$keytxt does not exist\n");
153 # get list of keys in file
155 open (TXT
, $keytxt) or die ("Cannot open $keytxt\n");
157 if ( m/^pub +(?:\d+)[DR]\/([0-9A
-F
]{8}) [0-9]{4}-[0-9]{2}-[0-9]{2} *(.*)/ ) {
164 # get all known signatures
166 print STDERR
"Requesting keys from keyserver\n";
167 system "gpg --recv-keys @keys";
170 print STDERR
"Running --list-sigs, this will take a while ";
171 open SIGS
, "gpg --fixed-list-mode --with-colons --list-sigs @keys 2>/dev/null |"
172 or die "can't get gpg listing";
174 my ($key, $uid, $sigs);
176 if ( m/^pub:(?:.*?:){3,3}([0-9A-F]{16,16}):/ ) {
181 if ( m/^uid:(?:.*?:){8,8}(.*):/s ) {
185 if ( m/^sig:(?:.*?:){3,3}([0-9A-F]{8})([0-9A-F]{8}):(?:.*?:){5,5}(.*?):/ ) {
187 if ($class eq '10x') {
189 } elsif ($class eq '11x') {
191 } elsif ($class eq '12x') {
193 } elsif ($class eq '13x') {
198 $sigs->{$key}->{$uid}->{$1.$2} = $class;
199 $sigs->{$key}->{$uid}->{$2} = $class;
206 next if ( m/^(rev|sub|tru):/ );
207 warn "unknown value: '$_', key: ".(defined $key ?
$key :'none')."\n";
212 for my $k ( keys %{$sigs} ) {
213 if ( $k =~ m/^[0-9A-F]{8}([0-9A-F]{8})$/ ) {
214 $sigs->{$1} = $sigs->{$k};
220 open MD
, "gpg --print-md md5 $keytxt|" or warn "can't get gpg md5\n";
223 open MD
, "gpg --print-md sha1 $keytxt|" or warn "can't get gpg sha1\n";
229 my $metatxt = quotemeta($keytxt);
230 $MD5 =~ s/^$metatxt:\s*//;
231 $SHA1 =~ s/^$metatxt:\s*//;
237 my ($key, $uid) = @_;
238 if (! defined $sigs->{$key}->{$uid}) {
239 warn "uid '$uid' not found on key $key\n";
240 return '(' . (' ' x
@mykeys) . ')';
243 foreach my $mykey (@mykeys) {
244 $r .= defined $sigs->{$key}->{$uid}->{$mykey} ?
$sigs->{$key}->{$uid}->{$mykey} : ' ';
250 print STDERR
"Annotating $keytxt, writing into $outfile\n";
251 open (TXT
, $keytxt) or die ("Cannot open $keytxt\n");
252 open (WRITE
, '>'.$outfile) or die ("Cannot open $outfile for writing\n");
254 $_ = myfromrecode
($_);
255 if (/^MD5 Checksum:/ && defined $MD5) {
256 s/[_[:xdigit:]][_ [:xdigit:]]+_/$MD5/;
258 if (/^SHA1 Checksum:/ && defined $SHA1) {
259 s/[_[:xdigit:]][_ [:xdigit:]]+_/$SHA1/;
261 if ( m/^pub +(?:\d+)[DR]\/([0-9A
-F
]{8}) [0-9]{4}-[0-9]{2}-[0-9]{2} *(.*)/ ) {
264 #if ($uid) { # in gpg 1.2, the first uid is here
265 # print WRITE print_tag($key, $uid) . " $_";
269 if ( m/^uid +(.*)$/ ) {
271 die "key is undefined" unless defined $key;
272 die "uid is undefined, key $key" unless defined $uid;
273 die "bad tag from $key | $uid" unless defined (print_tag
($key, $uid));
274 print WRITE print_tag
($key, $uid) . " $_";
280 print WRITE
"Legend:\n";
281 foreach my $i (0 .. @mykeys - 1) {
282 print WRITE
'('. ' 'x
$i . 'S' . ' 'x
(@mykeys-$i-1) . ") signed with $mykeys[$i]\n";
290 B<gpgsigs> - annotate list of GnuPG keys with already done signatures
294 B<gpgsigs> [-r] [-f I<charset>] [-t I<charset>] I<keyid>I<[>B<,>I<keyidI<[>B<,>I<...>I<]>>I<]> F<keytxt> [F<outfile>]
298 B<gpgsigs> was written to assist the user in signing keys during a keysigning
299 party. It takes as input a file containing keys in C<gpg --list-keys> format
300 and prepends every line with a tag indicating if the user has already signed
301 that uid. When the file contains C<MD5 Checksum:> or C<SHA1 Checksum:> lines
302 and placeholders (C<__ __>), the checksum is inserted.
310 Call I<gpg --recv-keys> before creating the output.
314 Convert F<keytxt> from I<charset>. The default is ISO-8859-1.
318 Convert UIDs to I<charset>. The default is derived from LC_ALL, LC_CTYPE, and
319 LANG, and if all these are unset, the default is ISO-8859-1.
323 Use this keyid (8 or 16 byte) for annotation. Multiple keyids can be separated
328 Read input from F<keytxt>.
332 Write output to F<outfile>. Default is stdout.
338 The following key signing parties are using B<gpgsigs>:
340 http://www.palfrader.org/ksp-lt2k4.html
342 http://www.palfrader.org/ksp-lt2k5.html
346 B<GnuPG> is known to change its output format quite often. This version has
347 been tested with gpg 1.2.5 and gpg 1.4.1. YMMV.
353 http://pgp-tools.alioth.debian.org/
355 =head1 AUTHORS AND COPYRIGHT
357 (c) 2004 Uli Martens <uli@youam.net>
359 (c) 2004, 2005 Peter Palfrader <peter@palfrader.org>
361 (c) 2004, 2005 Christoph Berg <cb@df7cb.de>
367 Redistribution and use in source and binary forms, with or without
368 modification, are permitted provided that the following conditions
371 1. Redistributions of source code must retain the above copyright
372 notice, this list of conditions and the following disclaimer.
374 2. Redistributions in binary form must reproduce the above copyright
375 notice, this list of conditions and the following disclaimer in the
376 documentation and/or other materials provided with the distribution.
378 3. The name of the author may not be used to endorse or promote products
379 derived from this software without specific prior written permission.
381 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
382 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
383 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
384 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
385 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
386 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
387 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
388 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
389 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
390 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.