Using the EncryptionKeyGenerator class to obtain a secure encryption key

The section Understanding the EncryptionKeyGenerator class details the techniques the EncryptionKeyGenerator class uses to generate an encryption key for a database. However, it isn’t necessary to understand these details to use the EncryptionKeyGenerator class in your application.

Follow these steps to use the EncryptionKeyGenerator class in your application:

  1. The EncryptionKeyGenerator class is included in the open-source ActionScript 3.0 core library (as3corelib) project. You can download the as3corelib package including source code and documentation. You can also download the SWC or source code files from the project page.

  2. Place the source code for the EncryptionKeyGenerator class (or the as3corelib SWC) in a location where your application source code can find it.

  3. In your application source code, add an import statement for the EncryptionKeyGenerator class.

    import com.adobe.air.crypto.EncryptionKeyGenerator;
  4. Before the point where the code creates the database or opens a connection to it, add code to create an EncryptionKeyGenerator instance by calling the EncryptionKeyGenerator() constructor.

    var keyGenerator:EncryptionKeyGenerator = new EncryptionKeyGenerator();
  5. Obtain a password from the user:

    var password:String = passwordInput.text; 
     
    if (!keyGenerator.validateStrongPassword(password)) 
    { 
        // display an error message 
        return; 
    }

    The EncryptionKeyGenerator instance uses this password as the basis for the encryption key (shown in the next step). The EncryptionKeyGenerator instance tests the password against certain strong password validation requirements. If the validation fails, an error occurs. As the example code shows, you can check the password ahead of time by calling the EncryptionKeyGenerator object’s validateStrongPassword() method. That way you can determine whether the password meets the minimum requirements for a strong password and avoid an error.

  6. Generate the encryption key from the password:

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

    The getEncryptionKey() method generates and returns the encryption key (a 16-byte ByteArray). You can then use the encryption key to create your new encrypted database or open your existing one.

    The getEncryptionKey() method has one required parameter, which is the password obtained in step 5.

    Note: To maintain the highest level of security and privacy for data, an application must require the user to enter a password each time the application connects to the database. Do not store the user’s password or the database encryption key directly. Doing so exposes security risks. Instead, as demonstrated in this example, an application should use the same technique to derive the encryption key from the password both when creating the encrypted database and when connecting to it later.

    The getEncryptionKey() method also accepts a second (optional) parameter, the overrideSaltELSKey parameter. The EncryptionKeyGenerator creates a random value (known as a salt) that is used as part of the encryption key. In order to be able to re-create the encryption key, the salt value is stored in the Encrypted Local Store (ELS) of your AIR application. By default, the EncryptionKeyGenerator class uses a particular String as the ELS key. Although unlikely, it’s possible that the key can conflict with another key your application uses. Instead of using the default key, you might want to specify your own ELS key. In that case, specify a custom key by passing it as the second getEncryptionKey() parameter, as shown here:

    var customKey:String = "My custom ELS salt key"; 
    var encryptionKey:ByteArray = keyGenerator.getEncryptionKey(password, customKey);
  7. Create or open the database

    With an encryption key returned by the getEncryptionKey() method, your code can create a new encrypted database or attempt to open the existing encrypted database. In either case you use the SQLConnection class’s open() or openAsync() method, as described in Creating an encrypted database and Connecting to an encrypted database.

    In this example, the application is designed to open the database in asynchronous execution mode. The code sets up the appropriate event listeners and calls the openAsync() method, passing the encryption key as the final argument:

    conn.addEventListener(SQLEvent.OPEN, openHandler); 
    conn.addEventListener(SQLErrorEvent.ERROR, openError); 
     
    conn.openAsync(dbFile, SQLMode.CREATE, null, false, 1024, encryptionKey);

    In the listener methods, the code removes the event listener registrations. It then displays a status message indicating whether the database was created, opened, or whether an error occurred. The most noteworthy part of these event handlers is in the openError() method. In that method an if statement checks if the database exists (meaning that the code is attempting to connect to an existing database) and if the error ID matches the constant EncryptionKeyGenerator.ENCRYPTED_DB_PASSWORD_ERROR_ID. If both of these conditions are true, it probably means that the password the user entered is incorrect. (It could also mean that the specified file isn’t a database file at all.) The following is the code that checks the error ID:

    if (!createNewDB && event.error.errorID == EncryptionKeyGenerator.ENCRYPTED_DB_PASSWORD_ERROR_ID) 
    { 
        statusMsg.text = "Incorrect password!"; 
    } 
    else 
    { 
        statusMsg.text = "Error creating or opening database."; 
    }

    For the complete code for the example event listeners, see Complete example code for generating and using an encryption key.