Module 11: Keeping the data (2)
Copyright: C Wragg 2000

Saving to a file

The process of saving data out to a file on disc can appear complex, especially if it involves using a standard save-type window and drag-and-drop, so we are going to postpone the more difficult elements and concentrate on making our application work at a simpler level.

The check code window offers two ways in which to save the data - auto save or enter filename. The autosave option will save the data file within the application folder under the name data0. It has the advantage that you don't have to enter a name for the file, nor do you need to do so when loading the data back in later. It has no real disadvantages, and has the advantage of simplicity.

The alternative is to enter a filename. This might be useful if you want to keep more than one file of secret data, of if you are sharing your computer with someone else in the family and you each want your own file. It is this process, however, that is more complex, and so we shall concentrate on the automatic method first.

Encrypting the data - using EOR

There is no point in saving the data if it can be read by simply loading into Edit! The whole point of this program is to protect your data from prying eyes, and as you may wish to record PIN numbers and other very sensitive information it must be robust. This does not mean that the encryption process itself has to be complicated.

The process used in Secrets takes advantage of the EOR function, itself a Basic keyword. It has the marvellous characteristic that if it is applied twice, then you get back to where you started. This means that you can encode something by operating with EOR once, and you then decode it by using EOR a second time in the same way. Those of you familiar with logic operators will have no difficulty here, but for those who are less confident, here is a brief explanation.

Take two binary numbers 101 and 011. the result of using the EOR function on these numbers is

101 EOR 011 = 110

If we now apply the reverse process, it will look like this

110 EOR 011 = 101 - the number we started with!

Think of EOR as meaning either, or, but not both. EOR operates on each digit in turn, so taking the first digit of both numbers we have 1 and 0, so that give a 1 - 1--.

Now compare the respective second digits 0 and 1 which give the same result, so we now have 11-.

Finally compare the last digits. These are both 1's and EOR does not allow both, so the result is zero and we have the encoded number 110.

Picture of EOR process
The password 011 working on 101

Now imagine this process applied to every digit and letter of your secret data. The number we used, 011, is effectively the password. Applying the password to every character in turn ends up with pure gobbledygook - just what we want. Apply the same password again, and it magically unravels the jumbled code and restores your secret information. Another advantage of this method is that when you reload no harm is done to your precious information if you enter the wrong password! All that will happen is that you load further gobbledygook!

It follows that your data must be as secure as your password, so it is essential that (a) it is not too short or simple enabling it to be quickly found by trial and error, and (b) is not too obvious - you should never use your telephone number, your date of birth, or your partner's name!

For someone who loves puzzles and cracking codes, it is not impossible for someone to study the pattern of the encrypted file and deduce the password. A couple of extra devices are therefore included in the encryption routine to make this much more difficult, but since my personal data relies on this as well as possibly yours too, I will leave you to work these out for yourself if you really want to know!

The saving process

The first step is to add the routine to PROCclick that will respond to a click on the auto save button. This will close the check code window, and call the procedure that manages the saving process which we call PROCautosave. The code is as follows and should be added to PROCclick just before the last two lines of the procedure (ENDCASE, ENDPROC).

WHEN savecheck%
    CASE block%!16 OF
        WHEN 3:REM the auto save button
            !block%=savecheck%
            SYS"Wimp_CloseWindow",,block%
            PROCautosave
    ENDCASE

We now have to add a new procedure called autosave. To keep our program tidy and easy to follow, all the file handling procedures should be kept together, so add the following code at the end of the RunImage file.

REM Encryption, Saving and Loading routines

DEFPROCautosave
code2$=FNstring(code%)
$code%=STRING$(8,CHR$0)
IF code$<>code2$ PROCreport("Codes do not match",1):ENDPROC
PROCencode
path$="<Secrets$Dir>.Data0"
$path%=path$
PROCsave
FORX%=1TO50
    secret$(0,X%)=""
    desc$(0,X%)=""
NEXT
ENDPROC

Remember in the last Module we put the first password into the variable code$. This procedure now takes the second entry and puts it into code2$ so that we can make a comparison. If they are not the same then we branch out of the procedure before any harm is done, giving a message on the way to say that the Codes do not match. PROCreport is contained in the Library, and is invaluable for passing messages back about what is happening as well as reporting on any errors.

Having approved the password, the data is now encrypted by PROCencode. On return to PROCautosave the pathname of the file to be saved is put into path$ - notice the use of <Secrets$Dir> here to ensure it is saved in the application directory - and is put into memory at path% ready for the save process carried out by PROCsave. On returning again to PROCautosave, the arrays are cleared of redundant data before completing the process. Add PROCencode immediately after PROCautosave.

DEFPROCencode
cyc%=LEN(code$):point%=1
FORX%=1TO50
    secret$(0,X%)=FNencrypt(secret$(1,X%))
    desc$(0,X%)=FNencrypt(desc$(1,X%))
NEXT
ENDPROC

PROCencode does not do the encryption itself, but passes this task to a function FNencrypt which takes the content of secret$(1,X%) and returns the encrypted data in secret$(0,X%). You see at this point why we used a two-dimensional array for this data. It does the same for the desc$() data so that the description is not discernible in the encrypted file either. Now add the procedure encrypt.

DEFFNencrypt(a$)
c$=""
L%=LEN(a$):IF L%=0 THEN =c$
FORY%=1TOL%
    b$=MID$(a$,Y%,1)
    d$=MID$(code$,point%,1)
    c%=ASC(b$) EOR ASC(d$)
    b$=CHR$(c%)
    point%+=1:IF point%>cyc% point%=1
    c$+=b$
NEXT
=c$

Not a lot of code to keep your secrets safe! There are several Basic keyword used here, most of which we have already met, but as a reminder this is what each one does.
LEN(a$) returns the length (i.e. the number of characters) in the string a$
ASC(b$) returns the ASCII value of the first character in b$
CHR$(c%) is the reverse of ASC, returning the character with ASCII value c%
EOR either, or, but not both
and an important new keyword:
MID$(a$,x%,y%) one way of extracting part of the string a$.

MID$(a$,x%,y%) will take y% characters from the string starting at the x% th character. So, for example,

MID$("Butter",3,2) is "tt".

Other keywords like MID$ are LEFT$ and RIGHT$ which do the same thing but start from the left of the string or work back from the right of the string respectively. Examples are

LEFT$("Butter",3) is "But",

RIGHT$("Butter",2) is "er".

A nice feature added to BASIC V was to be able to abbreviate these functions further, so that if you left out the second parameter it would still work in a useful way. Thus

LEFT$("Butter") would be "Butte", just dropping the last character from the string, and

RIGHT$("Butter") would be "r", just the last character. Thus

"Butter" = LEFT$("Butter") + RIGHT$("Butter")

All this is useful information, and we could elaborate further, but returning to our function encrypt, it is also worth drawing attention to the penultimate line c$+=b$. Just as we can use this method of incrementing a numeric variable, so we can add to a string. What this line does is to take the string already in c$, add b$ onto the end, and leave the result in c$.

This section of code also demonstrates how a function works. Remember that a function is used to set a given variable. For example, we used it in the procedure encode in the line

secret$(0,X%) = FNencrypt(secret$(1,X%))

which means 'take the content of secret$(1,X%), encrypt it through the function encrypt, and place the result in secret$(0,X%). It is therefore necessary to have a means of passing the result back to this statement, and all function definitions do so by the '= a$' statement where a$ contains the result. Thus in FNencrypt it ends '=c$', meaning that the function ends by returning the content of c$.

The rest of the code, and why it works, you should be able to sort out for yourself.

PROCsave

The final step in the process is the procedure PROCsave, called towards the end of PROCautosave. The code for PROCsave should be added to the end of the RunImage file as follows:

DEFPROCsave
O=OPENOUT(path$)
FORX%=1TO50
    PRINT#O,desc$(0,X%),secret$(0,X%)
NEXT
CLOSE#O
ENDPROC

As you can see, it is really short and simple, but it does use three more Basic keywords.

O = OPENOUT()

tells the computer to open a file defined by path$ to receive data. If it already exists, then it will be overwritten; if it does not exist, then it will be created as a new file. The channel used to write this data will be identified by the number it puts in O.

PRINT#O,a$

writes the content of a$ to the file identified by the channel number O. Note that if we have another file open at the same time with channel number T, then we would write to the second file using PRINT#T, thus ensuring the correct file is updated.

CLOSE#O

closes the file as soon as al data has been written. Remember that it is important not to leave files open when they are not being used. Because this procedure is so simple, we have not put any error trap in here. If any error does occur within this procedure then the file would be left open causing problems, but we will trust you to type this in with great care and avoid any further complications for the time being.

So your data is saved at last. If you open the data file Data0 within the application directory in Edit then you will see it is totally meaningless, but if you want to restore your data to see that it is really still there - well, you will just have to wait for the next Module, won't you, and don't forget your password!

Return to the Module Index