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.