Beefy Boxes and Bandwidth Generously Provided by pair Networks
Problems? Is your data what you think it is?
 
PerlMonks  

Getting Started with GnuPG and GPG

by derby (Abbot)
on Mar 18, 2002 at 15:25 UTC ( [id://152489]=perltutorial: print w/replies, xml ) Need Help??

Since there have been enough posts to this fine site asking about encryption, I thought a nice tutorial would be appropriate. This tutorial will start of with a general overview of security, move into an overview of cryptography and then specifically demonstrate how to set up and use GnuPG and GPG.

Security

Encryption alone will not solve your security concerns. Too many people believe that encryption will magically make their data safe and secure. Not so. In the security realm, security is often described as an onion. The layers as a whole are the true security and each individual layer will always have issues and problems. You can have the largest encryption key and the best algorithm but store that key in a weak container and you're screwed. So before you proceed implementing encryption, ensure you're firewalls are up-to-date, ensure your OS is patched with the latest and greatest and ensure the people working with your data are trustworthy.

Encryption

To encrypt data is simply to jumble it up so others cannot read it without doing some extra work. There are two parts of most encryption systems - the key and the algorithm - the batman and robin of encryption (or is that robin and batman?).

In symmetric encryption the key is shared by both the sender and the receiver. DES is the most widely used symmetric encryption algorithm. While better that storing/sending in plaintext, symmetric has one big problem - how do you share the key? Anyway you think about it, that key is one big Achille's heel. You either have to pass it out of band (can be difficult and time consuming) or you have to wrap it in another encryption which really just pushes the issues to the wrapper.

In asymmetric encryption (aka public key), the key is not shared. Each user has two keys - a public key and a private key. These two keys are mathematically related in such a way that if another user encrypts using my public key then only my private key can decrypt it. There are a lot of other things going on but that's the crux of the situation. With asymmetric cryptography, we have to worry less about the distribution of the key. (But we should still worry - remember the onion).

GnuPG

GnuPG is an implementation of asymmetric cryptography. More to the point, it's an implementation of RFC 2440 which describes the OpenPG standard which was derived from the work of Phil Zimmerman (another implementation is OpenPGP). I strongly recommend reading the The GNU Privacy Handbook from start to finish. It's available in six languages and is extremely informative.

Installing GnuPG

The folks at GnuPG have made it easy and provide GnuPG as either source(tar, debian archive, or mac archive), or precompiled (MS-Windows 95/98/NT). Once you install GnuPG, just follow the Privacy Handbook on how to create your newpairs (private and public keys). This will create .gnupg file in your home directory. Remember the onion? Be sure to not expose this directory and it's contents in an unreasonable fashion. You can do all types of fun stuff putting extra layers on top of the directory. Move it to a floppy or burn it on a cd and then remove it from the filesystem and lock it in a safe (not always practical but you get the picture).

Once you have GnuPG installed and keys generated, you can do all types of encrypting and decrypting - but only for yourself. You need to get some other keys so you can communicate with others. If you're going to use GnuPG with the outside, you need to build your web of trust. If you're going to be using it by yourself, generate another keypair (as another user) and then exchange keys (that is, if you trust yourself).

update: Of course, you can use a single keypair if you just wish to encrypt/ decrypt stuff for yourself. I was going to give more examples of using GnuPG/GPG in a web environment where the user running the httpd process would encrypt data with the public key of another user. This would have been a good example of another layer of security. If the web user is compromised, the data is still fairly secure because it's encrypted with the other user's keys and that keyring is stored in a safe somewhere and only brought out to run reports (isn't it?).

GPG

There are several cpan modules that interface with GnuPG (and still more with OpenPGP). For simplicity, I prefer GPG. It's the easiest to start with. GPG utilizes IPC::Open3 to communicate directly with the GnuPG executable. That does have it's drawbacks but doesn't everything?

For example, let's say you created two users - alice and bob. Here's two simple scripts. One where alice encrypts a message for bob, the other where bob decrypts it.

alice.pl

#!/usr/bin/perl -w use strict; use Carp; use GPG; my( $gpg ) = new GPG( homedir => "/home/alice/.gnupg" ); croak $gpg->error() if $gpg->error(); my( $enc ) = $gpg->encrypt( "Can you read this", "bob\@dot.com" ); croak $gpg->error() if $gpg->error(); print $enc;

Which is rougly equivalent to the gpg command:

gpg --encrypt --recipient bob@dot.com

This will produce something like this:

-----BEGIN PGP MESSAGE----- Comment: For info see http://www.gnupg.org hQEOA9QD1LpROcE4EAQAg1EHC7h2n6ziXat276UZXrMsMkmYp5CUJx7DFgEMrOcm RjGcvF52HRBVjNiiiICN2PohAjWY3ZPCrzS0gALSkHIKQsRW+9eF5sCILtQCUERm Zls10oPsuSyGM1nrkfd84t9G3QrlJI7ojUAtzD9CFbQOUm/CFWF0Xn7vVSDfNckD /iG43Irj4GmHy5IWclXveZmYe/Z6jSxfwJhn2YqL4ihyRchXIWIykESoaBQSR9rt 0WUo+h0dbbWK2/NoC3kzfj3IbM2VvHnuGh4jgL8C8FcwFkypzuoP+h5RJesc1H+l XHJZBYCZN4y4+YLgSqtlgZBFZMy/PpLFi3smSiqj3HyV0kwB7FJjMswEyRhiAEbc 9+DMW0Y6m/V9NZ92ORjLBvKmjz/UoLOlHqhA/OR5knD3nn6IJu5OZHXt+IUEUhYC QnM+Zs1Rug+v6lYBCpN7 =Rjs4 -----END PGP MESSAGE-----

Send that to bob and he can decrypt it like so:

bob.pl

#!/usr/bin/perl -w use strict; use Carp; use GPG; my( $gpg ) = new GPG( homedir => "/home/bob/.gnupg" ); croak $gpg->error() if $gpg->error(); my($text) = join( "", <> ); my( $dec ) = $gpg->decrypt( BOBS_PASSPHRASE, $text ); croak $gpg->error() if $gpg->error(); print $dec;

Which produces:

Can you read this

note: I leave how to get the bob's passphrase as an exercise. Just remember the passphrase is the Achilles heel of GnuPG - lose it and you've lost your ability to decrypt records (or worse, you've given someone else the opportunity to read your data). Write it down, seal it in an envelope and lock it in a safe and have dual control to open it up (remember - onion).

Conclusion and Resources

That should get you started on using GnuPG with GPG. There are many other things to consider. First and foremost, read The GNU Privacy Handbook. Also, take a look at Bruce Schneier's Crypto-gram newsletters. And read his book Applied Cryptography. Some may find that book a hard read (especially if you're weak on mathematics). A more approachable first book is Network Security - PRIVATE Communication in a PUBLIC World. Also many thanks to all those who labored on works like PGP and GnuPG when it was an extremely scary time to work on crypto in the US.

Replies are listed 'Best First'.
Re: Getting Started with GnuPG and GPG
by jaf0faj (Novice) on Mar 13, 2012 at 13:10 UTC

    OK, I have been banging my head over the last little while trying to get GPG working through PERL and finally came across this gem of a tutorial. Thank you!

    My only issue is that I still cannot get it to work. In an attempt to emulate the tutorial on my machine, I created two scripts trialencode and trialdecode, listed here

    ################# ## trialencode ## ################# use strict; use GPG; my $gpg = new GPG(homedir => '/home/jaf/.gnupg'); my $plain="ARGHH!!"; my $phrase=$gpg->encrypt($plain,"jaf0faj\@xxxxxxx"); die $gpg->error() if $gpg->error(); print "Plain: $plain\n\nEncoded:\n$phrase\n"; open (OUT, ">trialencoded"); print OUT $phrase; close (OUT);
    ################# ## trialdecode ## ################# use strict; use GPG; my $gpg = new GPG(homedir => '/home/jaf/.gnupg'); open (IN, "trialencoded"); my $phrase=join("",<IN>); close(IN); my $message=$gpg->decrypt('HtfdIggtw?',$phrase); print "\n==========================\n\nEncoded:\n$phrase\n\nDecoded: [ +$message]\n"; print "\n\n\$gpg->error message: ".$gpg->error() if $gpg->error();

    When I run them consecutively via "perl trialencode && perl trialdecode" encoding works fine, but decoding fails. Here is the output from this:

    Plain: ARGHH!!

    Encoded:
    -----BEGIN PGP MESSAGE-----

    hIwDZMVp08Pd6AkBA/9RMIUI66urMEDQXgwgaQC6K4u2v5RCt8N7iMW/a+W5xnWI
    ZTInl912BtPs/KZTJvfDEjkjqSc0vrzPZzoT2EMDgjwwPh+uNe2z8PHFALTDUGpb
    x+EfIi0etb+4QlWL+MkHFoIeB1ZgTb2zEz7sIndrUEBf2MqF3mpZyrFISdAJPNJC
    AaS/x6aTC1hRIs0kYjf9m/laq29bebfsZUPEUR9fDuQeR8bD6KVEn3TT+7Chlv7E
    a7Uh1x041RlG/BTareLke0qq
    =0kR7
    -----END PGP MESSAGE-----

    ==========================

    Encoded:
    -----BEGIN PGP MESSAGE-----

    hIwDZMVp08Pd6AkBA/9RMIUI66urMEDQXgwgaQC6K4u2v5RCt8N7iMW/a+W5xnWI
    ZTInl912BtPs/KZTJvfDEjkjqSc0vrzPZzoT2EMDgjwwPh+uNe2z8PHFALTDUGpb
    x+EfIi0etb+4QlWL+MkHFoIeB1ZgTb2zEz7sIndrUEBf2MqF3mpZyrFISdAJPNJC
    AaS/x6aTC1hRIs0kYjf9m/laq29bebfsZUPEUR9fDuQeR8bD6KVEn3TT+7Chlv7E
    a7Uh1x041RlG/BTareLke0qq
    =0kR7
    -----END PGP MESSAGE-----

    Decoded: []

    $gpg->error message: gpg: encrypted with 1024-bit RSA key, ID C3DDE809, created 2012-03-13
    "Jaf O Faj (Testing sundry perl GPG packages) <jaf0faj@xxxxxxx>"


    What am I doing wrong? BTW, if I perform a "gpg --decrypt trialencoded on the command line, where trialencoded is the dump of the encoded phase generated in trialencode, gpg successfully decodes the text, as shown below (using HtfdIggtw? as the passphrase for the secret key)!

    gpg --decrypt trialencoded

    You need a passphrase to unlock the secret key for
    user: "Jaf O Faj (Testing sundry perl GPG packages) <jaf0faj@xxxxxxx>"
    1024-bit RSA key, ID C3DDE809, created 2012-03-13 (main key ID B5A7838C)

    gpg: encrypted with 1024-bit RSA key, ID C3DDE809, created 2012-03-13
    "Jaf O Faj (Testing sundry perl GPG packages) <jaf0faj@xxxxxxx>"
    ARGHH!!

      Wow! I don't know what's more amazing ... a question about a decade old post, the fact that the monastery is still here after ten years, or that I'm still here to answer it.

      The problem is GPG has not been updated in a dozen years but gpg has. Looks like the underlying options to the gpg command

      --batch --no-comment --no-version
      are no longer sufficient to keep non-error messages off of STDERR. GPG interpets anything on STDERR as an error and will not return the output
      $this->error($error) and return if $error; return $output;

      So ... the real solution is to use a newer module (maybe GnuPG -- but I haven't really looked into it). But ... if you're feeling hacky, you can always modify GPG to use the --quiet option and that should prevent information on STDERR from blocking the decrypt.

      -derby

        Excellent! I did hack the GPG.pm by inserting the --quiet option and gave it a go...works brilliantly. Thanks again for this. Now, if only I could get Crypt::OpenPGP to work....

        I have no problem with this posting being here ... it's a question about the tutorial.

        -derby

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perltutorial [id://152489]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others imbibing at the Monastery: (5)
As of 2024-03-28 23:42 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found