In the past, the ability to encrypt information with relative
strength
could be found only in the realms of governments. Thanks to a
gentleman named
Phil Zimmerman, this ability has been brought to the masses. In
1991 Mr.
Zimmerman invented Pretty Good Privacy or PGP for short. PGP was
designed to
be high-grade encryption software available for free to anyone who
wished to
use it.
One of the major aspects of PGP is that it utilizes
“Public-Key
Encryption”. In a nutshell, that means that you actually have two
keys: a
Private Key that only you should have access to and a Public Key that
you
give away to anyone you want. When someone wants to send you an
encrypted
file, they use your Public Key to encrypt the file. Having done
that, the
encrypted file can then only be decrypted by you using your
Private
Key.
One way to think of Public-Key Encryption is someone sending
you a snail
mail letter in an envelope that only you can open. Anyone can see
the
envelope but only you can read its contents.
Because of the US Government’s restrictions on exporting high-grade
encryption
technology, giving PGP to people outside the US was illegal.
Because of this a
team of programmers lead by Werner Koch in Germany took it
upon themselves to
write an Open Source, RFC2440 (OpenPGP) alternative to PGP
called GNU Privacy
Guard, or GnuPG. Because GnuPG was developed outside of
the US the export restrictions
didn’t apply. It should be noted that PGP and
GnuPG are virtually identical (with
a few exceptions) so, in the
interest
of Open Source and keeping people out of prison, we will be using GnuPG
in
this article.
As with most Unix-based command-line utilities you first call the
gpg
command followed by switches that affect the output of the utility. For
example,
to encrypt a file called “my_secret_data.txt” you would call GnuPG
with the -ecommand to encrypt followed by the
-r
NAME
to tell GnuPG who
should be able to decrypt the file. “NAME” in
this instance is the first name
or email address of the person who will be
receiving the encrypted file. (Note
that the user indicated by NAME must be
in your public key ring and can be obtained
by typing gpg
–list-keys
).
Here it is in action:
$ gpg -e -r john@doe.com my_secret_file.txt
Once this is done you will a file called
‘my_secret_file.txt.gpg’ in your
current directory. Any attempts to view the
contents of this file will prove
futile unless you encrypted it using your own
Public Key. Feeling like a
secret agent yet?
Now suppose Mr. John Doe has encrypted a file and sent it to you. To
decrypt
it you simply use the -d
switch followed by the
encrypted file.
$ gpg -d john_doe_secret_file.txt.gpg
Since you have your private key contained within your secret
key ring
GnuPG can determine whom ‘john_doe_secret_file.txt.gpg’ was intended
for and
will decrypt it after you provide your passphrase.
All in all, this is pretty simple stuff huh? Let’s take the next step of
using
GnuPG within a PHP script.
Encrypting files from within PHP
Now things get a
little tricky. Quite often your PHP scripts
are written to run automatically
within the web server without any intervention
by you. What kind of life can
you expect to lead if you have to enter your
GnuPG passphrase every time PHP
tries to decrypt a file? But we’re getting a
little ahead of ourselves. Let’s
first look at how we can encrypt a file with
GnuPG and PHP.
The following script does just that:
$gpg = '/usr/bin/gpg';
$recipient = 'john@doe.com';
$secret_file = 'secret_file.txt';
echo shell_exec("$gpg -e -r $recipient $secret_file");
?>
After running this script you will find ‘secret_file.txt.gpg’
in your
directory (Again, make sure ‘john@doe.com’ is in your public key ring!).
This
is assuming that GnuPG generated no errors. If it did then they will
be
echoed to STDOUT.
From here there are several things you can do. For one, if there are any
errors
you probably want to look for them within the script instead of just
echoing
them for the entire world to see. You might also want to email the
encrypted
file to Mr. Doe using PHP’s mail()
command.
But what if you want to encrypt raw data not contained in a
file? This too
is possible by piping the data directly to GnuPG:
$gpg = '/usr/bin/gpg';
$recipient = 'john@doe.com';
$encrypted_file = 'foo.gpg';
shell_exec("echo $argv[1] | $gpg -e -r $recipient -o $encrypted_file");
?>
This script takes the value of
$argv[1]
, the first argument
after the
script name, and passes it to GnuPG for encrypting. GnuPG, using
the
-o
switch, writes the encrypted data
out to
$encrypted_file
. Again, you
will probably want to check for and
deal with any errors generated by
GnuPG.
Another option is to leave off the -o $encrypted_file
part
and
store the encrypted data inside a variable. That way you can use PHP to
do with
the encrypted data as you please, saving valuable file I/O.
$gpg = '/usr/bin/gpg';
$recipient = 'john@doe.com';
$encrypted_message = base64_encode(shell_exec("echo $argv[1] | $gpg -e -r $recipient"));
mail('john@doe.net',
'Your
Encrypted
Message',
$enrypted_message);
?>
If you do this is especially important that you Base-64 encode the data
so
you can play nice with the email client receiving the encrypted message.
Decrypting GnuPG Encrypted Files with PHP
Decrypting
an encrypted file with PHP and GnuPG can be a bit more complex
than
encrypting, since you are required to provide a GnuPG passphrase. The
solution
to having to type the passphrase every time the script is run lies
in a handy
little gpg switch called --passphrase-fd
. This switch
tells GnuPG
to accept the passphrase from a file descriptor, which means that
you can echo
the passphrase and pipe the output to gpg, as seen in the
following example.
$gpg = '/usr/bin/gpg';
$passphrase = 'My
secret pass phrase.';
$encrypted_file = 'foo.gpg';
$unencrypted_file = 'foo.txt';
echo shell_exec("echo $passphrase | $gpg --passphrase-fd 0 -o $unencrypted_file -d $encrypted_file");
?>
This script tells gpg to accept the passphrase from STDIN
(indicated by
the 0 following the switch) and decrypt the information into a
file named
“foo.txt”.
As with encrypting information, you can leave off
the
-o
switch to gpg and let the decrypted
data be captured
inside a variable.
It should be noted that the -o
switch should always come
before
the -d
switch.
Pitfalls
As with anything encryption related, there
are pitfalls to the
methods described in this article. The major pitfall is
in storing your
passphrase in plaintext within the script. Should your
script’s source ever
been seen without having first been processed your
supposedly secret passphrase
will no longer be secret.
A second pitfall is in the use of PHP’s shell_exec()
statement.
Since
you are executing a shell command the passphrase is available for all
to see due
to having to echo it. Don’t use this method unless you are sure
that only trusted
users are on your server!
These two pitfalls are enough to suggest you probably won’t want to use
these
methods in situations of national security, to say the least.
Alternatives
One of the best alternatives is to take
advantage of a recent project within GnuPG
called GnuPG Made Easy (GPGME).
This is a
project to develop a GnuPG programming library so that GnuPG can be
embedded
within other applications and languages such as PHP. Having GnuPG would
be a
great addition to PHP because there would no longer be a need to use
shell_exec()
when encrypting/decrypting data.
Another alternative, and one which has already been built as a PHP module,
is
Mcrypt. However,
it
shares a downside with GnuPG in that you must still store the passphrase
within
your script or database.
Conclusion
Having the ability to encrypt data can
provide a distinct advantage in this world
of script-kiddies and nosey
governments. You are encouraged to explore the power
of bringing PHP and
GnuPG together and, if you have the coding mojo, contribute
to the PHP
project by building a GnuPG module with GPGME!
Copyright © 2011 - All Rights Reserved - Softron.in
Template by Softron Technology