as3Crypto and php, what a fun ride!

Actually not so fun, but I did manage (I should say we because I wasn’t alone in this). Cryptography is not my thing, eh, not everything can be your thing so I accept it. There is just too much to learn: hash functions, public keys, symmetric ciphers, etc. Want we wanted to do was to encrypt data on the As3 side and decrypt it on the php side. I was aware that there was some cryptographic algorythms in the as3corelib, but none of them (MD5, SHA-1) fitted our needs. There is another great cryptography library out there and it is as3Crypto; the problem is that it is a bit hard to get around, there is a lot to choose from. We settled on AES (Advanced Encryption Standard). After 2 hours of trying to get it to work, we found this great post on Google groups (about middle of the page). I am copying the content here to make it easier for people to find. I have to give all the credit for this post to Jason Foglia who posted his code.

Here is the As3 Class:

 
package
{
        import flash.display.Sprite;
        import flash.utils.ByteArray;
 
        import com.hurlant.crypto.symmetric.ICipher;
        import com.hurlant.crypto.symmetric.IVMode;
        import com.hurlant.crypto.symmetric.IMode;
        import com.hurlant.crypto.symmetric.NullPad;
        import com.hurlant.crypto.symmetric.PKCS5;
        import com.hurlant.crypto.symmetric.IPad;
        import com.hurlant.util.Base64;
        import com.hurlant.util.Hex;
        import com.hurlant.crypto.Crypto;
 
        public class CryptoCode extends Sprite
        {
                private var type:String='simple-des-ecb';
                private var key:ByteArray;
 
                public function CryptoCode()
                {
                        init();
                }
 
                private function init():void
                {
                        key = Hex.toArray(Hex.fromString('TESTTEST'));// can only be 8 characters long
 
                        trace(encrypt('TEST TEST'));
                        trace(decrypt(encrypt('TEST TEST'));
                }
 
                private function encrypt(txt:String = ''):String
                {
                        var data:ByteArray = Hex.toArray(Hex.fromString(txt));
 
                        var pad:IPad = new PKCS5;
                        var mode:ICipher = Crypto.getCipher(type, key, pad);
                        pad.setBlockSize(mode.getBlockSize());
                        mode.encrypt(data);
                        return Base64.encodeByteArray(data);
                }
                private function decrypt(txt:String = ''):String
                {
                        var data:ByteArray = Base64.decodeToByteArray(txt);
                        var pad:IPad = new PKCS5;
                        var mode:ICipher = Crypto.getCipher(type, key, pad);
                        pad.setBlockSize(mode.getBlockSize());
                        mode.decrypt(data);
                        return Hex.toString(Hex.fromArray(data));
                }
        }
 
}

Here is the php class:

 
<?
class Crypt
{
        var $key = NULL;
        var $iv = NULL;
        var $iv_size = NULL;
 
        function Crypt()
        {
                $this->init();
        }
 
        function init($key = "")
        {
                $this->key = ($key != "") ? $key : "";
 
                $this->algorithm = MCRYPT_DES;
                $this->mode = MCRYPT_MODE_ECB;
 
                $this->iv_size = mcrypt_get_iv_size($this->algorithm, $this->mode);
                $this->iv = mcrypt_create_iv($this->iv_size, MCRYPT_RAND);
        }
 
        function encrypt($data)
        {
                $size = mcrypt_get_block_size($this->algorithm, $this->mode);
                $data = $this->pkcs5_pad($data, $size);
                return base64_encode(mcrypt_encrypt($this->algorithm, $this->key, $data, $this->mode, $this->iv));
        }
 
        function decrypt($data)
        {
                return $this->pkcs5_unpad(rtrim(mcrypt_decrypt($this->algorithm, $this->key, base64_decode($data), $this->mode, $this->iv)));
        }
 
        function pkcs5_pad($text, $blocksize)
        {
                $pad = $blocksize - (strlen($text) % $blocksize);
                return $text . str_repeat(chr($pad), $pad);
        }
 
        function pkcs5_unpad($text)
        {
                $pad = ord($text{strlen($text)-1});
                if ($pad > strlen($text)) return false;
                if (strspn($text, chr($pad), strlen($text) - $pad) != $pad) return false;
                return substr($text, 0, -1 * $pad);
        }
}
 
?>

Now if you use the encrypt method of one you can send the data to the other one and decrypt it in the other language if you use the same key. Works like a charm. There is a mention that the key can only be 8 characters long but I haven’t tested it out.

, , , , , , , , ,

  1. #1 by Stefano - May 2nd, 2009 at 11:58

    Thank you for this post!

    DES provide a very little ecryption protection, try and use AES with 256bit key.
    It’s the only encryption algorythm that hasn’t been broken either theorically or by brute force yet.
    Ste

  2. #2 by Tim - June 20th, 2009 at 17:34

    I was wondering how to actually use the Crypt class in PHP. My main problem is with the key passed in through the init function. Do I pass in the exact same value as the key used in CryptoCode class, in this case “TESTTEST” or do I need to convert the PHP “TESTTEST” string into another format before passing it to the Crypt->init().

    I ask because I’m unable to decrypt data being passed from ActionScript. I get a 0 back from Crypt->encrypt().

  3. #3 by Tim - June 20th, 2009 at 20:36

    Never mind, I was able to find the problem. I was not initializing the PHP Crypt key properly because I was passing the key in through the constructor not the init() function.

  4. #4 by BubbleBoy - June 23rd, 2009 at 08:31

    Thanks! Interesting. It looks to me like you are NOT using AES in this script, although you say it in the intro? Did you implement AES as well?

    Very helpful anyway! Thanks!

  5. #5 by Atin - June 29th, 2009 at 03:08

    nice post man, but i am looking for an encryption and decryption in actionscript.. i tried hurlant, DES but its not working.. the encrypted code is not decrypted with its generated encrypted code.. i also tried xor encrypt decrypt but it fails to decrypt if the text has ‘and’ in it.. looking for help if anyone knows about this..

  6. #6 by MAADMAXX - July 3rd, 2009 at 00:11

    What a great post. I’m a intermediate/novice coder – would it be possible to provide working sample code in each direction? Would be greatly appreciated.

  7. #7 by Hong - October 14th, 2009 at 15:10

    I notice the decryption is not working sometimes. I went inside and found the root of the problem.

    For function pkcs5_unpad, this modification will ensure that decryption still goes through if there is no need for unpadding.

    if (strspn($text, chr($pad), strlen($text) – $pad) != $pad) return $text; //<– return $text instead of false when there is nothign to unpad

    It works for me but I am not a crypto artist so I am not exactly sure if this is the way to go.

    Comment and keep me with the game ppl. =)

  8. #8 by Hadi - November 7th, 2009 at 16:44

    if (strspn($text, chr($pad), strlen($text) – $pad) != $pad) return $text; //<– return $text instead of false when there is nothign to unpad
    blockquote>

    it seems that I have problem with Pading also… I submit the bug in as3Crypto their issues tab #28 but will you please explain a bit more about what you’re doing above? Thanks.

  9. #9 by AlexWD - November 12th, 2009 at 00:22

    I noticed some problems as well, but it’s not on the PHP end. Rather when decrypting on the PHP end I’m getting random chars appended to the front. I put a temporary solution that makes it work for me, but I’m not sure if it’s the right way to go because I don’t know the full extent of the problem. And it’s just a half-assed fix anyway.

  10. #10 by Shane - December 14th, 2009 at 03:32

    Would be really interested in a complete working AES version of this system with all the bugs removed. I was quite shocked to find out how much time I’ve had to spend finding a system to crypt data between php and actionscript. Yet still haven’t found a strong secure way.

  11. #11 by Sascha Krot - March 15th, 2010 at 03:28

    I think I may have spotted a bug in php Crypt :: decrypt method. The thing is, if a string is padded with spaces (e.g., 11 characters are needed to pad the value), then the padding gets effectively removed by the rtrim call.
    I believe, that rtrim might actually not be needed — AS3 Crypto PKCS#5 unpad implementation does not perform any trimming.

  12. #12 by Rami - November 7th, 2010 at 17:36

    I would like to use your script but for encrypting/decrypting an SWF file then load it using the loader class, is this possible? or it only works for string based encrypting/decrypting .. if possible would you please show me a way?

    thank you

  13. #13 by haplo - January 17th, 2012 at 22:56

    php side, 1st line of init() should be:

    $this->key = ($this->key != “”) ? $this->key : “”;

  14. #14 by Marian - February 11th, 2012 at 17:23

    Encrypting in php with AES and decrypting in as3:
    http://sarakhman-lab.blogspot.com/2012/02/encryption-as3php.html

  15. #15 by tn - February 25th, 2012 at 06:19

    @haplo: I don’t think so; you’re testing if the parameter $key is blank, NOT the already-set class variable this->key

  16. #16 by tn - February 25th, 2012 at 06:22

    The last line of the init() function (in the Flash code) is missing a right bracket.

  17. #17 by tn - February 25th, 2012 at 06:36

    For extra convenience, change PHP constructor to:

    function Crypt($key = “”)
    {
    $this->init($key);
    }

    This way you don’t need to call init yourself!

    To use PHP:
    With old constructor:
    $yourCryptObj = new Crypt();
    $yourCryptObj->init(“YOURCODE”);

    then you may
    $yourCryptObj->encrypt($rawData);
    OR
    $yourCryptObj->decrypt($encryptedData);

    With my version of the constructor, the first two lines can be replaced with:
    $yourCryptObj = new Crypt(“YOURCODE”);

    One less line. Hooray!

    (PS to the moderator: sorry for the multiple successive posts. Your post was very helpful, thought I’d give back =P)

  18. #18 by pronostic PMU - March 29th, 2012 at 15:14

    Thanks for your article, I’m not a crypto roxxor too ;-) and your article save me many hours. Thanks.

  19. #19 by Claudio - September 8th, 2012 at 19:35

    I’m trying to encrypt in as3 and decrypt in php, but the php function seems to return an empty string (even with the mod suggested by Hong)

    Did someone actually have it working?

(will not be published)
Subscribe to comments feed