Feb 10

The Adobe AIR runtime includes a SQLite database so that you can create data driven applications.

The following are the default locations for the SQLite database:

Mac OS X:

/Users/<userName>/Library/Preferences/<applicationName>/Local Store/<databaseFileName>.db

Windows:

C:\Documents and Settings\<userName>\Application Data\<applicationName>\Local Store\<databaseFileName>.db

Adobe AIR 1.5 introduces a feature to encrypt the SQLite database so that you can secure the contents of database. This is could come in handy if you are writing an application that stores information such as customer contact data.

The Open method and the OpenAsync method of the SQLConnection class include an encryptionKey parameter; this parameter tells AIR to encrypt the database file.

The code sample below shows you how to create / open an encrypted SQLite database. Links to an example application & code can be found at the end of this article.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import com.digitaldogbyte.util.Encryption;
 
private var dbConn:SQLConnection;
private var dbFile:File;
private var dbKey:ByteArray;
 
private function init():void
{
	dbKey = Encryption.retrieveKey();
 
	dbFile = File.applicationStorageDirectory.resolvePath("EncryptionExample.db");
	dbFile.createDirectory();
 
	dbConn = new SQLConnection();
	dbConn.addEventListener(SQLEvent.OPEN, handleDbOpen);
	dbConn.addEventListener(SQLErrorEvent.ERROR, handleDbError);
 
	// by passing in the dbKey variable as the encryptionKey parameter we are telling AIR to encrypt the SQLite database
	dbConn.openAsync(dbFile, SQLMode.CREATE, null, false, 1024, dbKey);
}

Let’s take a look at the Encryption class to see how the dbKey ByteArray is created. The dbKey value is assigned the return value of the retrieveKey method from the Encryption class. The retrieveKey method checks to see if a key already exists in the application’s EncryptedLocalStore. If the key already exists the retrieveKey method will return the existing key, however if the key does not exist; the generateKey method is called to create a key.

The generateKey method uses the as3crypto library’s Random type to create a key. This key is required to read & write to the encrypted database.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
package com.digitaldogbyte.util
{
 
	import com.hurlant.crypto.Crypto;
	import com.hurlant.crypto.prng.Random;
	import com.hurlant.crypto.symmetric.AESKey;
	import com.hurlant.crypto.symmetric.ECBMode;
	import com.hurlant.crypto.symmetric.ICipher;
	import com.hurlant.util.Hex;
 
	import flash.data.EncryptedLocalStore;
	import flash.utils.ByteArray;
 
	public class Encryption
	{
 
		private static var _key:ByteArray;
 
		private static function generateKey():void
		{
			// create key - write to encrypted local store
			_key = new ByteArray();
			var random:Random = new Random();
			random.nextBytes(_key, 16);
			flash.data.EncryptedLocalStore.setItem("key",_key);
		}
 
		public static function retrieveKey():ByteArray
		{
			// try to retrieve key from encrypted local store
			_key = flash.data.EncryptedLocalStore.getItem("key");
			// if no key found in encrypted local store - create a key
			if (_key == null)
			{
				generateKey();
			}
			return _key;
		}
 
	}
}

After you’ve created the encrypted database you can navigate to the database file and try to open it. The database file will not open in your database browser application since the actual database file has been encrypted.

SQLite open error

Here are the download links to the example application & code.

Jan 17

The Adobe AIR 1.1 runtime provides built-in encryption for the local store.

This feature can be used to secure sensitive information like usernames & passwords for web services.

The encrypted local store can be found at these locations on a user’s computer:

Windows: C:\Documents and Settings\<username>\Application Data\Adobe\AIR\ELS\

Mac OS: /Users/<username>/Library/Application Support/Adobe/AIR/ELS/

To use the AIR’s encrypted local store you will need to include the following packages:

1
2
3
import flash.data.EncryptedLocalStore;
 
import flash.utils.ByteArray;

The following code shows an example of encrypting a string and then storing it in the EncryptedLocalStore object. The strToEncrypt string needs to be converted into a ByteArray since the EncryptedLocalStore stores all of it’s data as a hash table that uses strings as keys and byte arrays for the data. In our example, we convert the strToEncrypt into a byteArray as the myByteArray variable using the ByteArray object’s writeUTFBytes method. We are now ready to save our data into the EncryptedLocalStore, which is done by using the EncryptedLocalStore’s setItem method. The setItem method takes a string parameter that it uses as the key for the hash table and then a byte array as the data that it needs to store.

1
2
3
4
5
6
7
var strToEncrypt:String = "Herman";
 
var myByteArray:ByteArray = new ByteArray();
 
myByteArray.writeUTFBytes(strToEncrypt);
 
EncryptedLocalStore.setItem("firstName", myByteArray);

To retrieve the encrypted data from the EncryptedLocaStore you will need to use the getItem method and the string key for the data that you want to retrieve from the hash table.

1
2
3
4
5
6
7
8
var storedValue:ByteArray = EncryptedLocalStore.getItem("firstName");
 
// get the string from the storedValue byte array and store in the strDecrypted variable
var strDecrypted:String = storedValue.readUTFBytes(storedValue.length);
trace(strDecrypted); // "Herman"
 
// read the string from the storedValue byte array
trace(storedValue.readUTFBytes(storedValue.length)); // "Herman"

More documentation can on the EncryptedLocalStore class can be found on Adobe’s site.

Jul 02

There are some small differences in syntax when dynamically attaching library objects in ActionScript 2.0 and ActionScript 3.0.

In this post, I will provide a very simplified example in both ActionScript 2.0 and ActionScript 3.0.

ActionScript 2.0 Example:

You will need to make sure the library object that you are trying to attach has been configured, to do this you need to right click on the object in the library, next select properties and then check the “Export for ActionScript” and “Export in first frame” options. Make sure to enter an Identifier name for the library object; the Identifier name is used to reference the library object in when you try to use it in the ActionScript code.

In this example we will use “myClip” as the Identifier name.

Below is the ActionScript 2.0 code that will dynamically create 5 instances of the myClip object.

1
2
3
4
5
6
7
8
9
10
11
12
13
var numberOfClips:Number = 5; 
var xStart:Number = 0; 
var yStart:Number = 0; 
var xVal:Number = xStart; 
var xOffset:Number = 2; 
for (var i=0;i<numberofclips;i++) 
{ 
     this.attachMovie("myClip","myClip"+i,this.getNextHighestDepth()); 
     this["myClip"+i]._y = yStart; 
     this["myClip"+i]._x = xVal; 
     xVal = this["myClip"+i]._x + this["myClip"+i]._width + this.xOffset; 
     this["myClip"+i].label_txt.text = i.toString(); 
}

ActionScript 3.0 Example:

You will need to make sure the library object that you are trying to attach has been configured, to do this you need to right click on the object in the library, next select properties and then check the “Export for ActionScript” and “Export in first frame” options. Make sure to enter an Class name for the library object; the Class name is used to reference the library object in when you try to use it in the ActionScript code. You don’t need to worry about the Base class, Flash will set a default Base class.

If you are attempting to attach a custom class that you created, you will need to use the Class name of the your custom class; you may also need to set the Base class if your custom class is derived from another custom class that you have created.

When you check the “Export for ActionScript” option, you will likely get a warning telling you that there is no class file found; for this basic example you can just click OK.

Below is the ActionScript 3.0 code that will dynamically create 5 instances of the myClip object.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var numberOfClips:Number = 5; 
var xStart:Number = 0; 
var yStart:Number = 0; 
var xVal:Number = xStart; 
var xOffset:Number = 2; 
for (var i:Number=0;i<numberofclips;i++) 
{ 
     var mc:myClip = new myClip(); 
     mc.name = "myClip"+(i+1); 
     this.addChild (mc); 
     mc.y = yStart; 
     mc.x = xVal; 
     xVal = mc.x + mc.width + this.xOffset; 
     mc.label_txt.text = (i).toString(); 
}

Here are the example source files.