

               PADLOCK
  Background I/O Encryption Library
             version 1.1

           Reference Manual

       Copyright December, 1999

    All rights reserved. This manual
    may be publicly distributed, but
          may not be altered.




CONTENTS
--------
I.   What is Padlock?
II.  Padlock Basics
III. Appendices
     A. Tips for Better Security
     B. Padlock Routines
     C. Useful Global Constants




I.   WHAT IS PADLOCK?
---------------------

Padlock is an encryption library for use with Euphoria version 2.0+. It has been designed to be as unobtrusive as possible. In theory, the standard Euphoria I/O functions could be wrapped and redirected to the corresponding Padlock functions, and your program would run as normal, invisibly encrypting your input and decrypting your output. The only effort on your part would be updating the calls to 'open'.

The principle used by Padlock is that of a password. However, since any string of bytes can be your password, we'll refer to it as a passkey. Each device you open with Padlock's 'pl_open' routine is given a passkey, or a list of passkeys. By using the same passkey or list of passkeys (in the same order) when reading and writing the file, you keep your file secure while enjoying the ability to work with the data as if nothing were changed.

While the algorithm used in Padlock is probably adequate for minimal security needs, such as preventing casual snooping, it is not terribly strong. As such, please do not expect Padlock to protect files that could cause great loss or damage should they be decrypted by an outside agent. THE AUTHOR OF THIS SOFTWARE CANNOT AND DOES NOT TAKE OR HOLD ANY RESPONSIBILITY FOR ANY DAMAGE TO OR LOSS OF DATA, PROPERTY, HEALTH OR LIFE RESULTING FROM THE USE OR MISUSE OF THIS LIBRARY. PADLOCK IS USED AT ONE'S OWN RISK.

Although this library is NOT placed in the public domain, it may be freely and openly distributed, or used in any application, for any public, private or commercial use. Unauthorized modifications are not to be distributed. All rights are reserved.

Anyone who has comments or suggestions, or who has questions not addressed in this manual, should feel free to contact the author of the Padlock library at:

      rodjackson@bigfoot.com


II.  PADLOCK BASICS
-------------------

To begin using Padlock, all one need do is include the library file:

   include padlock.e

With this done, you can call the various Padlock routines and use them in place of the standard Euphoria I/O routines.

Padlock currently has six main global routines:

   pl_close     -- closes a file opened with 'pl_open'
   pl_get_bytes -- gets several bytes from an encrypted file
   pl_getc      -- gets the next byte from an encrypted file
   pl_open      -- opens a file that is encrypted or to be encrypted
   pl_printf    -- writes formatted data to file, and again encrypts
   pl_puts      -- writes a string to file, once more encrypting

and one secondary global function:

   check_passkey_validity -- returns a 1 if given a valid passkey

The six main routines are the ones you'll use to work with encrypted I/O. Files are written using some combination of pl_printf() and pl_puts(). They can later be read via pl_getc() and/or pl_get_bytes(). If using a single passkey, be sure to use the same one for reading and writing. If using a list of passkeys, be sure to use the same ones IN THE SAME ORDER. And after you are done using a Padlocked file, be sure to use pl_close() to close the file, NOT the standard Euphoria routine.

A passkey can be any string of bytes (integers valued from 0 to 255.) It can also be of any length, provided it contains at least 6 unique bytes.

   "Hello!"                -- illegal; only 5 unique bytes
   "For this is the day"   -- legal
   {1,2.3,4.56,7.89,10,11} -- illegal; has non-byte elements
   {48,49,50,51,52,53}     -- legal
   "AAAABBBBCCCCDDDD"      -- illegal; only 4 unique bytes

To begin writing a new file that is to be Padlocked, employ the pl_open() routine:

   myfile = pl_open ("a:\\appdata.dat", "w", "For this is the day")

Notice the extra parameter, the passkey. You should also note that a file cannot be opened for update (reading AND writing) using Padlock. Padlock also is no longer able to open files for appending. It treats attempts to open files for text mode the same as if an attempt was made to open for binary mode. (In other words, use "r" or "rb", it makes no difference.)

Should you want to use a list of passkeys, for somewhat stronger security, simply include the list instead of a single passkey:

   myfile = pl_open ("a:\\appdata.dat", "w", {"Passkey1", "John Doe"})

Now that the file is opened, simply write to it using one of the appropriate output routines:

   pl_puts (myfile, "My Personal Diary, 1/1/2001\n")
   pl_puts (myfile, "Today, I went to ... and ran into ...\n")

   pl_printf (myfile, "exactly %d times!\n", {num_times})

When finished, close the file using pl_close:

   pl_close (myfile)

Your program can now safely end. Your file will remain on disk, encrypted against snoops. To retrieve the data, again open with pl_open, for reading, using the same passkey:

   myfile = pl_open ("a:\\appdata.dat", "r", "For this is the day")

or passkeys:

   myfile = pl_open ("a:\\appdata.dat", "r", {"Passkey1", "John Doe"})

Now just read in the data using the appropriate Padlock routines, and the original data is back!

   entry = {}
   data  = pl_get_bytes (myfile, 100)
   while (length (data) = 100) do
      entry = entry & data
      data = pl_get_bytes (myfile, 100)
   end while
   entry = entry & data -- entry contains the original text now...

Of course, pl_close() is used when finished.

That's all there is to the library. Below, you'll find more detailed descriptions of the routines, some useful global constants that were included, and tips for maximizing your security when using Padlock.


III. APPENDICES
---------------

A. Tips for Increasing Security
-------------------------------

For those of you wanting to get the most out of Padlock, there are a few steps you can take to make things a little bit harder for any would-be voyeur.

First, be sure to use passkeys of reasonable length. Using a variety of characters and symbols should also help make determining a passkey harder. A passkey of "123456" is unwise; it's too orderly, and it's length doesn't help either.

You might want, especially if there is a lot of data to be encrypted, to use the contents of another file as the passkey. For example, if you run your program on a DOS 3.1 system, you might choose to read in the contents of COMMAND.COM when it is first executed, using it as your passkey. This would have the extra benefit of preventing anyone without a DOS 3.1 system from copying the program and the data and simply viewing the data via the application.

Of course, you can also make use of multiple passkeys now too. These are combined into a larger composite passkey. The size of the composite passkey is the product of the sizes of the individual passkeys. For example, if your passkey list is:

   {"Applesauce", "John Doe", "CODE:Q3B9", "Padlocked"}

then the lengths of the passkeys are 10, 8, 9 and 9 bytes respectively. The base length of the composite passkey will then be:

   10 * 8 * 9 * 9 = 6480 bytes

Should your passkeys generate a particularly large composite, you may want to at least double the base number of bytes to determine the amount of memory your program might need to store it.

If your data file has a lot of repeating data, such as numerous identical records, or large regions filled with spaces or nulls, you will probably be best off with a purely random passkey. Multiple passkeys also work well for this situation.

Finally, if you are using a file for a passkey or a large composite passkey, you may want to make sure your operating system is using disk space for virtual memory while your application running. It doesn't hurt to ensure that the passkey, stored in RAM, isn't lurking on disk via a delete virtual memory file.

Hopefully, anyone using Padlock will find it to be flexible enough to work out a system that achieves their desired level of low-security encryption.


B. Padlock Routines
-------------------

   KEY
   ---
   x - a general object (atom or sequence)
   s - a sequence
   a - an atom
   i - an integer 
  fn - an integer used as a file number
 str - a string sequence

----------------------
check_passkey_validity
----------------------
SYNTAX:      check_passkey_validity (str)

DESCRIPTION: This routine checks 'str' to ensure that it is a valid
             passkey. That is, it must be a sequence of integer
             values, each value ranging from 0 to 255 inclusive. At
             least 6 of the values must be unique. If the parameter
             is valid, a 1 is returned. Otherwise a 0 is returned.

EXAMPLES:    is_valid = check_passkey_validity ("abcde")
              -- is_valid now contains a 0 since "abcde" is invalid

             if (check_passkey_validity ("SQ39LE01BY")) then
              -- the 'if' falls into the true section since the
              -- specified passkey was valid

--------
pl_close
--------
SYNTAX:      pl_close (fn)

DESCRIPTION: This closes a file previously opened with the pl_open
             routine. 'fn' is the file handle. This routine should be
             used instead of the built-in close routine, since this
             will also deallocate space for the passkey and other
             data in memory.

EXAMPLE:     myfile = pl_open ("myfile.dat","w","superpassword")
              ...
             pl_close (myfile)

SEE ALSO:    pl_open

-------
pl_getc
-------
SYNTAX:      i = pl_getc (fn)

DESCRIPTION: This returns the next character from the input device.
             'fn' is the file handle. It is expected that the device
             has been previously opened with pl_open, since this
             routine will expect an encrypted character. The
             character will be automatically decrypted before being
             returned as an integer. A -1 is returned at EOF.

EXAMPLE:     next_char = pl_getc (myfile)

SEE ALSO:    pl_get_bytes, pl_printf, pl_puts

------------
pl_get_bytes
------------
SYNTAX:      s = pl_get_bytes (fn, i)

DESCRIPTION: This routine behaves similarly to pl_getc, but it
             returns multiple characters in one call rather than just
             one. It is expected that the device has been previously
             opened with pl_open, since this routine expects
             encrypted data. 'fn' is the file handle. 'i' is the
             number of bytes (characters) to be read. If the end of
             the file is reached, there may be fewer than 'i'
             elements in the returned sequence. The data is
             automatically decrypted before being returned.

EXAMPLE:     print_line = pl_get_bytes (myfile, 80)

SEE ALSO:    pl_getc, pl_printf, pl_puts

-------
pl_open
-------
SYNTAX:      fn = pl_open (str1, str2, s)

DESCRIPTION: This routine is used to open a new file for input ("r")
             or output ("w"), using a single passkey or multiple
             passkeys for encryption. When opening a file for input,
             the routines pl_getc, and pl_get_bytes should be used
             to read from the file. When opening a file for output,
             the routines pl_puts and pl_printf should be used to
             write to it. The passkey(s) is/are only specified at
             the file's opening; there is no need for a second
             reference while the file is open. Note that "r" and "w"
             are automatically replaced with "rb" and "wb" since
             since Padlock only works with files in binary mode. Note
             also that mode "u"/"ub" is not allowed (nor is mode
             "a"/"ab" any longer.) 'str1' is the filename, 'str2' is
             the mode. 's' is the passkey (as a string of bytes
             containing at least 6 unique values), or it can be a
             list of passkeys (each containing at least 6 unique 
             values.) The numeric handle to the file is returned,
             unless the open failed, in which case -1 is returned.
             For more information on the nature of this procedure,
             please refer to the Euphoria documentation for the
             'open' routine.

EXAMPLES:    myfile = pl_open ("c:\\mydata.dat", "w", "passwordkey")

             myfile = pl_open ("c:\\mydata.dat", "r",
                               {"passkey1", "passkey2", "John Doe"})

SEE ALSO:    pl_close

---------
pl_printf
---------
SYNTAX:      pl_printf (fn, str, s)

DESCRIPTION: This routine will print data in the specified format,
             similar to Euphoria's built-in printf routine. The
             difference is that after converting the data to the
             desired format, the text is then encrypted before being
             output. A subsequent read of the data using pl_getc or
             pl_get_bytes will retrieve the formatted data in its
             unencrypted form. 'fn' is the file handle, 'str' is the
             format string for the data, and 's' is the sequence of
             objects to be formatted and output. Please refer to the
             documentation for the printf command in the Euphoria
             library manual for more detailed information regarding
             the format string.

EXAMPLE:     pl_printf (myfile, "The data is: %4d, %3.2f",
                        {var1, var2})

              -- if var1 is 294 and var2 is 988.36722, then the
              -- printout will be:

              --    The data is:  294, 988.37

              -- except in encrypted form.

SEE ALSO:    pl_getc, pl_get_bytes

-------
pl_puts
-------
SYNTAX:      pl_puts (fn, str)

DESCRIPTION: This routine ouputs a string to the specified file,
             after encrypting it. 'fn' is the file handle, 'str' is
             the string to be output. The text can be retrieved via
             the pl_getc and pl_get_bytes routines.

EXAMPLE:     pl_puts (myfile, "This is my first diary entry...\n")
                -- outputs the text, but in encrypted form

SEE ALSO:    pl_getc, pl_get_bytes


C. Useful Global Constants
--------------------------

Currently, Padlock only uses one global constant.

PADLOCK_VERSION -- this is an atom; it represents the version of the
                   Padlock library that is in use. Since it is found
                   in all past and future versions of Padlock, it can
                   be used to insure that a compatible version of the
                   library is being used. All Padlock libraries are
                   and will be backwards-compatible with respect to
                   data generated with the library.

