-- M. D. Schroeder, November 3, 1981 3:28 PM; --
DIRECTORY
crD: FROM "CoreDefs",
csD: FROM "CoreStreamDefs",
DESDefs,
IODefs,
Inline,
ovD: FROM "OverviewDefs",
Storage,
String,
Stream,
Time;
CryptFile: PROGRAM
IMPORTS csD, DESDefs, Inline, IODefs, Storage, String, Time =
BEGIN
OPEN IODefs;
user: crD.DMSUser = [NIL, NIL, NIL];
key: DESDefs.Key;
seed: DESDefs.Block;
modeChar: CHARACTER;
s: STRING ← [64];
inputHandle: csD.StreamHandle ← NIL;
outputHandle: csD.StreamHandle ← NIL;
deadBytes: [0 .. 255];
bufferPages: CARDINAL = 2;
bP: POINTER = Storage.Pages[bufferPages];
inStreamPages: CARDINAL = 1;
outStreamPages: CARDINAL = 1;
time: LONG CARDINAL;
length, bytesRead: csD.Position;
xString: STRING = "XXX "L;
unexpectedString: STRING = "***Unexpected disk error***"L;
DescribeOpenError: PROCEDURE [r: ovD.ErrorCode] =
BEGIN
SELECT r FROM
ovD.illegalFilename => WriteLine["***File name illegal***"L];
ovD.fileInUse => WriteLine["***File in use***"L];
ovD.fileNotFound => WriteLine["***File not found***"L];
ENDCASE => WriteLine[unexpectedString];
END; --DescribeOpenError--
DescribeRWError: PROCEDURE [r: ovD.ErrorCode] =
BEGIN
WriteChar[CR];
SELECT r FROM
ovD.diskFull => WriteLine["***Disk full***"L];
ovD.fileTooBig => WriteLine["***File too big***"L];
ovD.diskError, ovD.diskCorrupted => WriteLine["***Disk error***"L];
ENDCASE => WriteLine[unexpectedString];
WriteLine["Trying to delete output file."L];
csD.Reset[outputHandle ! csD.Error => CONTINUE];
END; --DescribeRWError--
DO -- main command loop --
BEGIN -- block for exits --
WriteString["Type e for encrypt; d for decrypt; q for quit: "L];
DO
SELECT modeChar ← ReadChar[] FROM
’d, ’e, ’q => {WriteChar[modeChar]; EXIT};
ENDCASE => {WriteChar[’?]; LOOP};
ENDLOOP;
WriteChar[CR];
IF modeChar = ’q THEN EXIT;
s.length ← 0;
WriteString["Type input file name: "L];
ReadLine[s ! Rubout => {WriteString[xString]; RETRY}];
inputHandle ← csD.OpenFromName[s, user, byte, read, inStreamPages
! csD.Error => {DescribeOpenError[reason]; GOTO finish}];
s.length ← 0;
WriteString["Type output file name: "L];
ReadLine[s ! Rubout => {WriteString[xString]; RETRY}];
outputHandle ← csD.OpenFromName[s, user, byte, overwrite, outStreamPages
! csD.Error => {DescribeOpenError[reason]; GOTO finish}];
s.length ← 0;
WriteString["Type key string: "L];
ReadLine[s ! Rubout => {WriteString[xString]; RETRY}];
key ← DESDefs.MakeKey[LONG[s]];
seed ← LOOPHOLE[key, DESDefs.Block];
time ← Time.Current[];
length ← csD.GetLength[inputHandle];
IF modeChar=’e
THEN BEGIN --encrypting, so save number of dead bytes at the start of the file--
deadBytes ← (8 - Inline.LowHalf[length MOD 8]) MOD 8;
csD.Write[outputHandle, deadBytes
! csD.Error=>{DescribeRWError[reason]; GOTO finish} ];
bytesRead ← 0;
END
ELSE BEGIN --retrieve dead bytes number--
deadBytes ← csD.Read[inputHandle
! csD.Error=>{DescribeRWError[reason]; GOTO finish}];
IF deadBytes > 7 THEN
{WriteLine["Input file not encrypted."L]; GOTO finish};
bytesRead ← 1;
END;
WriteString[" ..."L];
UNTIL bytesRead=length DO
nBytes: CARDINAL = csD.ReadBlock[inputHandle, bP, 0, bufferPages*512
! csD.Error=>{DescribeRWError[reason]; GOTO finish}];
nBlocks: CARDINAL = (nBytes+7)/8;
writeBytes: CARDINAL ← nBlocks*8;
bytesRead ← bytesRead+nBytes;
IF bytesRead=length AND modeChar=’d
THEN writeBytes←writeBytes-deadBytes;
seed ← IF modeChar=’e
THEN DESDefs.CBCEncrypt[key, seed, nBlocks, LONG[bP], LONG[bP]]
ELSE DESDefs.CBCDecrypt[key, seed, nBlocks, LONG[bP], LONG[bP]];
csD.WriteBlock[outputHandle, bP, 0, writeBytes
! csD.Error=>{DescribeRWError[reason]; GOTO finish}];
WriteChar[’.];
ENDLOOP;
WriteChar[SP];
csD.Checkpoint[outputHandle];
time ← Time.Current[] - time;
IF modeChar = ’d THEN length ← length - deadBytes - 1;
s.length ← 0;
String.AppendLongDecimal[s, LOOPHOLE[length, LONG INTEGER]];
WriteString[s];
WriteString[" byte file "L];
WriteString[IF modeChar=’e THEN "en"L ELSE "de"L];
WriteString["crypted"L];
IF length > 512 THEN BEGIN
WriteString[" at the rate of "L];
WriteDecimal[LOOPHOLE[Inline.LowHalf[length/time], INTEGER]];
WriteString[" bytes per second"L];
END;
WriteLine["."L];
GOTO finish;
EXITS
finish => BEGIN
IF inputHandle#NIL
THEN {csD.Destroy[inputHandle]; inputHandle ← NIL};
IF outputHandle#NIL
THEN {csD.Destroy[outputHandle]; outputHandle ← NIL};
END;
END; -- exits block --
WriteChar[CR];
ENDLOOP; -- main command loop --
Storage.FreePages[bP];
END. --CryptFile program--