LoginRegisterCommercial SupportContact Us


POD documentation > Data Handling > Crypt.pm

Crypt.pm

Simple, Secure Data Encryption
posted on 3:05 PM, July 12, 2009

ExSite::Crypt - ExSite crypto driver

The Crypt class encrypts/decrypts arbitrary data and represents the ciphertext using URL-safe characters [A-Z][a-z][0-9][-_]. This allows the ciphertext to easily be placed in URLs, forms, or SQL statements.

The default encryption scheme is TEA (Tiny Encryption Algorithm) as defined at http://www.ftp.cl.cam.ac.uk/ftp/papers/djw-rmn/djw-rmn-tea.html . TEA provides strong 128-bit encryption with a very concise algorithm, and concise output. ExSite's implementation has the following features not found in other TEA implementations:

Although ExSite alters your key in strong mode (by salting the unused pad bits with random data), it is still good practice to use a different passphrase for strong and fast encryption tasks.

To make the ciphertext URL-safe, we MIME-encode it, then we replace '+' characters with '-', and '/' with '_'. We also strip MIME's '=' pad characters, which are superfluous for our purposes.

To override the default crypto algorithms, simply install your own 'encrypt' and 'decrypt' handlers, and have them do whatever you like. They receive 1 argument each, the plaintext and ciphertext, respectively. There is an expectation by some parts of ExSite that the ciphertext is URL-safe ASCII. You can always pass your text through ExSite::Misc::safetext and ExSite::Misc::unsafetext if not URL-safe.

Usage

    my $c = new ExSite::Crypt(%options);  # eg.
    my $c = new ExSite::Crypt();  # or

    my $c = new ExSite::Crypt(key=>"a reasonably lengthly passphrase", 
                            mode=>"fast");
    my $c = new ExSite::Crypt(level=>32,mode=>"fast");  # use full number of rounds, but other fast shortcuts
    my $ciphertext = $c->encrypt($plaintext);

    my $plaintext = $c->decrypt($ciphertext);

Strong or Fast?

Strong mode provides maximum data security, by filling unused pad bits with random data, MD5 hashing the passkey for better use of the key space, and using the maximum recommended number of mixing rounds. Strong mode is recommended for secure data storage, eg. data that is saved to a database, or critical/sensitive data that is transmitted over insecure connections.

Fast mode uses unhashed passwords, empty pad bits, and a smaller number of mixing rounds. This makes it about 3 times faster than strong mode, at the expense of being less secure. Fast mode security should be adequate to prevent simple sniffing, eavesdropping, or unsophisticated cracking attempts, but not a concerted attack by experts. It is recommended for obfuscating data in URLs or forms to prevent tampering if the number of such obfuscations is potentially large and therefore detrimental to performance.

Automatic Encrpytion

Database columns that are defined (by ExSite) to be of the ``crypt'' datatype will have their contents automatically encrypted/decrypted when written to or read from the database. These columns otherwise behave like ``text'' datatypes.

The user identity will be encrypted in the authentication cookie, if $config{auth}{type} eq "crypt". This authentication mode saves resources since the cookie contents are more trustworthy, so the user does not need to be revalidated on every request.

User passwords will be automatically encrypted/decrypted if $config{auth}{password_storage_method} eq "crypt".

The Crypt class is also invoked automatically for construction and parsing of authtokens for automatic logins (see ExSite::Auth).

Key Security

Decryption keys are stored by default in cleartext in your configuration file. That means that encrypted data may be reasonably secure in transmission, or while stored in a database, but if you have concerns about securing data from users who have server access (ie. persons who can read the configuration file), then the default key storage method is inadequate.

To implement a custom key storage system, install a ``crypt_key'' handler to return the appropriate decryption key. The handler is passed the key type (usually ``key_strong'' or ``key_fast''), and should return the appropriate key. The handler can implement whatever key fetching methods and security protocols it chooses to.

Example: Write a compiled program, say getkey.c, that simply writes the key phrase to stdout. Inside this program, conduct whatever tests you feel are necessary to validate that it is safe to give out the key, before you actually write it out. Then make an ExSite handler to invoke this program, eg.

    sub crypt_key_handler {
        my ($this,$keytype) = @_;
        # NOTE: this example ignores the key type.
        # We simply run our external key fetching program
        return `getkey.exe`;
    }

Using this method, your keys are never stored in plain view. However, practically speaking they are still not terribly secure. Since the key fetching program must be run in an automated fashion by the webserver, all an attacker has to do is spoof the webserver environment to fool the program into thinking it is safe to reveal the key. Also, if you encode the key in a simple string inside the program, it may be possible to extract the key without even running the program, simply by inspecting the object code.

In general, if the encrypted data is designed to be automatically decrypted by an automated server process, the ultimate security of your data is not going to be terribly strong. Adding stronger ciphers will not help, since the main point of weakness is that the webserver (an unprivileged process) requires access to the keys to make use of the encrypted data.