Secure cross-domain communication with hash functions
I love posting to remote forms. Who doesn’t? But you wanna make sure bad guys can’t post their own invalid or evil data. Here’s a little recipe that works well, and you can adapt it for just about any platform.
Let’s say I’m posting my name and email address to a PHP script on a remote server. I’m sending it from Flash in a JSON packet. The simplest, super insecure way is to just POST it to a PHP script like so:
{ “name”: “Charlie”, “email”: “me@theinternet.com” }
Here, your only security measure is to hope that nobody knows where your PHP script is. Any jerk with a hunger for chaos could post their own JSON var to this url and it would happily accept it. You could check the referrer url or ip, but that’s trivial to spoof and doesn’t add much protection. You’ll need something stronger. Enter the hash and the secret key.
Hashes are awesome. They basically generate a unique alphanumeric code from an input string that is very difficult to reverse. Easy to make, hard to break. [SHA1](http://en.wikipedia.org/wiki/SHA-1) is a common [hash function](http://en.wikipedia.org/wiki/Cryptographic_hash_function) that you can find libraries for pretty much every platform from Flash to [Arduino](http://code.google.com/p/crypto-arduino-library/source/browse/trunk/Sha1.cpp?spec=svn2&r=2).
All you need is a secret string that will live in a variable on both sides of your transaction. Let’s choose “SECRETKEY” for this example, but you should choose a better, way longer one, preferably something [randomly generated](http://random.org). Drop that into a variable in Flash. When it comes time to send your JSON packet, include an extra variable that is the SHA1 hash of your email (name works too, any other variable really) and your key combined. In this case we find the SHA1 hash of “me@theinternet.comSECRETKEY”, which happens to be “1ef64d22165900bf137be2826d60e99f62c39fa1”. Throw this in your JSON packet too, so now you’re sending:
{ “name”: “Charlie”, “email”: “me@theinternet.com”, “hash”: “1ef64d22165900bf137be2826d60e99f62c39fa1” }
There, you’re done on the client side. Drop your secret key into a variable on the server side as well. Now, when you receive a new JSON post, you can build a hash on the server side the same way you generated it on the client, and then make sure they match. Here’s a few lines of PHP that do this:
$secret_key = “SECRETKEY”; // here’s our secret key
$hash = sha1($json_packet->email . $secret_key); // get the hash of our email and key combined
if($hash != $json_packet->hash) { // if our hashes don’t match
return false; // give up
}
$hash = sha1($json_packet->email . $secret_key); // get the hash of our email and key combined
if($hash != $json_packet->hash) { // if our hashes don’t match
return false; // give up
}
So you are encrypting data with a secret key that is never transmitted between your servers. It remains safely hidden in your code. Unless your malicious user knows this key, they can’t generate JSON packets that your server will accept. The great thing about this method is that it doesn’t matter how much sniffing your enemies do on your communications, they still need to know your key to send valid data.