FILE CRYPT.TXT VAN SWAAY 13-MAY-81 Author: Maarten van Swaay Department of Chemistry Kansas State University Manhattan, Kansas 66506 Operating System: RT11 V3 or later SYSGEN options: SJ with .TWAIT support, or FB CRYPT is a program that will encrypt and decrypt files. It is primarily intended for use on text files, although it will operate on all file types. CRYPT is called with a standard monitor command: .R CRYPT . CRYPT performs the following actions: 1. CRYPT requests an encryption string, which may be any string of at least 8 keystrokes and a . If the encryption string contains 20 or more keystrokes before the , only the first 20 are used. If the string contains between 9 and 19 keystrokes before the , the , and the that comes with it, will be used as part of the encryption string. CRYPT does not write or retain any record of the encryption string. It is the responsibility of the user to keep a record of that string; without it there is no way to regenerate the plaintext after a pass through CRYPT. The operation performed by CRYPT is symmetrical: an even number of passes through CRYPT, with the same encryption string, will regenerate the the original input. CRYPT is also symmetrical with respect to the crypt string and the input text. If the input is nonrandom, e.g. if it contains long strings of space codes, information about the crypt string can be retrieved from the output file. For the intended applications (exams, etc.), that should not be a major shortcoming. 2. After CRYPT has accepted the encryption string, it requests a file command. That command may not contain wildcards (% and *). The command can have the following structures: a. indev:infile b. oudev:=indev:infile c. oudev:outfile=indev:infile DK: will be inserted by CSI if indev: or oudev: are omitted from the string. More than one input and/or output file may be specified, but only the first of each will be recognized. Type will encrypt the input file in-place on the disk. This is the recommended use, because no plaintext records will then remain anywhere. Type will create a new output file if the output device is not file-structured, e.g. if TT: is used for output. If the output device specified is file-structured, the input file will be encrypted in-place, even if the output device is not the same as the input device. Note that this action differs from the standard interpretation of the CSI string. Type will create a new output file if the input and output filespecs are not identical. If the two filespecs are identical, the input file will be encrypted in-place. 3. CRYPT assumes no responsibility for the disposition of privileged information elsewhere on a disk, e.g. in the form of backup files or deleted early versions. For the protection of sensitive information, such as exams etc., it will be the responsibility of the user to insure that no unencrypted versions of the text are left on a disk. Although it is not a simple job to gain access to deleted files, it is by no means impossible. To avoid the existence of plaintext information on a disk one should do the following: a. Encrypt each backup file as it is made, and before it is deleted by a subsequent edit session. At the end of the work session, encrypt the current version of the file in-place, and convert it back into plaintext before the start of the next edit session. b. If a backup file is accidentally deleted before it is encrypted, retrieve it with the help of the DIR/DEL command and a session with DUP, which can create directory entries without moving files. c. If neither of the above approaches are practical, copy some large files beyond all existing files, and then squeeze the disk. That will roll the newly written files over the blocks that previously held the deleted versions of your plaintext. Methods and require some familiarity with file manipulations beyond what the average user is aware of. More information about that can be found in the chapters on DIR, DUP, and PIP in RT11 Vol. 2A. It is safe to print plaintext output from CRYPT via the SPOOL, even though that will involve the temporary presence of a plaintext copy of the file on on the system disk. The spooler can be compiled with a condition DSTROY=1, and will then destroy the content of all files it prints, in addition to deleting those files from the directory. PROGRAM NOTES The mechanisms used by CRYPT is a word-by-word XOR between the input file and a text string that is entered at run-time. The encryption string must be at least 10 bytes long (8 characters + CRLF). If the entered string is longer than 20 bytes (including CRLF), it is truncated to 20 bytes (10 words). A text string containing 8-19 characters closed by CRLF is acceptable; the CRLF code will then be part of the encryption string. There are no restrictions on the character set used in the encryption string, but monitor control codes (^C, ^F, ^B, ^X) will be intercepted by the monitor. To avoid the creation of copies of the crypt string at the end of the encrypted file, null words in the input file are left unchanged. CRYPT begins with a request for buffer space to hold the CSI I/O list and enough queue space for the I/O, completion routines, and .TWAIT requests. Then the encryption string is requested. Before input of that string, any unused input in the ring buffer is discarded. After the input string has been accepted, CSI is called in special mode, to avoid lookup and enter functions. On return, the command string is inspected for absence of wildcard specs. Next, the input filespec is inspected: input from a non-file device is refused. The absence of an input file is also ground for rejection of the command string. If no output file was specified, CRYPT will encrypt the input file in-place, without modifying the directory of the input device. If an output device was specified, its nature is inspected. If the output device is non-file, output will be written to that device without further tests. If the output device is file-structured, a test is made whether a file name was given. If no file name was given for output, the input file will be encrypted in-place. Note that this action differs from the standard interpretation of a CSI string. If a file name was given, it is compared against the input filespec. If the two filespecs are identical, the input file will be rewritten in-place. Only if the output filespec differs from the input filespec will a new file be created on a file-structured device. CRYPT will announce its choice of in-place encryption or creation of a new output file, and then perform the action. The I/O loop contains a pair of .READC requests with separate staging blocks and transfer buffers, and separate completion routines. Each completion routine contains a call to the conversion subroutine and a .WRITC request on the same buffer and staging block as the parent .READC. Block numbers for the input requests are controlled from the I/O loop; block numbers for the output requests are maintained in the completion routines. After the last .READC has been issued, an exit routine waits for release of both transfer buffers. Between tests on the release flags, the program puts itself to sleep for 2 time ticks, or about 33 msec. There remain some unresolved questions: 1. How should magtape and cassette be treated? At present, both are refused as input devices, but that may be overly restrictive. 2. No space is requested for drivers, under the assumption that RMON is smart enough not to overlay occupied memory during a .FETCH. That sounds reasonable enough, but may not be watertight. 3. The queue elements are 10 words long, but under XM a .FETCH is not allowed. Only LOADed drivers can be used under XM. That means that the program should be restricted to SJ and FB, in which case the queue elements need only be 7 words each. If the program must run under XM, it should do .DSTATUS on each driver, rather than .FETCH. 4. If the input device can read a block in less than 6 msec, it would be possible to generate a re-entrant call to the conversion subroutine under the SJ monitor, because SJ allows interruption of completion routines by other completion routines. Under FB and XM all completion routines are queued up, so that they cannot interrupt each other. 5. Items 3 and 4 would justify an up-front call to RMON to check for compatibility between the program and the monitor under which it is running. That has not been done yet. 6. The .READC and .WRITC requests are made with brute force; they all fill the entire staging block. It should be possible to leave most or the argument fields blank in those requests. In the interest of readability that has not been done. 7. After the crypt string is accepted, the program clears the lower-case bit in the JSW. For unknown reasons, lower-case input is still passed through when CSI accepts its filespec. CSI is bright enough to handle the conversion by itself, but that does not answer the question why the JSW is ignored at that time. An untested hypothesis is that CSIGEN has its own ideas about case conversion, although that sounds a bit farfetched. Any user comments that can shed light on these questions will be very welcome!