This week's book giveaway is in the OCAJP forum. We're giving away four copies of OCA Java SE 8 Programmer I Study Guide 1Z0-808 and have Jeanne Boyarsky & Scott Selikoff on-line! See this thread for details.
I have a very old DOS foxpro application that I support. The software cannot be moved to windows because it uses old hardware with DOS drivers that cannot be replaced by newer equipment at this time. The log in for this system is a password stored in plain text in a .dbf table. Any person with Excel on their desktop can open this table and apparently someone has because the system has been accessed with passwords that belong to users on vacation. Unfortunately all files used by this application are on a public Novell network shared by all users at the facility. Even if I could move the password into some other kind of file, like plain text buried somewhere, that could be opened as well. Again the language used here is very old ( foxpro, dbase III) and it does not have encryption built in. Since this is a DOS language it cannot call objects built in other languages. Additionally the user only types in a password, not a user name. This is because the program limits the user access to one routine at a time and when the routine finishes the user is immediately logged out.
Is there some kind of scramble or hash algorithm I could create with the password string and a variable (or a set or variables) stored in a program so the password in the table isn't what the user types in?
Foxpro has a checksum function and a 16 bit version of the function is in the DOS version of Foxpro. An article by a Foxpro developer suggested a way to use the checksum to encode passwords. Not perfect but much better than cleartext in a table
You can improve the security of your application by storing the checksum of a password instead of the password itself. When the user logs in, take the checksum of the password they enter and compare it with the number stored in the login table.
Using a checksum in this way means that nobody - not even the developer - can read the login table and see a user's password in plain view. If the intruder does have a copy of FoxPro and if they have plenty of time to spare then they could try calculating the checksums of all the likely passwords. This is a long job but not a totally impossible one so do not rely on this simple technique if your system must have absolute security.
The secure way to handle password storage in database fields is to use a randomly seeded digest (in effect a checksum). A random set of bytes concatenated with the bytes of the password and a message digest is created and stored in the database together with the random byte bytes. A test of a submitted password is then made by checking whether or not the stored digest is the same as one creatd by using the stored random bytes and the submitted password.
Just using a digest/checksum without the random bytes is not secure since two people with the same password will have the same digest/checksum value in the database. Also, without the random bytes a simple dictionary check is possible. The random bytes must be (most probably) different but they are not required to be secret. In my experience a checksum normally has a very limited size and anything less than a 20 byte result is likely to be insecure. Message digests are designed for this type of usage and I would suggest you use the 256 bit variant of SHA2.
Now of course all this requires you to be able to store the random bytes and the digest in the database. The resulting random bytes and the digest are both binary so in order to be able to store them in an existing char field in the database you will need to encode them using something like base64 encoding and this inevitably inflates the length (base64 inflates by about 4/3) so you must tailor the length of the digest and the length of the random bytes to that the resulting encoded result fits into your existing table column.
Please note - neither a checksum nor a message digest are an encryption. Both are irreversible transformations which is what makes a message digest (augmented with a random seed) good for storing password information in a database since there is no way of getting back the password from the stored data.