Sunday, February 14, 2010

Flex Asynchronous Ciphering using as3crypto

Built myself a little password safe application based on Adobe AIR, and one of the features I wanted to put into it was to store encrypted files. I downloaded the as3crypto package from google code, and had my encryption/decryption functionality ready and working in an hour.

It was working smoothly right until I tries to use  it on a slightly larger file (a 6.7Mb image file) when the application froze and i got the “Not responding” message on the title of the application window. The application defrosted after a while and the file was processed properly, but it had the GUI locked for far too long.

No worries, I said to myself, all I need is some background process to do the dirty work while the GUI stays free for working with me.

Its a shame that Adobe Flex do not support multi threads.

Eventually I worked around this problem and wrote a component that interlaces calls to whatever function you give it, so the GUI wont freeze. (see my post on flex multi threading workaround).
Then I took to the task of making my ciphering class work a chunk at a time. After a superficial profiling session I came to the conclusion that the reading and writing of the files are by far cheaper operations then the ciphering, so the steps used in the solution are:

  • Initiate everything: read source file into memory
  • Interlace on encrypt and decrypt for a small chunk at a time
  • Finalize: write file 

Note: I made a lenient assumption that I wouldn't store a file I cant open all at once.

When I put everything together, it didn't work. I kept crashing on decryption and got an error saying: Error: PKCS#5:unpad: Invalid padding value. expected [252], found [152]
I had a vague  idea what this meant, but no idea what I was doing wrong. The answer came to me an hour after i posted a mayday question on stack overflow. so I posted the answer too:
the encryption and decryption actions change the actual chunk size. in the processChunck method, the ByteArray length before encryption was 16400 and after changed to 16416. using the decrypt changes the ByteArray length from 16416 back to 16400.
hence the solution i chose was to use two numeric values, one for each method used.
I have no idea why this happens, its not the padding (tested it with Crypto.getPad("none")).
So now I'm sharing it with the world (or rather with the 6 other people who viewed the question in stack overflow so far)
Requirements:

  • Download and add the as3crypto package from google code  into your project
  • Create an interlacing component that would call the async-crypto in pace with the GUI frame rate (or use what i wrote: here)
 
Download the source for the CryptoAsync and add it into your project.
Usage example:
var aCrypt:CryptoAsync = new CryptoAsync("C:/screen.jpg","C:/xxx.crp",key,CryptoAsync.ENCRYPT);
aCrypt.getSet();
asyncThread.exec(aCrypt.run,aCrypt);
var aCrypt:CryptoAsync = new CryptoAsync("C:/xxx.crp","C:/result.jpg",key,CryptoAsync.DECRYPT);
aCrypt.getSet();
asyncThread.exec(aCrypt.run,aCrypt);
When:
  • key is a string of your liking
  • asyncTread is an instance of AsyncThreadComponent you can find here

good luck

Friday, February 12, 2010

Flex AS3 Multi Treading Workaround

Its well known that the current versions of Flex (using either the flash or AIR players) do not provide support for multithreading. Everything you do is loaded on the same main thread that is running the GUI too.
This restriction means that if you have to do a dutiful task, the GUI actually stops responding to the user and  your app may even get the “Not Responding” label in the title bar while its off processing.
The way to bypass this issue is to follow two guidelines
  • Break down the big process in to smaller, manageable runs. this means that if you have a loop that each iteration is taxing, you would want to call that loop one iteration at a time.
  • Call the single iteration in a way that interlaces with the GUI refresh rate.
Here is a simple GUI component that you may place on your application, to invoke calls on some other process without hampering the responsiveness of the GUI.
The method you call by this component has to be in the nature of:
public function runFunction(data:Object):Boolean

Download zip file for AsyncThreadComponent

Usage:
Paste this on your app:
<view:AsyncThreadComponent id="asyncThread" />
When you want something to be invoked, create an object and pass the method:
asyncThread.exec(theObject.runFunction,theObject);

Independent on Sundays