DESCRYPT.LIB - Data Encryption Library for Clipper Copyright 1992-2000 by David H. Rifkind. All rights reserved Extrasensory Software P.O. Box 3038 Glendale, CA 91221 818-550-9487 818-55-=8275 Fax www.extrasensory.com sales AT extrasensory DOT com Introduction ------------ DESCRYPT is a data encryption library that uses the Federal Information Processing Standard Data Encryption Algorithm (FIPS DEA), more commonly known as DES. DES is an extremely secure encryption algorithm. Its design is such that knowing the algorithm does not help in 'breaking' an encrypted message. Only knowing or finding the key will make that possible. The algorithm itself is public information. DES Operations --- ---------- The fundamental DES algorithm works on blocks of 64 bits, using a 56-bit key. The key is contained in another 64-bit block, with one bit out of every eight being ignored (viz. for a parity bit in a seven-bit ASCII character). In this implementation, it is the high-order bit of each byte that is ignored. Since DES works on eight-byte blocks, any variable-length data encrypted with DESCRYPT will be padded to a multiple of eight bytes with zero (NUL) characters. If you need to retrieve the exact length, store some extra data. One approach is to add the length onto the beginning of a string with i2bin(), and retrieve it with bin2w(). Another is to add a non-NUL character on the end of the string. Since the padding at the end will always be NULs, the last non-NUL will be the end mark. Of course, if the data cannot contain NULs, you can just strip the NULs off of the end. Although eight characters of key are enough for DES to provide security, there is some risk that a password may be guessed if it is too short. Longer passwords can be allowed by making multiple encryption passes, using a different substring of the password for the key on each pass. DESCRYPT supports two methods of operation for encrypting strings: Electronic Code Book (ECB), and Cipher Block Chaining (CBC). In ECB, each eight-byte block of the string is encrypted separately using the same key. With this method, large blocks of repeated data (like spaces or zeros) will produce repeated eight-byte patterns in the output, with some risk that the patterns will give an 'enemy' a clue as to the nature of the data. CBC reduces this risk. It requires an eight-byte initialization vector which is exclusive-ored with the first data block before encryption. The encrypted first block is exclusive-ored with the second data block before encryption, and so on for subsequent blocks. CBC output shows no large-scale patterns. Function Reference -------- --------- EncryptBlk() ciphertext := EncryptBlk(plaintext, key) Encrypts a single eight-byte data block. The plaintext is truncated to eight bytes, or padded with 0 (NUL) bytes if it is shorter. The key is also truncated or padded to eight bytes. The result is always exactly eight bytes in length. DecryptBlk() plaintext := DecryptBlk(ciphertext, key) Decrypts a single eight-byte block. This is the complement of EncryptBlk(). Both ciphertext and key are truncated or padded as decribed above, though if the ciphertext is not exactly eight bytes you have probably done something wrong and will not get the desired result. EncryptStr() ciphertext := EncryptStr(plaintext, key, [iv]) Encrypts a string of any length. The key is truncated or padded to eight bytes, and the plaintext is padded with 0 bytes to a multiple of eight bytes. The result is always a multiple of eight bytes in length. If the initialization vector 'iv' is supplied, it should be a string of up to eight characters which will be used for Cipher Block Chaining. If 'iv' is omitted, EncryptStr() works in Electronic Code Book mode. DecryptStr() plaintext := DecryptStr(ciphertext, key, [iv]) Decrypt a string. This is the complement of EncryptStr(). The key and ciphertext are padded as described above, though as for DecryptBlk(), if the ciphertext was not a multiple of eight bytes to start with, you've probably done something wrong. The result may have up to seven 0 bytes on the end which were added by EncryptStr(). As with EncryptStr(), 'iv' is the initialization vector for Cipher Block Chaining. Without 'iv', DecryptStr() works in Electronic Code Book mode. Password() ciphertext := Password(key) This is a one-way encryption function. It truncates or pads the key to eight bytes, then uses the result to encrypt a block of eight 0 bytes, then encrypt the result again and again, for a total of 16 passes. Given the ciphertext, there is no known way to reconstruct the key. This function is useful for password validation. Rather than storing a plaintext password, store only the encrypted version. To check a password later, encrypt it and see if the result is the same as the stored version. Also useful for checking whether a key is correct before decrypting text: store the one-way encrypted key along with the text, then use this method to check the key for validity. Encode224() codestring := Encode224(string) DES encrypted data may contain data with any byte values from 0 to 255. Such data cannot be stored in Clipper memo fields. This function converts a data string into one containing only values from 32 to 255, expanding it by about 15% in the process. The result can be passed through Decode224() to retrieve the original data. Decode224() string := Decode224(codestring) Reverses the conversion performed by Encode224(). Notes on Security ----- -- -------- In theory, a DES-encrypted message is safe as long as the key is secure. In practice, there are usually easier ways to break encrypted data than by attacking the algorithm itself. In many cases, passwords can be guessed. This can be done by computer, with the aid of an on-line dictionary, or simply by trying likely words. When computer users are allowed to choose their own passwords, many will pick their own names, or a spouse' or child's, or other obvious alternatives. To avoid this, some systems require passwords to be of some minimum length, and contain a number of non-alphanumeric characters. (Although DES works with eight-byte keys, you can make several passes to allow longer keys.) The most secure kind of password is one generated at random by the computer (as long as the generator is random enough and not flawed). However, random passwords are hard to remember and users have to write them down, giving another opportunity for them to be discovered. A clever hacker may be able to avoid your encryption altogether if he can locate the original, unencrypted data. This might exist in memory before or after an encryption run and be available to a debugger, or in files on disk, or in erased but recoverable space on disk. Plaintext moved over networks or modems is at least theoretically susceptible to interception or eavesdropping, as are passwords. A typical and unfortunately common mistake along these lines is to write code like this: accept "Password: " to password if password == decrypt(encryptedPassword) // Password is okay... endif The correct password has been stored encrypted, which is correct, but at the point where it is decrypted for comparison with the input, it exists in memory as plaintext. Anybody reasonably handy with a debugger can then find it. A better approach is: if encrypt(password) == encryptedPassword This is why DESCRYPT's Password() function works one way only. Finally, for completeness, I'll mention a persistent rumor in the UNIX network community that the National Security Agency intentionally 'weakened' DES before it was published, to make it possible for NSA computers to break. I don't believe there has ever been any evidence behind the rumor, but if you're using DES to help plot the overthrow of the U.S. government, you might want to take it into consideration. (Note to the NSA: that was a joke.) References ---------- Cryptography: A Guide for the Design and Implementation of Secure Systems. Carl H. Meyer and Stephen M. Mattas. John Wiley & Sons, 1982. ISBN 0-471-04892-5. Federal Information Processing Standard Publication 46 (FIPS PUB 46), Data Encryption Algorithm. National Technical Information Service, U.S. Department of Commerce. ANSI X3.92, Data Encryption Algorithm. American National Standards Institute. This is FIPS PUB 46 recast as an ANSI standard. ANSI X3.105, Data Link Encryption. American National Standards Institute. Describes modes for the use of the DEA over communication links. ANSI X3.106, Data Encryption Algorithm - Modes of Operation. American National Standards Institute. Describes modes for enhancing the security of the DEA when encrypting large blocks of data.