Category : Pascal Source Code
Archive   : PIBCIPHR.ZIP
Filename : DECRYPT.VMS

 
Output of file : DECRYPT.VMS contained in archive : PIBCIPHR.ZIP

(*$R-,V-,S-*)
PROGRAM Decrypt( Input , Output );

(*----------------------------------------------------------------------*)
(* Decrypt --- Vigenere decryption program *)
(*----------------------------------------------------------------------*)
(* *)
(* Author: Philip R. Burns. *)
(* *)
(* Date: January, 1989 *)
(* Version: 1.0 (January, 1989) *)
(* 1.1 (April, 1989) *)
(* *)
(* Systems: VAX/VMS and IBM PC Turbo Pascal. *)
(* *)
(* Usage: On the Vax: *)
(* *)
(* Prepare a file called DEC.COM with the following *)
(* DCL statements: *)
(* *)
(* $ assign/user 'p1' pas$input *)
(* $ assign/user 'p2' pas$output *)
(* $ run decrypt *)
(* *)
(* Define an appropriate DCL command like the following: *)
(* *)
(* Decrypt == "@DEC" *)
(* *)
(* Then to decrypt a file, enter: *)
(* *)
(* Decrypt source result *)
(* *)
(* source --- name of source file to be decrypted *)
(* result --- name of result file after decryption *)
(* *)
(* Example: *)
(* *)
(* Decrypt mymess.enc mymess.let *)
(* *)
(* On the PC: *)
(* *)
(* Decrypt result *)
(* *)
(* Example: *)
(* *)
(* Decrypt mymess.let *)
(* *)
(* Remarks: This program decrypts a text file which has been *)
(* encrypted using a variation of the Vigenere substitution *)
(* cipher by the companion program "encrypt." *)
(* *)
(* "/*" and "*/" are used in place of the usual comment *)
(* delimeters in the nested comments for the "other" *)
(* machine, since the Vax doesn't like nested comments. *)
(* *)
(* I am contributing this program to the public domain. *)
(* *)
(*----------------------------------------------------------------------*)

{ ===== START VAX/VMS CODE ===== }

TYPE
AnyStr = VARYING[255] OF CHAR (* Varying length string *);
LongInteger = INTEGER (* 32-bit integer type *);

{ ===== END VAX/VMS CODE ===== }

{ ===== START PC TURBO PASCAL CODE ===== }
{ }
{ TYPE }
{ AnyStr = STRING[255] /* Varying length string */; }
{ LongInteger = LONGINT /* 32-bit integer type */; }
{ }
{ ===== END PC TURBO PASCAL CODE ===== }

CONST
First_Char = 0 (* First ascii character = NUL *);
Last_Char = 127 (* Last ascii character = DEL *);
Control_End = 31 (* Last ascii control character *);
Blank_Char = 32 (* Ascii blank *);

(* # of non-control characters *)

Span = ( Last_Char - Blank_Char );

VAR
MsgLine : AnyStr (* One line of message *);
StringKey : AnyStr (* Decryption string *);
RanSeed : LongInteger (* Random number seed *);

(*----------------------------------------------------------------------*)
(* Portable random-number generator routines. *)
(*----------------------------------------------------------------------*)
(* *)
(* These routines provide a portable way of producing uniformly *)
(* distributed random numbers between 0 and 1. The reason for *)
(* using these routines rather than the standard system routines *)

(* is so that files may be encrypted on one machine, e.g., the Vax, *)
(* and then decrypted on the PC, or vice versa. *)
(* *)
(*----------------------------------------------------------------------*)

CONST
M = 714025;
IA = 1366;
IC = 150889;
RM = 1.400512E-6;

VAR
Y : LongInteger;
R : ARRAY[1..97] OF LongInteger;

(*----------------------------------------------------------------------*)
(* SetRandom --- Set the seed for the random number generator *)
(*----------------------------------------------------------------------*)

PROCEDURE SetRandom( VAR Seed : LongInteger );

VAR
J : INTEGER;

BEGIN (* SetRandom *)

IF ( Seed > 0 ) THEN
Seed := -Seed;

Seed := ( IC - Seed ) MOD M;

FOR J := 1 TO 97 DO
BEGIN
Seed := ( IA * Seed + IC ) MOD M;
R[ J ] := Seed;
END;

Seed := ( IA * Seed + IC ) MOD M;
Y := Seed;

END (* SetRandom *);

(*----------------------------------------------------------------------*)
(* Random --- Get a uniform random number between 0 and 1 *)
(*----------------------------------------------------------------------*)

FUNCTION Random( VAR Seed : LongInteger ) : REAL;

VAR
J : INTEGER;

BEGIN (* Random *)

J := 1 + ( 97 * Y ) DIV M;

IF ( J < 1 ) THEN
J := 1
ELSE IF ( J > 97 ) THEN
J := 97;

Y := R[ J ];
Random := Y * RM;

Seed := ( IA * Seed + IC ) MOD M;
R[ J ] := Seed;

END (* Random *);

(*----------------------------------------------------------------------*)
(* Decode --- Decryption of text using Vigenere algorithm *)
(*----------------------------------------------------------------------*)

PROCEDURE Decode( VAR Message : AnyStr );

VAR
Index : INTEGER;

BEGIN (* Decode *)

FOR Index := 1 TO LENGTH( Message ) DO
IF ( ( ORD( Message[ Index ] ) > Control_End ) AND
( ORD( Message[ Index ] ) < Last_Char ) ) THEN
Message[ Index ] := CHR( ( ORD( Message[ Index ] ) - Blank_Char + Span -
TRUNC( Random( RanSeed ) * Span ) ) MOD Span +
Blank_Char );

END (* Decode *);

(*----------------------------------------------------------------------*)
(* LXOR --- Find logical exclusive OR of two integers *)
(*----------------------------------------------------------------------*)

FUNCTION LXOR( I , J : LongInteger ) : LongInteger;

VAR
BXOR : LongInteger;

BEGIN (* LXOR *)

{ ===== START VAX/VMS CODE ===== }

BXOR :: BOOLEAN := XOR( I :: BOOLEAN , J :: BOOLEAN );
LXOR := BXOR;

{ ===== END VAX/VMS CODE ===== }

{ ===== START PC TURBO PASCAL CODE ===== }
{ }
{ LXOR := I XOR J; }
{ }
{ ===== END PC TURBO PASCAL CODE ===== }

END (* LXOR *);

(*----------------------------------------------------------------------*)
(* LSHL --- Perform left shift of integer by specified # of bits *)
(*----------------------------------------------------------------------*)

FUNCTION LSHL( I : LongInteger; NBits : INTEGER ) : LongInteger;

BEGIN (* LSHL *)

{ ===== START VAX/VMS CODE ===== }

LSHL := I * ( 2 ** NBits );

{ ===== END VAX/VMS CODE ===== }

{ ===== START PC TURBO PASCAL CODE ===== }
{ }
{ LSHL := I SHL NBits; }
{ }
{ ===== END PC TURBO PASCAL CODE ===== }

END (* LSHL *);

(*----------------------------------------------------------------------*)
(* Calc_Hash --- Hash key string to find seed for random number *)
(*----------------------------------------------------------------------*)

FUNCTION Calc_Hash( Key : AnyStr ) : LongInteger;

VAR
Index : INTEGER;
Sum : LongInteger;

BEGIN (* Calc_Hash *)

Sum := 0;
(* Exclusive OR characters together *)

FOR Index := 1 TO LENGTH( Key ) DO
Sum := LXOR( LSHL( Sum , 1 ) , ORD( Key[ Index ] ) );

(* Square result and subtract 31 to *)
(* produce initial seed. *)
Calc_Hash := Sum * Sum - 31;

END (* Calc_Hash *);

(*****************************************************************************)

BEGIN (* Decrypt *)
(* ASSIGN KEY HERE!!! *)

StringKey := 'Veni, Vidi, Vici';

(* Initialize random number from key *)

RanSeed := Calc_Hash( StringKey );

SetRandom( RanSeed );
(* Decrypt all lines in input file *)
REPEAT
(* Read next line of input *)
READLN ( MsgLine );
(* Decrypt text *)
Decode ( MsgLine );
(* Write decrypted text to output file *)
WRITELN( MsgLine );
(* Until no more input lines left *)
UNTIL ( EOF );

END (* Decrypt *).