2 Replies Latest reply on Sep 9, 2010 8:00 AM by John Hall

    Actionscript code Error from mx to s

    Raproductions79383

      I am working on creating an encrypted database that the user must type in once to create the database and then type in again after the application is reopened to login per say so far i have created an application using mx to s components

      <?xml version="1.0" encoding="utf-8"?>

      <mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" creationComplete="init();" width="500" height="314" xmlns:ns1="*" xmlns:s="library://ns.adobe.com/flex/spark">

      <mx:Script>

      <![CDATA[

      import com.adobe.data.encryption.EncryptionKeyGenerator;

       

      private const dbFileName:String = "Raproductions.db";

       

      private var dbFile:File;

      private var createNewDB:Boolean = true;

      private var conn:SQLConnection;

       

      // ------- Event handling -------

       

      private function init():void

      {

      conn = new SQLConnection();

      dbFile = File.applicationStorageDirectory.resolvePath(dbFileName);

      if (dbFile.exists)

      {

      createNewDB = false;

      instructions.text = "Enter your database password to open the encrypted database.";

      openButton.label = "Open Database";

      }

      }

       

       

      private function openConnection():void

      {

      var keyGenerator:EncryptionKeyGenerator = new EncryptionKeyGenerator();

       

      var password:String = passwordInput.text;

       

      if (password == null || password.length <= 0)

      {

      statusMsg.text = "Please specify a password.";

      return;

      }

       

      if (!keyGenerator.validateStrongPassword(password))

      {

      statusMsg.text = "The password must be 8-32 characters long. It must contain at least one lowercase letter, at least one uppercase letter, and at least one number or symbol.";

      return;

      }

       

      passwordInput.text = "";

      passwordInput.enabled = false;

      openButton.enabled = false;

       

      var encryptionKey:ByteArray = keyGenerator.getEncryptionKey(dbFile, password);

       

      conn.addEventListener(SQLEvent.OPEN, openHandler);

      conn.addEventListener(SQLErrorEvent.ERROR, openError);

       

      conn.openAsync(dbFile, SQLMode.CREATE, null, false, 1024, encryptionKey);

      }

       

       

      private function openHandler(event:SQLEvent):void

      {

      conn.removeEventListener(SQLEvent.OPEN, openHandler);

      conn.removeEventListener(SQLErrorEvent.ERROR, openError);

       

      statusMsg.setStyle("color", 0x009900);

      if (createNewDB)

      {

      statusMsg.text = "The encrypted database was created successfully.";

      }

      else

      {

      statusMsg.text = "The encrypted database was opened successfully.";

      }

      }

       

       

      private function openError(event:SQLErrorEvent):void

      {

      conn.removeEventListener(SQLEvent.OPEN, openHandler);

      conn.removeEventListener(SQLErrorEvent.ERROR, openError);

       

      if (!createNewDB && event.error.errorID == EncryptionKeyGenerator.PASSWORD_ERROR_ID)

      {

      statusMsg.text = "Incorrect password!";

      }

      else

      {

      statusMsg.text = "Error creating or opening database.";

      }

      }

      ]]>

      </mx:Script>

      <mx:HBox>

      </mx:HBox>

      <mx:Text id="instructions" text="Enter a password to create an encrypted database. The next time you open the application, you will need to re-enter the password to open the database again." width="75%" height="65"/>

      <mx:TextInput id="passwordInput" displayAsPassword="true"/>

      <mx:Button id="openButton" label="Create Database" click="openConnection();"/>

      <mx:Text id="statusMsg" color="#990000" width="75%"/>

       

      </mx:WindowedApplication>

       

       

      and here is the one that throws the error code

       

       

      <?xml version="1.0" encoding="utf-8"?>

      <s:WindowedApplication xmlns:fx="http://ns.adobe.com/mxml/2009"

         xmlns:s="library://ns.adobe.com/flex/spark"

         xmlns:mx="library://ns.adobe.com/flex/mx" width="544" height="268">

      <fx:Script>

      <![CDATA[

      import com.adobe.data.encryption.EncryptionKeyGenerator;

       

      private const dbFileName:String = "testing23.db";

       

      private var dbFile:File;

      private var createNewDB:Boolean = true;

      private var conn:SQLConnection;

       

      // ------- Event handling -------

       

      private function init():void

      {

      conn = new SQLConnection();

      dbFile = File.applicationStorageDirectory.resolvePath(dbFileName);

      if (dbFile.exists)

      {

      createNewDB = false;

      instructions.text = "Enter your database password to open the encrypted database.";

      openButton.label = "Open Database";

      }

      }

       

       

      private function openConnection():void

      {

      var keyGenerator:EncryptionKeyGenerator = new EncryptionKeyGenerator();

       

      var password:String = passwordInput.text;

       

      if (password == null || password.length <= 0)

      {

      statusMsg.text = "Please specify a password.";

      return;

      }

       

      if (!keyGenerator.validateStrongPassword(password))

      {

      statusMsg.text = "The password must be 8-32 characters long. It must contain at least one lowercase letter, at least one uppercase letter, and at least one number or symbol.";

      return;

      }

       

      passwordInput.text = "";

      passwordInput.enabled = false;

      openButton.enabled = false;

       

      var encryptionKey:ByteArray = keyGenerator.getEncryptionKey(dbFile, password);

       

      conn.addEventListener(SQLEvent.OPEN, openHandler);

      conn.addEventListener(SQLErrorEvent.ERROR, openError);

       

      conn.openAsync(dbFile, SQLMode.CREATE, null, false, 1024, encryptionKey);

      }

       

       

      private function openHandler(event:SQLEvent):void

      {

      conn.removeEventListener(SQLEvent.OPEN, openHandler);

      conn.removeEventListener(SQLErrorEvent.ERROR, openError);

       

      statusMsg.setStyle("color", 0x009900);

      if (createNewDB)

      {

      statusMsg.text = "The encrypted database was created successfully.";

      }

      else

      {

      statusMsg.text = "The encrypted database was opened successfully.";

      }

      }

       

       

      private function openError(event:SQLErrorEvent):void

      {

      conn.removeEventListener(SQLEvent.OPEN, openHandler);

      conn.removeEventListener(SQLErrorEvent.ERROR, openError);

       

      if (!createNewDB && event.error.errorID == EncryptionKeyGenerator.PASSWORD_ERROR_ID)

      {

      statusMsg.text = "Incorrect password!";

      }

      else

      {

      statusMsg.text = "Error creating or opening database.";

      }

      }

      ]]>

      </fx:Script>

       

      <fx:Declarations>

      <!-- Place non-visual elements (e.g., services, value objects) here -->

      </fx:Declarations>

      <s:Panel x="41" y="13" width="463" height="224" title="Raproductions Vehicle Maintainance">

      <mx:Text id="statusMsg" color="#990000" width="75%" x="58" y="150"/>

      <mx:TextInput id="passwordInput" displayAsPassword="true" x="81" y="108"/>

      <mx:Button id="openButton" label="Create Database" click="openConnection();" x="245" y="109"/>

      <mx:Text id="instructions" text="Enter a password to create an encrypted database. The next time you open the application, you will need to re-enter the password to open the database again." width="75%" height="65" x="58" y="34"/>

      <mx:HBox x="221" y="6">

      </mx:HBox>

      </s:Panel>

      </s:WindowedApplication>

      It throws the error code

       

      ArgumentError: The dbFile parameter value can't be null.
      at com.adobe.data.encryption::EncryptionKeyGenerator/getEncryptionKey()[C:\Users\Admin\Adobe Flash Builder 4\Test_sandbox\src\com\adobe\data\encryption\EncryptionKeyGenerator.as:40]
      at Test_sandbox/openConnection()[C:\Users\Admin\Adobe Flash Builder 4\Test_sandbox\src\Test_sandbox.mxml:52]
      at Test_sandbox/__openButton_click()[C:\Users\Admin\Adobe Flash Builder 4\Test_sandbox\src\Test_sandbox.mxml:101]
      Here is the encryptionKeyGenerator.as

       

      package com.adobe.data.encryption
      {
      import flash.data.EncryptedLocalStore;
      import flash.filesystem.File;
      import flash.utils.ByteArray;
      import mx.utils.SHA256;
      public class EncryptionKeyGenerator
      {
      // ------- Constants -------
      public static const PASSWORD_ERROR_ID:uint = 3138;
      private static const STRONG_PASSWORD_PATTERN:RegExp = /(?=^.{8,32}$)((?=.*\d)|(?=.*\W+))(?![.\n])(?=.*[A-Z])(?=.*[a-z]).*$/;
      private static const SALT_ELS_KEY_STUB:String = "com.adobe.data.encryption.EncryptedDBSalt::";
      // ------- Constructor -------
      public function EncryptionKeyGenerator()
      {
      }
      // ------- Public methods -------
      public function validateStrongPassword(password:String):Boolean
      {
      if (password == null || password.length <= 0)
      {
      return false;
      }
      return STRONG_PASSWORD_PATTERN.test(password);
      }
      public function getEncryptionKey(dbFile:File, password:String, saltELSKey:String=null):ByteArray
      {
      if (dbFile == null)
      {
      throw new ArgumentError("The dbFile parameter value can't be null.");
      }
      if (!validateStrongPassword(password))
      {
      throw new ArgumentError("The password must be a strong password. It must be 8-32 characters long. It must contain at least one uppercase letter, at least one lowercase letter, and at least one number or symbol.");
      }
      if (saltELSKey != null && saltELSKey.length <= 0)
      {
      throw new ArgumentError("If a saltELSKey parameter value is specified, it can't be an empty String.");
      }
      var saltKey:String;
      if (saltELSKey == null)
      {
      saltKey = SALT_ELS_KEY_STUB + dbFile.nativePath;
      }
      else
      {
      saltKey = saltELSKey;
      }
      var concatenatedPassword:String = concatenatePassword(password);
      var salt:ByteArray;
      if (!dbFile.exists)
      {
      salt = makeSalt();
      // save the salt in the encrypted local store for future use
      EncryptedLocalStore.setItem(saltKey, salt);
      }
      else
      {
      salt = EncryptedLocalStore.getItem(saltKey);
      if (salt == null)
      {
      var errorMessage:String;
      if (saltELSKey != null)
      {
      errorMessage = "The dbFile parameter value specifies an existing database, but the specified saltELSKey parameter value doesn't exist.";
      }
      else
      {
      errorMessage = "The dbFile parameter value specifies an existing database, but there is no encryption salt value in the default salt ELS key. Possibly when the database was created a custom salt ELS key was specified.";
      }
      throw new ArgumentError(errorMessage);
      }
      }
      var unhashedKey:ByteArray = xorBytes(concatenatedPassword, salt);
      unhashedKey.position = 0; // have to reset to 0 for an accurate hash
      var hashedKey:String = SHA256.computeDigest(unhashedKey);
      var encryptionKey:ByteArray = generateEncryptionKey(hashedKey);
      return encryptionKey;
      }
      // ------- Creating encryption key -------
      private function concatenatePassword(pwd:String):String
      {
      var len:int = pwd.length;
      var targetLength:int = 32;
      if (len == targetLength)
      {
      return pwd;
      }
      var repetitions:int = Math.floor(targetLength / len);
      var excess:int = targetLength % len;
      var result:String = "";
      for (var i:uint = 0; i < repetitions; i++)
      {
      result += pwd;
      }
      result += pwd.substr(0, excess);
      return result;
      }
      private function makeSalt():ByteArray
      {
      var result:ByteArray = new ByteArray;
      for (var i:uint = 0; i < 8; i++)
      {
      result.writeUnsignedInt(Math.round(Math.random() * uint.MAX_VALUE));
      }
      return result;
      }
      private function xorBytes(passwordString:String, salt:ByteArray):ByteArray
      {
      var result:ByteArray = new ByteArray();
      for (var i:uint = 0; i < 32; i += 4)
      {
      // Extract 4 bytes from the password string and convert to a uint
      var o1:uint = passwordString.charCodeAt(i) << 24;
      o1 += passwordString.charCodeAt(i + 1) << 16;
      o1 += passwordString.charCodeAt(i + 2) << 8;
      o1 += passwordString.charCodeAt(i + 3);
      salt.position = i;
      var o2:uint = salt.readUnsignedInt();
      var xor:uint = o1 ^ o2;
      result.writeUnsignedInt(xor);
      }
      return result;
      }
      private function generateEncryptionKey(hash:String):ByteArray
      {
      var result:ByteArray = new ByteArray();
      // select a range of 128 bits (32 hex characters) from the hash
      // In this case, we'll use the bits starting from position 17
      for (var i:uint = 0; i < 32; i += 2)
      {
      var position:uint = i + 17;
      var hex:String = hash.substr(position, 2);
      var byte:int = parseInt(hex, 16);
      result.writeByte(byte);
      }
      return result;
      }
      }
      }