NAME¶
PGP::Sign - Create detached PGP signatures for data, securely
SYNOPSIS¶
use PGP::Sign;
($signature, $version) = pgp_sign ($keyid, $passphrase, @data);
$signer = pgp_verify ($signature, $version, @data);
@errors = PGP::Sign::pgp_error;
DESCRIPTION¶
This module is designed to do one and only one thing securely and well; namely,
generate and check detached PGP signatures for some arbitrary data. It doesn't
do encryption, it doesn't manage keyrings, it doesn't verify signatures, it
just signs things. This is ideal for applications like PGPMoose or control
message generation that just need a fast signing mechanism. It supports
versions 2.6, 5.0, and 6.5.2 of PGP, as well as GnuPG, and therefore supports
any of the signature types understood by those programs provided they are
installed.
The interface is very simple; just call
pgp_sign() with a key ID, a pass
phrase, and some data, or call
pgp_verify() with a signature (in the
form generated by
pgp_sign()), a version number (which can be undef if
you don't want to give a version), and some data. The data can be specified in
pretty much any form you can possibly consider data and a few you might not.
Scalars and arrays are passed along to PGP; references to arrays are walked
and passed one element at a time (to avoid making a copy of the array); file
handles, globs, or references to globs are read a line at a time and passed to
PGP; and references to code are even supported (see below). About the only
thing that we don't handle are references to references (which are just
printed to PGP, which probably isn't what you wanted) and hashes (which are
treated like arrays, which doesn't make a lot of sense).
If you give either function a reference to a sub, it will repeatedly call that
sub, sending the results to PGP to be signed, until the sub returns undef.
What this lets you do is pass the function an anonymous sub that walks your
internal data and performs some manipulations on it a line at a time, thus
allowing you to sign a slightly modified form of your data (with initial
dashes escaped, for example) without having to use up memory to make an
internal copy of it.
In a scalar context,
pgp_sign() returns the signature as an ASCII-armored
block with embedded newlines (but no trailing newline). In a list context, it
returns a two-element list consisting of the signature as above and the PGP
version that signed it (if that information was present in the signature).
Warning: It's expected that in the future this interface will change, and
pgp_sign() will instead return a list consisting of the ASCII-armored
block and all headers found in the armor.
If you're using GnuPG,
pgp_sign() will pass it the option
--force-v3-sigs so that it will generate PGP 5.0-compatible signatures.
pgp_sign() will return undef in the event of any sort of error.
pgp_verify() returns the signer of the message in the case of a good
signature, the empty string in the case of a bad signature, and undef in the
event of some error. It takes the same sort of data sources as
pgp_sign().
pgp_error() (which isn't exported by default) returns the error
encountered by the last
pgp_sign() or
pgp_verify(), or undef if
there was no error. In a list context, a list of lines is returned; in a
scalar context, a long string with embedded newlines is returned.
Six global variables can be modified (note that these may eventually be
partially or completely replaced with an interface via a
PGP::Sign::config() call):
- $PGP::Sign::PGPS
- The path to the program to use to generate signatures. This is set at the
time of installation, but can be overridden.
- $PGP::Sign::PGPV
- The path to the program to use to verify signatures. This is set at the
time of installation, but can be overridden. There are two separate
variables since PGP 5.0 uses two separate program names for signing and
verifying; for PGP 2.6, 6.5.2, or GnuPG, just set both this and
$PGP::Sign::PGPS to the same value.
- $PGP::Sign::PGPPATH
- The path to a directory containing the PGP key rings that should be used.
If this isn't set, all versions of PGP will use the value of the
environment variable PGPPATH or $HOME/.pgp (the default). GnuPG
will use the value of the environment variable GNUPGHOME or
$HOME/.gnupg. Note that PGP when signing may want to write
randseed.bin (or randseed.rnd) in this directory if there
isn't already a random seed there, so if you're encountering problems with
signing, make sure the directory PGP is using is writeable by the user
doing the signing. Note also that if you're using GnuPG and the Entropy
Gathering Daemon (egd), the entropy socket or a link to it must be located
in this directory.
- $PGP::Sign::PGPSTYLE
- What style of command line arguments and responses to expect from PGP. The
only three valid values for this variable are "PGP2" for PGP 2.6
behavior, "PGP5" for PGP 5.0 behavior, "PGP6" for PGP
6.5 behavior, and "GPG" for GnuPG behavior. What command line
arguments PGP::Sign uses when running PGP are entirely determined by this
variable. It is set at the time of installation, but can be
overridden.
- $PGP::Sign::TMPDIR
- The directory in which temporary files are created. Defaults to TMPDIR if
set, and /tmp if not.
- $PGP::Sign::MUNGE
- If this variable is set to a true value, PGP::Sign will automatically
strip trailing spaces when signing or verifying signatures. This will make
the resulting signatures and verification compatible with programs that
generate attached signatures (since PGP ignores trailing spaces when
generating or checking attached signatures). See the more extensive
discussion of whitespace below.
ENVIRONMENT¶
- PGPPATH
- If $PGP::Sign::PGPPATH is set and $PGP::Sign::PGPSTYLE is something other
than "GPG", PGP::Sign sets PGPPATH to tell PGP where to find its
key rings. (GnuPG uses a command line argument instead.)
- TMPDIR
- The directory in which to create temporary files. Can be overridden by
changing $PGP::Sign::TMPDIR. If not set, defaults /tmp.
In addition, all environment variables that PGP normally honors will be passed
along to PGP and will likely have their expected effects. This includes
PGPPATH, unless it is overridden (see above).
DIAGNOSTICS¶
Mostly the contents of @PGP::Sign::ERROR (returned by
pgp_error()) are
just the output of PGP. The exceptions are:
- Execution of %s failed: %s
- We couldn't fork off a PGP process for some reason, given (at least as the
system reported it) after the colon.
- No signature from PGP (command not found?)
- We tried to generate a signature but the output from the command we tried
to run didn't contain anything that looked like a signature. One common
explanation for this is that the path in $PGP::Sign::PGPS is invalid and
that binary doesn't exist.
- %s returned exit status %d
- Some command that we ran, or tried to run, returned a non-zero exit
status. %s will contain the exact binary name that PGP::Sign was
attempting to run.
BUGS¶
PGP::Sign does not currently work with binary data, as it unconditionally forces
text mode in PGP by using the "-t" option. This is a high priority
to fix, but I'd like to implement some sort of generic way of setting PGP
options rather than just adding more entry points.
There's no way of generating version four DSS signatures. This will be fixed by
the same improvement that will fix the previous bug.
PGP, all versions that I have available, behaves differently when generating
attached signatures than when generating detached signatures. For attached
signatures, trailing whitespace in lines of the data is not significant, but
for detached signatures it is. This, combined with the fact that there's no
way that I can see to get PGP to verify a detached signature without using
files on disk, means that in order to maintain the intended default semantics
of this module (manipulating detached signatures), I had to use temporary
files in the implementation of
pgp_verify(). PGP::Sign sets its umask
before creating those temporary files and opens them with O_EXCL, but files
may be left behind in the event that an application using
pgp_verify()
crashes unexpectedly. Setting $PGP::Sign::TMPDIR is recommended.
Also, because of this incompatibility, you need to be aware of what the process
checking the signatures you generate is expecting. If that process is going to
turn your signature into an attached signature for verification (as pgpverify
does for Usenet control messages), then you need to pre-munge your data to
remove trailing whitespace at the ends of lines before feeding it to PGP.
PGP::Sign will do that for you if you set $PGP::Sign::MUNGE to a true value.
To add even more confusion to the mix, earlier versions of GnuPG followed an
interpretation of RFC 2440 that specified text-mode signatures are performed
against data with canonicalized line endings and with trailing whitespace
removed (see section 5.2.1). There is no difference specified there between
attached and detached signatures, and GnuPG treated them both the same.
Versions of GnuPG at least after 1.0 appear to have changed to follow the PGP
behavior instead.
When verification of a signature fails, currently not very much information
about what failed is available (since an invalid signature isn't considered an
error in the
pgp_error() sense).
CAVEATS¶
This module is fairly good at what it does, but it doesn't do very much. At one
point, I had plans to provide more options and more configurability in the
future, particularly the ability to handle binary data, that would probably
mean API changes. I'm not sure at this point whether I'll get to that, or just
replace this module with one that only uses GnuPG as I see no reason to use
any other PGP implementation at this point and GnuPG has a much nicer
programmatic interface.
However, just in case, the interface to this module should not be considered
stable yet; you may have to change your application when you upgrade to a
newer version of this module. The README will list API changes.
RESTRICTIONS¶
PGP::Sign passes pass phrases to PGP via an open one-ended pipe, since this is
the only secure method (both command line switches and environment variables
can potentially be read by other users on the same machine using ps). This
should be supported by any recent version of PGP; I have tested it against
2.6.2, 2.6.3i, 5.0, 6.5.2, GnuPG 0.9.2, and GnuPG 1.0.1. Implicit in this
mechanism, though, is the requirement that the operating system on which
you're running this module supports passing an open pipe to an
exec()ed
subprocess. This may cause portability problems to certain substandard
operating systems.
SEE ALSO¶
pgp(1),
pgps(1),
pgpv(1),
gpg(1)
RFC 2440, <
http://www.rfc-editor.org/rfc/rfc2440.txt>, which specifies the
OpenPGP message format.
The current version of this module is always available from its web site at
<
http://www.eyrie.org/~eagle/software/pgp-sign/>.
AUTHOR¶
Russ Allbery <rra@stanford.edu>
COPYRIGHT AND LICENSE¶
Copyright 1997, 1998, 1999, 2000, 2002, 2004 Russ Allbery
<rra@stanford.edu>.
This program is free software; you may redistribute it and/or modify it under
the same terms as Perl itself.
HISTORY¶
Based heavily on work by Andrew Gierth and benefitting greatly from input,
comments, suggestions, and help from him, this module came about in the
process of implementing PGPMoose signatures and control message signatures for
Usenet. PGPMoose is the idea of Greg Rose, and signcontrol and pgpverify are
the idea of David Lawrence.
Support for PGPPATH, the test suite, some bug fixes, and the impetus to get
another version released came from Andrew Ford. Thank you.
Original support for GnuPG from Todd Underwood and Monte Mitzelfelt. Code for
using --status-fd based on code by Marco d'Itri.