Summary

Refer to Vault 2 for the latest version.

Vault is a Windows application written in .NET 2.0 for encrypting files. This application makes use of the Account Manager library.

Index

Modification History

AuthorDateDescription
Stephen W. Cote08/11/2006Link to version 1.2
Stephen W. Cote06/15/2006Add new feature descriptions for version 1.1
Stephen W. Cote04/01/2006Document created.

Introduction

Dependencies

  • .NET 2.0 Framework. (Not included).
  • SQL Express or SQL Server on one or more computers. (Not included).

Downloads

  • Vault_1.2.zip - The compiled application. Includes AccountManager, CoreLib, DatabaseEngine, and dependencies.
  • Vault_1.2.source.zip - The Visual Studio 2005 project and source code. Includes source code to project dependencies.
  • LicenseTestSource.zip - Example Visual Studio 2005 project and source code. Demonstrates how a master license created with Vault can be used within an application to load and validate a license file.

Screenshots

The following are some screenshots taken from the Vault UI.

Overview

Vault encrypts files for delivery to a pre-determined computer. It is useful for physically transferring files between computers when a network connection is not available or practical, or when it is desirable to only allow a file to be decrypted on a particular computer. The Vault approach is to use a mobile installation in tandem with a SQL Express database (ie: via USB fob, memory card, or even as a normal email attachment).

Vault uses up to three levels of security, where each level may include multi-pass encryption or enciphering using RSA and AES algorithms, and where such algorithms may be applied successively to the source data, or to a dependent key.

The first level is the default security provided by AccountManager and CoreLib, which is intended to protect data inasmuch as the installation itself is protected. The default security is comprised of a number of key pairs, ciphers, and signatures, some of which are shipped with the software, and some that are generated on demand. Except for verifying the signatures, the shipped keys are meant to provide a first line of defense for data security, and are only as secure as the installation itself. There are three different distributed pairs: 1) a public key used to verify product licensing, and confirm signatures on the other keys. 2) a ship key used to encrypt/decrypt everything, and 3) a randomly selected key from a pre-generated key ring. When the product is installed, several new keys are generated and encrypted. When data is added to the database through AccountManager, it is encrypted using the generated keys.

The first level of security locks encrypted data in the database to the installed application. This can be ideal for network applications where breaching either the database or the application is not enough to obtain all the required keys. However, for a mobile solution where the application and database are kept together, this security is only an obstacle.

The second level of security improves the first level. For any given computer, the Vault program improves the security by creating a new key pair (RSA), encrypting the private key with the product key, optionally adding a password cipher onto the key, and storing it on that computer. The public key is stored in the application database, identified by the computer name and MAC address. When data is added to a selected improvement, a new AES key is generated, used to encrypt the data, and then encrypted with the public key. In order to extract data, all of the keys from the installation are required, plus the unencrypted private key stored on the destination computer.

The third level is a maleable and independent password cipher. Since Vault implements AccountManager for managing data, and AccountManager requires a valid user to query data, an AccountManager user (AMUser) must be logged into the AccountManager runtime. Vault uses an account named product_user. AccountManager performs the necessary checks and balances to apply organization-level encryption (first level), vaulted encryption (second level), non-specific password ciphers (third level), and if necessary, data compression. By default, Vault uses a salted hash of the product_user's plaintext password. However, where the second level includes a key reference for each individual data item, thus allowing an attacker to identify which key needs to be broken for which data item, the third level records no reference or signature. The cipher is never stored on disk or the database, and only exists in memory from when a user enters it until the user clears it.

[ top ]

Admissions

It is important to be upfront with how encrytion is handled within software. Therefore, the following is a description of how encryption is handled in Vault.

Vault was written as a cryptographic and licensing exercise, to use the AccountManager library in a stand-alone implementation, and to use SQLEXPRESS in a deployed Windows application. As mentioned in the Introduction, the data security is three levels of AES encryption, backed by RSA encryption, where up to five layers of RSA encryption are used to protect the cipher. Although the AccountManager was designed to be multi-user and multi-organizational, and has a rather innovative approach to roles based security, it does have a few glaring oversights when used in a stand-alone context. For example, anyone with access to the database can extract a data item and be three AES keys away from reading the data. If the application installation is also present, then the first AES key used to encrypt the data can be retrieved with some effort though without having to crack anything, and then it's only a matter of breaking the improvement AES key, and then cracking the data item to identify the missing third key. A password cipher applied to the private key stored on the destination computer affords some security, and the optional second password cipher on the data helps to further secure the data. User account passwords are hashed in the database, and the password cipher is a salted hash. But, not includng any password used to login (at the moment this is automatic since it's a stand-alone app), a user has to enter at least two passwords to extract the first stored data item, and then possibly a second password for each additional data item using a different password cipher, all the while having to maintain which password cipher belongs to which data item.

While the non-specificity of the password cipher appears to engender bad user experience, the objective was to provide an optional level of security that afforded the greatest protection, and that meant not associating any sort of signatures or key references on the database entry for a specific data item that might help that item be cracked.

The organization-level AES key used for default encryption doesn't change for a given application version. This affords little protection as it's strictly an academic exercise to obtain the key used to encrypt the organization key if both the database and the application installation or available. For that reason, adding any more layers of protection to that key doesn't seem prudent because using that same key for many encryptions would make it easier to be cracked anyway. To help foil this, the improvement AES key used to encrypt data is generated on demand for each copy operation and after a predetermined number of files. An improvement AES key is never used again for encryption, only for decryption. Therefore, the potential to crack one RSA-encrypted AES key remains, but the liklihood of cracking all AES keys is greatly reduced.

[ top ]

Background

Vault uses AccountManager to store data in a database. AccountManager uses a generic grouping schema that can replicate the organization and appearance of a directory structure, as well as a generic mechanism for storing encrypted and compressed data by user and by group, or even to create tagging groups for data. AccountManager has been tested for numerous organizations with thousands of users and tens of thousands of data items, with minimal performance degredation (when not using by-data item permissions, which can drop performance by up to two-thirds).

AccountManager is in its third version (though it is labelled AccountManager2, that is because it is for .NET 2.0), and was a port from the original Java version. The API is still very much Java orientated, particularly with the getters and setters. The original goal of AccountManager was to store variable data in a structured format. It started out as an XML-based storage system in 2000, and then was temporarily redesigned to use a rather clever albeit obtuse storage model named HoneyComb (never released, so there's nothing to Google for). Around that time it became clear this could be addressed with a database or a storage stream, so the HoneyComb storage library was sever finished. But, around that time, the need for a lightweight directory service was realized, one that could also store user data and complex permission relationships. The directory service had to be a snap-in library, not a separate product. This was the advent of the current AccountManager model. At one point AccountManager was in use for a large scale product during which time the performance and permission structure were greatly improved; though, it won't scale to have multiple instances using the same database .. that never got fixed, albeit was outside the original scope of the library. Account Manager also has a few legacy caveats, including the inability to have more than one instance of an account logged in at a time. This was partly done for what was considered a security measure, but on later review didn't really provide much security.

I've always been fascinated with cryptography and storing data for some reason. I've read a lot on cryptography, but didn't really have a chance to make much use of it. I just didn't have anything to hide at the time. Even today I don't have much need to pro-actively encrypt anything not already covered by out-of-the-box encryption (ie: HTTPS traffic). Then again, I have found myself in situations where I wanted to transfer private data or source code, and staging it off a secure server was not always an option if firewall restrictions blocked those ports. I also spent a lot of time sending password-protected zip files back-and-forth with customers to either meet soft security protocols or pro-active security restrictions. In a nutshell, that is what Vault was designed to do: encrypt one or more files for delivery to a destination.

Because AccountManager was originally designed for multiple concurrent users, the Vault database can be used interchangeably with the standalone client and a portal making use of the AccountManager library. This is useful for deploying encrypted resources for web applications, and for managing license keys.

[ top ]

Cryptography and Licensing

As previously mentioned, I haven't happened upon or made much opportunity for using encryption in my software. Licensing, though, was another story. I've always been somewhat fascinated with license keys, starting with those used by commercial software, as well as licensing schemes used in some enterprise software. While working on some of these projects, I was consistently appalled at how poorly the licensing algorithms were protected, if at all. Usually they were validated by signatures or simply encoded alphanumeric codes. It wasn't that these were merely susceptible to attack, but more importantly they were easy to circumvent. I created my own licensing schema that used a combination of a signature and lightly encrypted key. The key itself isn't very interesting. It's fifty-six (56) characters, including nine (9) hyphens, which leaves forty-seven (47) characters of data. License keys are encrypted with a key that is built into the CoreLib library, and signed with a private key through Vault (protected by the improvement key).

However, this approach has its fallacies: Once the database is setup, the keys needed to successfully decrypt and enlist the license for the product can't be replaced without invalidating the keys generated during installation. Because new keys are generated for each installation, the only realistic point of attack is at the pre-install point, executed by swapping out all of the keys from the byte code (written in Java or C#). Otherwise, it would be possible to extract and replace the keys, but the signatures would not be valid. Even still, those portions of code could be blocked from execution. Also, the unencrypted key format could be determined (a little reflection goes a long way) to generate a new fake license. Or, all of the hooks to the license code could be removed in the byte code. Although, such a license could never be validated with the software manufacturer.

Vault includes a built-in License generator for use with the CoreLib library. The License generator creates a Master license from which any number of product licenses may be created, as well as a volatile trial license template with time-based expiration, and a public signature key for validating the license using the CoreLib library. Note: The same version of CoreLib, specifically the same product key ring which is built into CoreLib, must be used to create and consume the licenses. New product keys can be generated with the LicenseMaster tool (these are encoded into class files), and which can replace the corresponding source code in CoreLib. CoreLib can then be recompiled, and replace current versions. Warning: Once CoreLib's product keys change, all data and accounts stored through the AccountManager library will be inaccessible.

[ top ]

Performance

The following performance statistics were gathered on a bulk-copy operation of 10810 files, spanning 712 directories, and totalling 224MB (or, the entire contents of the JDK 1.5 SDK; it's roughly 55MB compressed).

To better understand the performance numbers, it's helpful to understand what is going on for each operation.

Folders/Directories translate to groups of type directory in AccountManager. A directory group causes a permission group to be created, resulting in two database records for the groups, and two participation records: the user is associated with the permission group, and the directory group is associated with the permission group.

Data items (AMData) with by-item permissions and vault-security enabled translate into one database record and ten participation records, five of which associate the data item with the permissions, and five of which associate the user with the previous five participations. This is a total of eleven records, whis multiplied by two for individual copy actions that generate a new key, or 1/25.

With auto-thumbnail generation enabled, a new Data item is created for images and stored in the user's ~/.thumbnail directory, and which will share the same Vault key if Vault encryption is enabled and the thumbnail is generated at the time of the copy operation as opposed to being generated during a view operation, and which will be assigned its own by-item permissions if by-item permissions are enabled.

In other words, a single image file for a single copy operation with every feature enabled causes thirty-three records to be created, thirty of which are participation records for the by-item permissions. Understandably, this makes auto-generating by-item permissions for massive copy operations to be inefficient, particularly when multi-user roles-based security isn't needed. But, for comparison, this feature is enabled and makes for the worst performer.

Here are some performance numbers, from worst to best.

Absolute Worst:

10810 files took 1192 seconds, or about 19 minutes (9 files per second; excruciatingly slow), consuming 90MB.
Enabled Options:
Auto-Thumbnail generation (w/ same level of encryption as the data items)
By-item permissions
DEBUG Logging (consumed 16K rows @ 5MB of space.)
Password cipher enabled.
Vault encryption enabled.
AccountManager encryption enabled.
Auto data compression for non-images (gzip)

Middle of the Road:

10810 files took 584 seconds, or about 9.7 minutes (18.5 files per second, still slow), consuming 65MB.
Enabled Options:
Password cipher enabled.
Vault encryption enabled.
AccountManager encryption enabled.
Auto data compression for non-images (gzip)

Baseline:

10810 files took 534 seconds, or about 8.9 minutes (20.2 files per second), consuming 63MB
Enabled Options:
Auto data compression for non-images (gzip)

Comparison with a Zip program

10810 files took 361 seconds, or about 5 minutes (29.9 files per second), consuming 45MB.

The program claimed a running time of two minutes fifteen seconds, but the observed time was 5 minutes, which was the same method of measurement used for the other figures.

Performance Remarks

Vault is configured for the Middle of the Road operation. It is about half the speed as zipping up a similar set of files.

[ top ]

Setup

Vault requires the .NET 2.0 Framework and SQLExpress. Since Vault is intended to be a mobile application and to be executed from its present location, it does not include an installer.

Upon first use, Vault requires an administration password be specified. This is due to the use of AccountManager to store encrypted data in the SQLExpress database, which is multi-user and multi-organizational, and to avoid using a default or randomized password. A default product account and product password are available. By choosing these values, access to the application and data is less restricted, and the default data cipher is derived from the default password. To restrict data access to a specific computer without using any passwords, choose the default product account and don't specify an Improvement password later on. However, for maximum security, change the product account name and password, and elect to specify an Improvement password later on.

After specifying the administration password, and optionally specifying an alternate product user name and password, the Vault database will be prepared. This may take up to a minute to perform.

After the database is prepared, a login page will be displayed if the default product account was not used. Specify the login credentials to access the main UI.

[ top ]

Security

Vault is written in C#; managed code. That adds a rather large black mark because anything listening in to the runtime can effectively grab the unecrypted data streams, or private keys.

Passwords and the Data Cipher

This section only applies to those who specify custom account credentials.

Passwords are hashed with SHA-256 immediately after being specified. Passwords can be reset in the database by overwriting the password field. This would allow a person with access to the database to change the password and logon as that account.

By default, the third level of security - to encipher data with a password - is enabled by default. The data cipher is derived from a SHA-256 hash and a few salts from the plaintext password at the time of a successful login. If a password is lost or otherwise changed, the data cipher cannot be reconstructed and data is inaccessible.

The in-memory data cipher can be changed or cleared at any time through the Vault UI, but remember that the default is always derived from the plaintext of the account password. This allows users to change the cipher at will, but no record or reference is kept as to which cipher belongs to which data item. In such a case it is up to the user to keep track.

Improved Security

The second level of security - to encipher data with an AES key protected by an RSA private key stored on the local machine, apart from the application - is enabled by selecting Security -> Improve Current Computer. After selecting this option, a prompt is displayed asking whether or not a password cipher should be used to protect the RSA private key. If so, a password and password confirmation are required.

If a password is used to encipher the improvement key, then a user will be prompted once for the password when a Vaulted (or item stored with improved security) item is first displayed, Afterwards, if no password is specified or the Improvement is locked via the menu option, the data item is displayed with a red background or with a red icon. If the Improvement is unlocked, the item is displayed with a green background or its mime-type specific icon.

Improvements are stored by system account, and named using a combination of the machine name and MAC address (need to change to Machine ID).

Data is encrypted with improved security by selecting the improvement from the drop-down-list on the main UI. Each copy operation, up to twenty files, causes a new AES key to be generated. When copying images, thumbnails are automatically created and use the same improvement key, so the maximum number of times a single AES key may be used is forty: twenty for the fileset from a single copy operation, and if all of those files are images, twenty for the thumbnails.

Improvements can be removed by selecting Security - Unimprove Current Computer from the menu. Warning: When a computer is unimproved, the private key and all improvement AES keys are deleted, and the randomized data is used to overwrite the file several times on the local computer. However, improved data is not decrypted. It will be henceforth inaccessible. So be careful. A confirmation is provided.

Standard Security

By default, any data added to Vault is encrypted with an AES key generated at the time the product was setup. The AES key is encrypted with an RSA key, that is encrypted with a randomly selected product key, which is encrypted with the product Ship Key. As mentioned earlier, with both the database and application in hand, it is academic to get around this.

[ top ]

Data Structure

Directory Groups

In AccountManager, individual data items are filtered group id and the name. Since groups are filtered by organization, data items inherit this by requiring the group be specified. The group id corresponds to an AccountManager Group, which can be of a type user, control, or directory. Data is added to directory type groups.

Keep in mind these directories are all organized within the database, and not representative of the local filesystem or local permissions.

While this is a Windows application, the directory path struture is heretically Linux flavored. The Vault UI does not allow any directory navigation above the home directory, "~".

Directories are created in two ways. First, by clicking the Add Dir button. Second, by dragging and dropping a Windows explorer selection containing one or more directories into the Contents list. Note that drag-and-drop operations on the Directory tree are not currently permitted.

Directories may be removed by clicking the Delete button.

Directories and their contents may be decrypted and copied to the local filesystem by clicking the Extract button.

The Directory view does not lookup sub-directories until accessed, so it may be necessary to click on a directory node in order to obtain the expansion(+) icon.

Contents List

The Contents List displays data items associated with a particular directory.

Data Items

As previously discussed, data items may have up to three AES ciphers, where one of those ciphers is a password cipher, and where the other two ciphers are encrypted with also-encrypted RSA keys. After entering any necessary password, Vault handles the encryption and decryption of all involved keys.

By default, Data items are applied with the first (default AES key) and third (AES password cipher) of encryption. The second level is controlled by choosing an Improvement from the drop down list. Non-image data that exceeds 512 bytes is automatically compressed using GZip.

Note: Once a data item is added in an encrypted (level 1), vaulted (level 2), or enciphered (level 3) state, the encryption cannot be stripped through the Vault uI. The data item has to be extracted, deleted from Vault, and then re-added without encryption.

Data is added to Vault by dragging and dropping files onto the Contents list. When images are copied, 100x100 pixel thumbnails are automatically generated for a tiny preview pane situated on the UI, and also used for displaying image icons in the list view. All thumnails are stored in the ~/.thumbnails directory, and use the same encryption as the related data item. Thumbnails can be purged by clicking the Tools -> Cleanup Thumbnails menu item.

Data may be deleted when the parent directory is deleted, or when selected in the Contents list and the Delete button is clicked.

Data may be copied to the local filesystem when the Extract button is clicked.

Image and text data may be previewed by clicking the preview button. Images are automatically scaled down so as not to exceed the screen dimensions, and to provide some padding on either side to access the primary Vault UI. The preview will change as new items are selected in the Contents list.

[ top ]

License Tools

The CoreLib library includes a SecurityManager tool for handling the RSA and AES keys, a LicenseManager tool for importing, exporting, and validating license objects with SecurityManager classes, and a License class.

Vault includes a few tools for creating time-based trial licenses, and single- and multi-use licenses by product code, product version, and consumption.

A license key is a fifty-six character plaintext code including a product identifier key, a customer identifier, a vendor identifier, a minimum version, a maximum version, a grant date, an expiration date, access type and variant access data, and consumption type and variant consumption data.

A master key is created, and is comprised of a configuration file, a private RSA key for signatures, a public key for signature verification (aka PublicSignKey), and an RSA key pair for shipping (aka ShipKey).

The PublicSignKey and ShipKey can be exported from Vault as raw XML data in the Core.Interfaces.IConfig format, from which a Core.Interfaces.ISecurityManager may be derived. For convenience, the PublicSignKey and ShipKey can also be exported as Core.Interfaces.IEncodedComponent C# files, and that can be included in product builds.

Retail and Trial license keys are created from Master Licenses, and can be generated in batches up to a thousand at a time. Correlating the customer id used for each license with a CRM is up to the end user.

License keys are signed with the private Master License key, and encrypted with the ShipKey. Licenses are encoded as XML.

The LicenseManager tool requires both keys to validate a license.

Trial Licenses

Trial licenses have two states. The first state is the public version that is generated or transmitted to the user. This version is validated for its structure and verified against the signature, but is not considered a valid license until it has been confirmed. In this unconfirmed state, it is considered to be volatile and may only be used for confirmation.

To confirm a trial license, the host application must provide a new SecurityManager, which defines an RSA key pair and encrypted AES key (SecurityManager will autogenerate and encrypt these; see example). The LicenseManager exposes a static method for confirming volatile licenses with a new SecurityManager, and returns a valid trial licenses. The new SecurityManager is used to encrypt and sign the new trial license plaintext. It is therefore up to the LicenseManager host to store the SecurityManager (it exports to XML) for use with the Trial License.

The LicenseManager also exposes a static method for checking whether or not a trial license has expired, and addresses some (but not all) attempts at system date manipulation by the end user to circumvent the license expiry.

The reason for the extra steps with the Trial License was to make it somewhat symbolic and provide some accounting as to who received the trial license.

[ top ]

Data Tags

Version 1.1 uses the data flags feature in Account Manager 3.1 to create data tags. Data tags make it easy to group sets of content together by similarity, and easily discover that content at the touch of a button.

[ top ]