{$A+,B-,D-,E+,F-,G+,I+,L-,N-,O-,R-,S-,V-,X+} {$M 4048,0,131040} Program encrypt; { Author Trevor J Carlsen - released into the public domain 1992 } { PO Box 568 } { Port Hedland } { Western Australia 6721 } { Voice +61 91 73 2026 Data +61 91 73 2569 } { FidoNet 3:690/644 } { Syntax: encrypt /p=PassWord /k=KeyFile /f=File } { Example - } { encrypt /p=billbloggs /k=c:\command.com /f=p:\prog\anyFile.pas } { PassWord can be any alpha-numeric sequence of AT LEAST four } { Characters. } { KeyFile is the full path of any File on the system that this } { Program runs on. This File, preferably a large one, must not } { be subject to changes. This is critical as it is used as a } { pseudo "one time pad" style key and the slightest change will } { render decryption invalid. } { File is the full path of the File to be encrypted or decrypted.} { notes: Running Encrypt a second time With exactly the same parameters } { decrypts an encrypted File. For total security the keyFile } { can be stored separately on a floppy. Without this keyFile or } { knowledge of its contents it is IMPOSSIBLE to decrypt the } { encrypted File. } { Parameters are Case insensitive and may be in any order and } { may not contain any Dos separator Characters. } Const BufferSize = 65520; Renamed : Boolean = False; Type buffer_ = Array[0..BufferSize - 1] of Byte; buffptr = ^buffer_; str80 = String[80]; Var OldExitProc : Pointer; KeyFile, OldFile, NewFile : File; KeyBuffer, Buffer : buffptr; KeyFileSize, EncFileSize : LongInt; PassWord, KFName, FFName : str80; Procedure Hash(p : Pointer; numb : Byte; Var result: LongInt); { When originally called numb must be equal to sizeof } { whatever p is pointing at. if that is a String numb } { should be equal to length(the_String) and p should be } { ptr(seg(the_String),ofs(the_String)+1) } Var temp, w : LongInt; x : Byte; begin temp := LongInt(p^); RandSeed := temp; For x := 0 to (numb - 4) do begin w := random(maxint) * random(maxint) * random(maxint); temp := ((temp shr random(16)) shl random(16)) + w + MemL[seg(p^):ofs(p^)+x]; end; result := result xor temp; end; { Hash } Procedure NewExitProc; Far; { Does the "housekeeping" necessary on Program termination } Var code : Integer; begin ExitProc := OldExitProc; { Reset Exit Procedure Pointer to original } Case ExitCode of 0: Writeln('Successfully encrypted or decrypted ',FFName); 1: begin Writeln('This Program requires 3 parameters -'); Writeln(' /pPassWord'); Writeln(' /kKeyFile (full path and name)'); Write (' /fFile (The full path and name of the File'); Writeln(' to be processed)'); Writeln; Write ('These parameters can be in any order, are Case,'); Writeln(' insensitive, and may not contain any spaces.'); end; 2: Writeln('Could not find key File'); 3: Writeln('Could not rename and/or open original File'); 4: Writeln('Could not create encrypted File'); 5: Writeln('I/O error during processing - could not Complete'); 6: Writeln('Insufficient memory available'); 7: begin Writeln('Key File is too small - aborted'); Writeln; Writeln(' Key File must be at least as large as the buffer size '); Write (' or the size of the File to be encrypted, whatever is the'); Writeln(' smaller.'); end; 8: Writeln('PassWord must consist of at least 4 Characters'); else { any other error } Writeln('Aborted With error ',ExitCode); end; { Case } if Renamed and (ExitCode <> 0) then Writeln(#7'WARNinG: original File''s name is now TEMP.$$$'); {$I-} close(KeyFile); Code := Ioresult; close(NewFile); Code := Ioresult; close(OldFile); Code := Ioresult; if ExitCode = 0 then Erase(OldFile); Code := Ioresult; {$I+} end; { NewExitProc } Function Str2UpCase(Var S: String): String; { Converts a String S to upper Case. Valid For English. } Var x : Byte; begin Str2UpCase[0] := S[0]; For x := 1 to length(S) do Str2UpCase[x] := UpCase(S[x]); end; { Str2UpCase } Procedure Initialise; Var CommandLine : String; FPos,FLen, KPos,KLen, PPos,PLen : Byte; Procedure AllocateMemory(Var p: buffptr; size: LongInt); begin if size < BufferSize then begin if MaxAvail < size then halt(6); GetMem(p,size); end else begin if MaxAvail < BufferSize then halt(6); new(p); end; end; { AllocateMemory } begin FillChar(OldExitProc,404,0); { Initialise all global Variables } FillChar(PassWord,243,32); ExitProc := @NewExitProc; { Set up new Exit Procedure } if ParamCount <> 3 then halt(1); CommandLine := String(ptr(PrefixSeg,$80)^)+' '; { Add trailing space } CommandLine := Str2UpCase(CommandLine); { Convert to upper Case } PPos := pos('/P=',CommandLine); { Find passWord parameter } KPos := pos('/K=',CommandLine); { Find keyFile parameter } FPos := pos('/F=',CommandLine); { Find Filename For encryption} if (PPos = 0) or (KPos = 0) or (FPos = 0) then Halt(1); FFName := copy(CommandLine,FPos+3,80); FFName[0] := chr(pos(' ',FFName)-1); { Correct String length } KFName := copy(CommandLine,KPos+3,80); KFName[0] := chr(pos(' ',KFName)-1); PassWord := copy(CommandLine,PPos+3,80); PassWord[0] := chr(pos(' ',PassWord)-1); if length(PassWord) < 4 then halt(8); { Create a random seed value based on the passWord } Hash(ptr(seg(PassWord),ofs(PassWord)+1),length(PassWord),RandSeed); assign(OldFile,FFName); {$I-} rename(OldFile,'TEMP.$$$'); if Ioresult <> 0 then halt(3) else renamed := True; assign(OldFile,'TEMP.$$$'); reset(OldFile,1); if Ioresult <> 0 then halt(3); assign(NewFile,FFName); reWrite(NewFile,1); if Ioresult <> 0 then halt(4); assign(KeyFile,KFName); reset(KeyFile,1); if Ioresult <> 0 then halt(2); EncFileSize := FileSize(OldFile); KeyFileSize := FileSize(KeyFile); if KeyFileSize > EncFileSize then KeyFileSize := EncFileSize; if Ioresult <> 0 then halt(5); {$I+} if (KeyFileSize < BufferSize) and (KeyFileSize < EncFileSize) then halt(7); AllocateMemory(buffer,EncFileSize); AllocateMemory(KeyBuffer,KeyFileSize); end; { Initialise } Procedure Main; Var BytesRead : Word; finished : Boolean; Procedure CodeBuffer(number: Word); { This is the actual encryption/decryption engine } Var x : Word; begin For x := 0 to number - 1 do buffer^[x] := buffer^[x] xor KeyBuffer^[x] xor Random(256); end; { CodeBuffer } begin {$I-} finished := False; Repeat BlockRead(OldFile,buffer^,BufferSize,BytesRead); if Ioresult <> 0 then halt(5); if (FilePos(KeyFile) + BytesRead) > KeyFileSize then seek(KeyFile,0); BlockRead(KeyFile,KeyBuffer^,BytesRead,BytesRead); if Ioresult <> 0 then halt(5); CodeBuffer(BytesRead); finished := BytesRead < BufferSize; BlockWrite(NewFile,buffer^,BytesRead); Until finished; end; { Main } begin Initialise; Main; end.