Secure Communication Between ActionScript and PHP

When I wanted to implement a high score table in my last game, I knew I would have to use some kind of encrypted communication between a Flash client and a server-side code, or soon someone would forge a score. If you are serious about creating a commercial Flash game, you are better off choosing one of many providers of on-line game services. Their solution scales better than your would-be implementation, has higher availability, and was thoroughly tested with thousands of implementations.

However, if you’d like to learn something new, want to create propriety secure communication, or just want to do everything by yourself, read along.

Since my web site already makes a good use of Apache, MySQL, and PHP, I needn’t think twice which server-side technology to use. It is also free, robust, and easy to use. Because I have never done any interoperability between ActionScript and PHP, let alone cryptography in any of them, I’ve turned to our best friend Google for help.

I have found out that Adobe does not provide cryptographic services in their ActionScript libraries, thus the Flash community generally uses Metal Hurlant’s as3crypto library for all its cryptographic needs. PHP on the other hand has many extensions for cryptography, mcrypt being the most feature rich and as3crypto equal. However, the common understanding is that these two libraries don’t cooperate, particularly with the AES (Rijndael) algorithm that I wanted to use, so the developers use custom implementations of the AES algorithm.

I am the last to have anything against the custom implementation, but I couldn’t believe that the libraries, which implement common algorithms and are embraced by the industry, would not cooperate. And I was right. Before I present the solution, let me address a few misconceptions that I have seen developers do when they implement secure communication.

Many implementations use the AES encryption with the ECB mode of operation, which is the simplest mode of operation and does not hide data patterns well. See the article of block cipher modes for nice visual representation of this flaw.

After the message is encrypted, it is usually Base64 encoded. This might have served a purpose early in the implementation – to easily compare binary data through ASCII representation but is unnecessary if you use binary transport.

A secret key usually consists of alphanumeric characters only. When you are creating the secret key, you should be even more paranoid than when creating a password. Use all available characters, even non-printable ones. You can use hexspeak to have a meaningful but hard-to-guess key, or create a GUID that has the same length as your 128-bit AES key. Constructing a string with special characters is easy in PHP but a pain in ActionScript. I recommend saving the key to a file and use that file in ActionScript.

Here is a sample PHP code that generates the secret key in hexspeak and saves it to the file:

$key = pack('NNNN', 0xdeadbeef, 0xcafebabe, 0xc001d00d, 0xbaadf00d);
$file = fopen('key.bin', 'wb');
fwrite($file, $key);
fclose($file);

And here is how you can use the generated key file in ActionScript:

[Embed(source="key.bin", mimeType="application/octet-stream")]
const KEY:Class;
var key:ByteArray = new KEY();

You shouldn’t use the same key for every application or even for every service within an application. The objective here is that the attacker cannot compromise all your products with one hacked secret key. Still, the attacker can inject false messages without ever knowing your secret key by reusing captured messages. You can battle this by making the key generation dynamic and exchange keys between the server and the client on a regular basis. Keep in mind that these methods only make it hard for the attacker to guess your secret key or reuse the messages. You are defenceless if the attacker decompiles your ActionScript code. Only code obfuscation and a complex state machine will keep most attackers at bay.