16. Office-Quality Encryption

FileFlex' core encryption technology is "office quality", meaning its good enough for casual protection in an office environment, but far from "spook-proof". FileFlex encryption will prevent casual users from gaining access to data, but won't stop determined hackers from cracking the code.

I originally intended to implement DES but determined that DES wouldn't encrypt in-place and was quite slow. In-place encryption is critical; when you've got a 30-character field, you want to make sure the encrypted data will fit back into it. The new FileFlex encryption routines do on-the-fly, dynamic encryption and are exceptionally fast.

Encryption Limits

While there's no technical reason you can't encrypt everything, FileFlex doesn't support encryption of non-alphanumeric fields. This is because the encrypted data is totally random and you couldn't put the data back into the fields. If you want to encrypt numbers (i.e., salary data), store them in alphanumeric fields. For speed reasons,FileFlex doesn't check to see if you're attempting to encrypt or decrypt from a non-text field. FileFlex will attempt to encrypt or decrypt the data. However, the results are likely to be invalid or unreliable.

In practice, you also shouldn't encrypt any field you intend to search or index. In theory, you could do a DBQuery on encrypted data by doing a search for the encrypted string. But this doesn't seem really viable in practice.

Encryption keys should be printable characters. Encryption using keys that aren't standard characters may be unreliable. I won't accept any encryption bug reports where the key isn't something that can be typed from a keyboard (without using the Option key).

Standalone Encryption (DBEncrypt and DBDecrypt)

The easiest new commands to use are DBEncrypt and DBDecrypt. Both take as arguments a string and a key and return either an error code or an encrypted or decrypted string, as appropriate. In the following sample line, "ardvark"is the key:
  put DBDecrypt(fld "src","aardvark") into plainText
  put DBEncrypt(fld "src","aardvark") into scrambleText

Dynamic, On-the-Fly Encryption Functions

The idea behind dynamic encryption is that the data is plain-text in your project but enroute to or from a FileFlex data file the data is encrypted. Dynamic encryption options are extensions to existing FileFlex functions. The extended functions include:
  FileFlex Function        Encryption Mode
  -----------------        ---------------
  DBGetCurrRecVal          dynamic decrypt
  DBWriteRec               dynamic encrypt
  DBGetFieldByName         dynamic decrypt 
  DBGetFieldByNum          dynamic decrypt 
  DBGetMemo                dynamic decrypt 
  DBWriteMemo              dynamic encrypt

DBWriteMemo

Syntax of DBWriteMemo is DBWriteMemo(memoField, memoVal). An optional "E"or "Encrypt" parameter and a key parameter has been added to the DBWriteMemo call so that the encryption syntax is:
  DBWriteMemo(memoField, memoVal [, encryptFlag, key])
Example:
  put DBWriteMemo("MYMEMO",fld "memo","E","aardvark") ¬
         into theResult
Note: Everything inside the brackets "[]" are optional.

DBGetMemo

Same idea as DBWriteMemo. Encryption syntax is:
  DBGetMemo(memoField [, decryptFlag, key])
Example:
  put DBGetMemo("MYMEMO","D","aardvark") into fld "memo"

DBGetFieldByName, DBGetFieldByNum

In both cases, decryption requires additional parameters:
  DBGetFieldByName(fieldName [, decryptFlag,key])
  DBGetFieldByNum(fieldNum [, decryptFlag,key])
Example:
  put DBGetFieldByName("SALARY","D","aardvark") into fld "salary"  put DBGetFieldByNum(8,"D","aardvark") into fld "salary"

Some Background on Implementation Choices

When you look at DBGetCurrRecVal, this is where things start to get interesting. Encryption/decryption couldn't be implemented with just an "E"or "D" parameter since that would require you to encrypt or decrypt ALL the fields at once. This is not practical. The easiest "out"for would have been to require you to get encrypted fields one field at a time using DBGetMemo and DBGetFieldByName. This isn't wasn't slick as I'd like and user feedback indicated it would be overly onerous in your development cycle.

The next choice was to specify the whether a field is to be encrypted by prepending some special character in front of a field name, and this way the program would be able to check the first character. If the first character was the special character, the field would be decrypted. The problem with this approach is that you'd have to redefine the whole bloody database schema each time you switched from an encrypted field to an unencrypted field (and vice versa). But it's pretty easy to understand and is marginally elegant.

How Field-List Decryption Works

The third choice was to pass a list of field names to the DBGetCurrRecVal function when decrypting. This is the method that's been implemented in FileFlex. Here's how it works:

Assume the variable "decryptList" contains a comma-delimited list of fields to be decrypted. Here's an example:
  SALARY,NOTES,AGE
To turn on decryption, you'd pass a "D" parameter. (You want to be able to specifically turn on decryption because checking field names will be slower than normal operations--and therefore you don't want it on when not necessary).

Here's an example to bring data back into a card:
  put DBGetCurrRecVal("GD",decryptList,"aarvark") into theResult
"C" for global variables, "D" is the decryptFlag. Here's the syntax:
  DBGetCurrRecVal("C|B|G[D]" [,decryptFieldList, key])
Note: Decryption is not supported for options that return the entire record in a single container.

DBWriteRec (with "G", "B", or "C" parameters)

DBWriteRec can be used to write either from a set of matching named global variables, from card or background fields (SuperCard/HyperCard only) or from a complex container. This segment talks about doing the C,B,G magic.

Again, you'd build a field list. For the purpose of this example, we'll assume the variable encryptList contains the field list:
  put DBWriteRec("GE",12,encryptList,"aarvark") into theResult 	
  put DBWriteRec("E",12,newData,encryptList,"aardvark") ¬
          into theResult
"G" for global variables, "E" to encrypt. 12 is the record to write. EncryptList is the field list and "aarvark" is the key. Syntax is:
  DBWriteRec("C|B|G[E]",recNum [,encryptList,key])
Note: Encryption is not supported for options that save the entire record from a single complex container.



  [Previous Chapter]    [Table of Contents]    [Next Chapter]


Copyright (c) 1996 David Gewirtz under license to Component Software Corp. All rights reserved worldwide.