diff options
Diffstat (limited to 'README')
-rw-r--r-- | README | 472 |
1 files changed, 472 insertions, 0 deletions
@@ -0,0 +1,472 @@ +NAME + GnuPG::Interface - Perl interface to GnuPG + +SYNOPSIS + # A simple example + use IO::Handle; + use GnuPG::Interface; + + # setting up the situation + my $gnupg = GnuPG::Interface->new(); + $gnupg->options->hash_init( armor => 1, + homedir => '/home/foobar' ); + + # Note you can set the recipients even if you aren't encrypting! + $gnupg->options->push_recipients( 'ftobin@cpan.org' ); + $gnupg->options->meta_interactive( 0 ); + + # how we create some handles to interact with GnuPG + my $input = IO::Handle->new(); + my $output = IO::Handle->new(); + my $handles = GnuPG::Handles->new( stdin => $input, + stdout => $output ); + + # Now we'll go about encrypting with the options already set + my @plaintext = ( 'foobar' ); + my $pid = $gnupg->encrypt( handles => $handles ); + + # Now we write to the input of GnuPG + print $input @plaintext; + close $input; + + # now we read the output + my @ciphertext = <$output>; + close $output; + + waitpid $pid, 0; + +DESCRIPTION + GnuPG::Interface and its associated modules are designed to provide an + object-oriented method for interacting with GnuPG, being able to perform + functions such as but not limited to encrypting, signing, decryption, + verification, and key-listing parsing. + + How Data Member Accessor Methods are Created + Each module in the GnuPG::Interface bundle relies on Moo to generate the + get/set methods used to set the object's data members. *This is very + important to realize.* This means that any data member which is a list + has special methods assigned to it for pushing, popping, and clearing + the list. + + Understanding Bidirectional Communication + It is also imperative to realize that this package uses interprocess + communication methods similar to those used in IPC::Open3 and + "Bidirectional Communication with Another Process" in perlipc, and that + users of this package need to understand how to use this method because + this package does not abstract these methods for the user greatly. This + package is not designed to abstract this away entirely (partly for + security purposes), but rather to simply help create 'proper', clean + calls to GnuPG, and to implement key-listing parsing. Please see + "Bidirectional Communication with Another Process" in perlipc to learn + how to deal with these methods. + + Using this package to do message processing generally invovlves creating + a GnuPG::Interface object, creating a GnuPG::Handles object, setting + some options in its options data member, and then calling a method which + invokes GnuPG, such as clearsign. One then interacts with with the + handles appropriately, as described in "Bidirectional Communication with + Another Process" in perlipc. + +GnuPG Versions + As of this version of GnuPG::Interface, there are two supported versions + of GnuPG: 1.4.x and 2.2.x. The GnuPG download page + <https://gnupg.org/download/index.html> has updated information on the + currently supported versions. + + GnuPG released 2.0 and 2.1 versions in the past and some packaging + systems may still provide these if you install the default "gpg", + "gnupg", "gnupg2", etc. packages. This modules supports only version + 2.2.x, so you may need to find additional package repositories or build + from source to get the updated version. + +OBJECT METHODS + Initialization Methods + new( *%initialization_args* ) + This methods creates a new object. The optional arguments are + initialization of data members. + + hash_init( *%args* ). + + Object Methods which use a GnuPG::Handles Object + list_public_keys( % ) + list_sigs( % ) + list_secret_keys( % ) + encrypt( % ) + encrypt_symmetrically( % ) + sign( % ) + clearsign( % ) + detach_sign( % ) + sign_and_encrypt( % ) + decrypt( % ) + verify( % ) + import_keys( % ) + export_keys( % ) + recv_keys( % ) + send_keys( % ) + search_keys( % ) + These methods each correspond directly to or are very similar to a + GnuPG command described in gpg. Each of these methods takes a hash, + which currently must contain a key of handles which has the value of + a GnuPG::Handles object. Another optional key is command_args which + should have the value of an array reference; these arguments will be + passed to GnuPG as command arguments. These command arguments are + used for such things as determining the keys to list in the + export_keys method. *Please note that GnuPG command arguments are + not the same as GnuPG options*. To understand what are options and + what are command arguments please read "COMMANDS" in gpg and + "OPTIONS" in gpg. + + Each of these calls returns the PID for the resulting GnuPG process. + One can use this PID in a "waitpid" call instead of a "wait" call if + more precise process reaping is needed. + + These methods will attach the handles specified in the handles + object to the running GnuPG object, so that bidirectional + communication can be established. That is, the optionally-defined + stdin, stdout, stderr, status, logger, and passphrase handles will + be attached to GnuPG's input, output, standard error, the handle + created by setting status-fd, the handle created by setting + logger-fd, and the handle created by setting passphrase-fd + respectively. This tying of handles of similar to the process done + in *IPC::Open3*. + + If you want the GnuPG process to read or write directly to an + already-opened filehandle, you cannot do this via the normal + *IPC::Open3* mechanisms. In order to accomplish this, set the + appropriate handles data member to the already-opened filehandle, + and then set the option direct to be true for that handle, as + described in "options" in GnuPG::Handles. For example, to have GnuPG + read from the file input.txt and write to output.txt, the following + snippet may do: + + my $infile = IO::File->new( 'input.txt' ); + my $outfile = IO::File->new( '>output.txt' ); + my $handles = GnuPG::Handles->new( stdin => $infile, + stdout => $outfile, + ); + $handles->options( 'stdin' )->{direct} = 1; + $handles->options( 'stdout' )->{direct} = 1; + + If any handle in the handles object is not defined, GnuPG's input, + output, and standard error will be tied to the running program's + standard error, standard output, or standard error. If the status or + logger handle is not defined, this channel of communication is never + established with GnuPG, and so this information is not generated and + does not come into play. + + If the passphrase data member handle of the handles object is not + defined, but the the passphrase data member handle of + GnuPG::Interface object is, GnuPG::Interface will handle passing + this information into GnuPG for the user as a convenience. Note that + this will result in GnuPG::Interface storing the passphrase in + memory, instead of having it simply 'pass-through' to GnuPG via a + handle. + + If neither the passphrase data member of the GnuPG::Interface nor + the passphrase data member of the handles object is defined, then + GnuPG::Interface assumes that access and control over the secret key + will be handled by the running gpg-agent process. This represents + the simplest mode of operation with the GnuPG "stable" suite + (version 2.2 and later). It is also the preferred mode for tools + intended to be user-facing, since the user will be prompted directly + by gpg-agent for use of the secret key material. Note that for + programmatic use, this mode requires the gpg-agent and pinentry to + already be correctly configured. + + Other Methods + get_public_keys( @search_strings ) + get_secret_keys( @search_strings ) + get_public_keys_with_sigs( @search_strings ) + These methods create and return objects of the type GnuPG::PublicKey + or GnuPG::SecretKey respectively. This is done by parsing the output + of GnuPG with the option with-colons enabled. The objects created do + or do not have signature information stored in them, depending if + the method ends in *_sigs*; this separation of functionality is + there because of performance hits when listing information with + signatures. + + test_default_key_passphrase() + This method will return a true or false value, depending on whether + GnuPG reports a good passphrase was entered while signing a short + message using the values of the passphrase data member, and the + default key specified in the options data member. + + version() + Returns the version of GnuPG that GnuPG::Interface is running. + +Invoking GnuPG with a custom call + GnuPG::Interface attempts to cover a lot of the commands of GnuPG that + one would want to perform; however, there may be a lot more calls that + GnuPG is and will be capable of, so a generic command interface is + provided, "wrap_call". + + wrap_call( %args ) + Call GnuPG with a custom command. The %args hash must contain at + least the following keys: + + commands + The value of this key in the hash must be a reference to a a + list of commands for GnuPG, such as "[ qw( --encrypt --sign ) + ]". + + handles + As with most other GnuPG::Interface methods, handles must be a + GnuPG::Handles object. + + The following keys are optional. + + command_args + As with other GnuPG::Interface methods, the value in hash for + this key must be a reference to a list of arguments to be passed + to the GnuPG command, such as which keys to list in a + key-listing. + +OBJECT DATA MEMBERS + call + This defines the call made to invoke GnuPG. Defaults to 'gpg'; this + should be changed if 'gpg' is not in your path, or there is a + different name for the binary on your system. + + passphrase + In order to lessen the burden of using handles by the user of this + package, setting this option to one's passphrase for a secret key + will allow the package to enter the passphrase via a handle to GnuPG + by itself instead of leaving this to the user. See also "passphrase" + in GnuPG::Handles. + + options + This data member, of the type GnuPG::Options; the setting stored in + this data member are used to determine the options used when calling + GnuPG via *any* of the object methods described in this package. See + GnuPG::Options for more information. + +EXAMPLES + The following setup can be done before any of the following examples: + + use IO::Handle; + use GnuPG::Interface; + + my @original_plaintext = ( "How do you doo?" ); + my $passphrase = "Three Little Pigs"; + + my $gnupg = GnuPG::Interface->new(); + + $gnupg->options->hash_init( armor => 1, + recipients => [ 'ftobin@uiuc.edu', + '0xABCD1234ABCD1234ABCD1234ABCD1234ABCD1234' ], + meta_interactive => 0 , + ); + + $gnupg->options->debug_level(4); + + $gnupg->options->logger_file("/tmp/gnupg-$$-decrypt-".time().".log"); + + Encrypting + # We'll let the standard error of GnuPG pass through + # to our own standard error, by not creating + # a stderr-part of the $handles object. + my ( $input, $output ) = ( IO::Handle->new(), + IO::Handle->new() ); + + my $handles = GnuPG::Handles->new( stdin => $input, + stdout => $output ); + + # this sets up the communication + # Note that the recipients were specified earlier + # in the 'options' data member of the $gnupg object. + my $pid = $gnupg->encrypt( handles => $handles ); + + # this passes in the plaintext + print $input @original_plaintext; + + # this closes the communication channel, + # indicating we are done + close $input; + + my @ciphertext = <$output>; # reading the output + + waitpid $pid, 0; # clean up the finished GnuPG process + + Signing + # This time we'll catch the standard error for our perusing + my ( $input, $output, $error ) = ( IO::Handle->new(), + IO::Handle->new(), + IO::Handle->new(), + ); + + my $handles = GnuPG::Handles->new( stdin => $input, + stdout => $output, + stderr => $error, + ); + + # indicate our pasphrase through the + # convenience method + $gnupg->passphrase( $passphrase ); + + # this sets up the communication + my $pid = $gnupg->sign( handles => $handles ); + + # this passes in the plaintext + print $input @original_plaintext; + + # this closes the communication channel, + # indicating we are done + close $input; + + my @ciphertext = <$output>; # reading the output + my @error_output = <$error>; # reading the error + + close $output; + close $error; + + waitpid $pid, 0; # clean up the finished GnuPG process + + Decryption + # This time we'll catch the standard error for our perusing + # as well as passing in the passphrase manually + # as well as the status information given by GnuPG + my ( $input, $output, $error, $passphrase_fh, $status_fh ) + = ( IO::Handle->new(), + IO::Handle->new(), + IO::Handle->new(), + IO::Handle->new(), + IO::Handle->new(), + ); + + my $handles = GnuPG::Handles->new( stdin => $input, + stdout => $output, + stderr => $error, + passphrase => $passphrase_fh, + status => $status_fh, + ); + + # this time we'll also demonstrate decrypting + # a file written to disk + # Make sure you "use IO::File" if you use this module! + my $cipher_file = IO::File->new( 'encrypted.gpg' ); + + # this sets up the communication + my $pid = $gnupg->decrypt( handles => $handles ); + + # This passes in the passphrase + print $passphrase_fh $passphrase; + close $passphrase_fh; + + # this passes in the plaintext + print $input $_ while <$cipher_file>; + + # this closes the communication channel, + # indicating we are done + close $input; + close $cipher_file; + + my @plaintext = <$output>; # reading the output + my @error_output = <$error>; # reading the error + my @status_info = <$status_fh>; # read the status info + + # clean up... + close $output; + close $error; + close $status_fh; + + waitpid $pid, 0; # clean up the finished GnuPG process + + Printing Keys + # This time we'll just let GnuPG print to our own output + # and read from our input, because no input is needed! + my $handles = GnuPG::Handles->new(); + + my @ids = ( 'ftobin', '0xABCD1234ABCD1234ABCD1234ABCD1234ABCD1234' ); + + # this time we need to specify something for + # command_args because --list-public-keys takes + # search ids as arguments + my $pid = $gnupg->list_public_keys( handles => $handles, + command_args => [ @ids ] ); + + waitpid $pid, 0; + + Creating GnuPG::PublicKey Objects + my @ids = [ 'ftobin', '0xABCD1234ABCD1234ABCD1234ABCD1234ABCD1234' ]; + + my @keys = $gnupg->get_public_keys( @ids ); + + # no wait is required this time; it's handled internally + # since the entire call is encapsulated + + Custom GnuPG call + # assuming $handles is a GnuPG::Handles object + my $pid = $gnupg->wrap_call + ( commands => [ qw( --list-packets ) ], + command_args => [ qw( test/key.1.asc ) ], + handles => $handles, + ); + + my @out = <$handles->stdout()>; + waitpid $pid, 0; + +FAQ + How do I get GnuPG::Interface to read/write directly from a filehandle? + You need to set GnuPG::Handles direct option to be true for the + filehandles in concern. See "options" in GnuPG::Handles and "Object + Methods which use a GnuPG::Handles Object" for more information. + + Why do you make it so difficult to get GnuPG to write/read from a + filehandle? In the shell, I can just call GnuPG with the --outfile + option! + There are lots of issues when trying to tell GnuPG to read/write + directly from a file, such as if the file isn't there, or there is a + file, and you want to write over it! What do you want to happen + then? Having the user of this module handle these questions + beforehand by opening up filehandles to GnuPG lets the user know + fully what is going to happen in these circumstances, and makes the + module less error-prone. + + When having GnuPG process a large message, sometimes it just hanges + there. + Your problem may be due to buffering issues; when GnuPG reads/writes + to non-direct filehandles (those that are sent to filehandles which + you read to from into memory, not that those access the disk), + buffering issues can mess things up. I recommend looking into + "options" in GnuPG::Handles. + +NOTES + This package is the successor to PGP::GPG::MessageProcessor, which I + found to be too inextensible to carry on further. A total redesign was + needed, and this is the resulting work. + + After any call to a GnuPG-command method of GnuPG::Interface in which + one passes in the handles, one should all wait to clean up GnuPG from + the process table. + +BUGS + Large Amounts of Data + Currently there are problems when transmitting large quantities of + information over handles; I'm guessing this is due to buffering issues. + This bug does not seem specific to this package; IPC::Open3 also appears + affected. + + OpenPGP v3 Keys + I don't know yet how well this module handles parsing OpenPGP v3 keys. + + RHEL 7 Test Failures + Testing with the updates for version 1.00 we saw intermittent test + failures on RHEL 7 with GnuPG version 2.2.20. In some cases the tests + would all pass for several runs, then one would fail. We're unable to + reliably reproduce this so we would be interested in feedback from other + users. + +SEE ALSO + GnuPG::Options, GnuPG::Handles, GnuPG::PublicKey, GnuPG::SecretKey, gpg, + "Bidirectional Communication with Another Process" in perlipc + +LICENSE + This module is free software; you can redistribute it and/or modify it + under the same terms as Perl itself. + +AUTHOR + GnuPG::Interface is currently maintained by Best Practical Solutions + <BPS@cpan.org>. + + Frank J. Tobin, ftobin@cpan.org was the original author of the package. + |