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

1 comment:

Please do not post spam on this blog, Spam sites will be reported to google.
thank you kindly.