Easy Blowfish Text Encryption

All security considerations aside, text encryption is great just for keeping curious editors out of a plain text file. Case of point: I build XML driven Flash games. While I don’t necessarily care if a player “looks under the hood” at the XML data, I would rather that they not try to cheat gameplay by manually tweaking XML configuration. So, a quick encryption of the XML works great to impede manual edits.

So, I’ve always turned to Blowfish for a quick encryption. Blowfish is a two-way cipher that can both encrypt and decrypt text. And thankfully, the fine folks at the AS3 Crypto project on Google code have included an AS3 implementation of the algorithm as part of their open source library. However, the AS3 Crypto library is pretty extensive; and likewise, it takes some extensive research to figure out all the parts and pieces. In my case, I wasn’t so worried about security as I was about having something easy that would generate an encryption. So, I put together this utility class which exposes a simple interface to the Blowfish algorithm and only imports the necessary library items (this import amounts to 11Kb, rather than the 40Kb of the full AS3 Crypto library). You’ll need to download the AS3 Crypto library to go with this utility class.

package
{
 import com.hurlant.util.Base64;
 import com.hurlant.crypto.symmetric.PKCS5;
 import com.hurlant.crypto.symmetric.ECBMode;
 import com.hurlant.crypto.symmetric.BlowFishKey;
 import com.hurlant.crypto.symmetric.ICipher;
 import com.hurlant.crypto.symmetric.IPad;
 import flash.utils.ByteArray;

 public class Blowfish
 {
 /**
 * Encrypts a string.
 * @param text  The text string to encrypt.
 * @param key  A cipher key to encrypt the text with.
 */
 static public function encrypt($text:String, $key:String=""):String
 {
 try
 {
 var $output:ByteArray = new ByteArray();
 $output.writeUTF($text);
 var $pad:IPad = new PKCS5();
 var $cipher:ICipher = _getCipher( $key, $pad );
 $pad.setBlockSize( $cipher.getBlockSize() );
 $cipher.encrypt( $output );
 $cipher.dispose();
 return Base64.encodeByteArray( $output );
 }
 catch ($error:Error)
 {
 trace("An encryption error occured.");
 }
 return null;
 }

 /**
 * Decrypts an encrypted string.
 * @param text  The text string to decrypt.
 * @param key  The key used while originally encrypting the text.
 */
 static public function decrypt($text:String, $key:String=""):String
 {
 try
 {
 var $input:ByteArray = Base64.decodeToByteArray( $text );
 var $pad:IPad = new PKCS5();
 var $cipher:ICipher = _getCipher( $key, $pad );
 $pad.setBlockSize( $cipher.getBlockSize() );
 $cipher.decrypt( $input );
 $cipher.dispose();
 $input.position = 0;
 return $input.readUTF();
 }
 catch ($error:Error)
 {
 trace("A decryption error occured.");
 }
 return null;
 }

 /** @private builds a Blowfish cipher algorithm. */
 private static function _getCipher( $key:String, $pad:IPad ):ICipher {
 return new ECBMode( new BlowFishKey(Base64.decodeToByteArray( $key )), $pad );
 }
 }
}

Implementation of this Blowfish utility class is extremely easy. Just import the class, then call its static encrypt() and decrypt() methods. The first param of each method is the text to encrypt, and the second params are the encryption key. When decrypting text, you must provide the same key that the text was originally encrypted with. Here’s a sample implementation:

import Blowfish;
var $key:String = "lockme";
var $encryption:String = Blowfish.encrypt("Don't read this text!", $key);

trace( $encryption );
// return: "sm63oSsAgk0T8TWad0vjRMv5KV7COH80"

trace( Blowfish.decrypt($encryption, $key) );
// return: "Don't read this text!"

11 comments so far

  1. ethan on

    Could you provide an xml example? I don’t see how this would prevent someone from decompiling the swf and browsing to the xml path. Unless the path was encrypted. But they could still see it. I must be missing something.

    • bigmac on

      The path to the XML is not what’s being encrypted… just encrypt the actual text within the XML file itself. So, while the external file has an extension of “.xml”, when you open that file you see nothing but gibberish. When loading that file into Flash, you just decrypt the text and then parse it as XML. While user may still locate and open that XML file, there will be no plain-text within it that might tempt them to make their own “modifications”.

  2. ethan on

    I guess i dont understand the order of operations here. How do you keep the XML editable and still have it scrambled when you browse to it?

  3. ethan on

    any clues? anyone?

    • mike on

      You would most likely keep your own version of this file for easy manipulation. That way you can edit it and make the changes you need. When you move your game to production you wont want to change the XML anymore so you secure it by encrypting the contents of it. This means that if users intercepts the XML, it just appears as random characters. The process from start to finish would be as follows. You create the game and the XML in plain text, once you decide to make the game public, you encrypt the XML file. When you encrypt the file, you will also need to allow Flash to decrypt the file so that is may read the XML properly as XML. This method works well unless your user can decompile the SWF file and find out the type of encryption (i.e. blowfish) and the encryption key. The process of decompilation is more difficult than just looking at a plain text file and may be thwarted further by obsfuscation techniques and sub-encryption of string literals. Each encryption/decryption does come at a performance cost however I do not know how much. Hopefully this clears somethings up. Thanks for the post.

  4. sam on

    the pain-in-the-ass solution is to store your editable xml offline and encrypt / upload a new copy of the encrypted xml every time you make a change; it’s a simple setup but sucks to implement if you make changes often.

    I did, however, run across this article: http://www.squidder.com/2010/04/23/auto-encrypt-assets-for-flash/ , which I have not tried but appears, at least theoretically, to be secure.

  5. julifos on

    As I understand it, you should keep two copies of your XML file. The “real.xml” one you can edit as usually (in a text editor). And the “encrypted.xml” one, which is the one you read from within your swf file. It contains the encrypted representation of “real.xml”. Your swf reads that, unencrypts and parses it as a XML doc.

  6. Angelo on

    It’s just fine your class! Thank you.

    I’d make only a couple of changes: I’d use writeUTFBytes() and readUTFBytes() instead of writeUTF() and readUTF().

    The function _getCipher would look like this:

    {
    var $output:ByteArray = new ByteArray();
    $output.writeUTFBytes($key);
    return new ECBMode( new BlowFishKey($output), $pad );
    }

  7. Elias on

    Thank You!

  8. Sebastjan on

    A project saver!! Thank you!

  9. […] on work of the extensive AS3 Crypto class, the simple Blowfish Encryption class from Lassie games, and also the Binary XML class from Ghostwire, we’ve created a tool which […]


Leave a comment