I have a small string of some data (less than 1kb) that I would like to have user agents pass to other sites when they are sent from my site. In order for the other sites to verify that I was the one that created the string I though of two options.
- The server pings me back to confirm (like paypal, openid, etc..)
- I use public/private keys to prove I sent the message (like PGP, DKIM, etc..)
I don't want to setup HMAC because that would mean I have to use custom keys for each site which would be a pain.
Out of those two choices it seems that #2 would save on bandwidth which makes it seem like a better choice.
So how can you setup public/private key cryptography using PHP and are there any downsides?
Creating a private and public key pair using the PHP Openssl functions:
You can then encrypt and decrypt using the private and public keys like this:
Rule 1: Don't implement it yourself, use a library.
Which library? Here are my recommended PHP public-key cryptography libraries:
In general, you'll want libsodium if security is your goal. Whether or not you use Halite is a matter of taste.
I've written an example of encrypting and decrypting with openSSL in PHP and Python
http://glynrob.com/php/hashing-and-public-key-encryption/
Github source code available.
Dont forget that the private key needs to be available at the location of decryption for this to work.
I would create S/MIME public/private keypairs using OpenSSL and then use the OpenSSL command to do the encryption & decryption. I believe that this is superior to using PGP because openssl is included with most linux operating systems and PGP isn't. OpenSSL is also standards-based and generally easier to work with, once you have the commands down.
I recommended against a "pure-PHP" solution (by pure-PHP I mean doing the crypto in PHP, rather than using PHP to call an existing library or a separate executable). You don't want to do bulk crypto in PHP. Too slow. And you want to use OpenSSL, because it's high performance and the security is well understood.
Here's the magic.
To make an X.509 key:
That puts the private key in mycert.key and the public key in mycert.pem. The private key is not password protected.
Now, to sign a message with S/MIME:
To encrypt a message with S/MIME:
To decrypt a message with S/MIME:
I also have some demos on using OpenSSL from the C language bindings, but not from PHP.
PGP is a good option - it is implemented properly and completely (i.e. you have little room for security mistakes with PGP). I think this SO question will help you with interfacing with GnuPG. The question is whether and how the other sites will verify your signature. You need to either conform to their verification mechanism requirements or provide your own module that those sites will use for verification.
Also it's possible that you can use OAuth or OpenID to identify users on those other sites, but I am not an expert in these technologies.