APPENDIX D

             PASSWORD ENCRYPTION AND PASSPHRASE TRANSFORMATION


     The FORTRAN program provided herein is a suggested method
for password encryption and passphrase transformation. The
program transforms a user identifier (USER-ID) and a user
password (4-8 characters) or passphrase (9-64 characters) into
64-bit values for subsequent encryption. This capability was
suggested by several people in comments to NBS on the Password
Usage Standard. Limited experience has indicated that passphrases
(greater than eight characters) are easier to remember and enter
than passwords consisting of any combination of eight characters
from the 95 character set suggested in the Standard. The method
provided in this appendix is cryptographic algorithm independent,
although 64-bit vectors are used. Key consists of 56 significant
bits plus eight bits of parity. Input and output are each 64 bits
in length.
     The program allows the entry of passwords consisting of all
characters from the 95 character set. Acceptable entries include
passwords (4-8 characters), passphrases (9-64 characters), the
equivalent eight character virtual password, or the equivalent 16
hexadecimal digit pass key. The last two are printed whenever a
passphrase is entered. User IDs up to 64 characters long may also
be entered. However, the transformed virtual value for the user
ID is not (normally) printed. User IDs and passwords which are
entered and are not a multiple of eight characters in length are
padded with spaces.
     A virtual password or user ID is calculated whenever a value
greater than 8 characters in length is entered and (for passwords
only) which does not consist of precisely 16 hexadecimal
characters. The virtual value is produced by CBC encryption using
the first eight bytes as key, and subsequent 8-byte blocks as
input to the CBC algorithm. The virtual value is selected in 7-
bit groups from the final output of this operation. These 7 bits
are stored in the right-most bits of a byte, and the left-most
bit is set to zero. Seven bit values which are not represented in
the 95-character set result in discarding the left-most bit and
adding the next bit from the final output value of the encryption
operation. If all bits from this final output value are used
before a complete
8-byte virtual password or user ID has been calculated, the
output value is again processed by the encryption

operation to produce an additional 64 bits from which to complete 
the virtual password or user ID calculation. The value which is
ultimately stored as the encrypted password is produced by
encrypting the user ID (or virtual user ID) by a key which is the
exclusive OR of the password (or virtual password) and a system
key. The system key may be set to 0 for system independent
operation (i.e., for intercommunication between systems).



     C    PASSWORD ENCRYPTION AND PASSPHASE TRANSFORMATION DEMONSTRATION
PROGRAM.
          FC   VERSION 1.2
     C    THIS PROGRAM WAS PRODUCED BY THE COMPUTER INTEGRITY AND SECURITY
STAFF,
     C    INSTITUTE FOR COMPUTER SCIENCES AND TECHNOLOGY
     C    TECHNOLOGY A-216
     C    NATIONAL BUREAU OF STANDARDS
     C    GAITHERSBURG, MARYLAND 20899
     C    (301)921-3427
     C
     C
     C    THE PROGRAM 15 DESIGNED TO COMBINE A USER'S
     C    IDENTIFIER WITH THE ASSOCIATED PASSWORD 50 THAT THE RESULT CAN NEVER
BE
     C    DIVIDED OR DECIPHERED.  THE RESULT IS AN ENCRYPTED PASSWORD
     C    WHICH CAN BE COMPARED WITH A PREVIOUSLY ENCRYPTED AND
     C    STORED PASSWORD.  THE DESIGN GOALS INCLUDE HAVING A SYSTEM FOR
     C    ENCRYPTING PASSWORDS THAT DOES NOT USE A STORED CRYPTOGRAPHIC KEY.
     C    SUCH SYSTEMS CAN EASILY PASS AN ENCRYPTED PASSWORD TO ANOTHER
COMPUTER
     C    SYSTEM FOR VALIDATION.  FOR SYSTEMS THAT DO NOT WISH TO USE ANOTHER
     C    COMPUTER TO VALIDATE PASSWORDS OR TO INTERCHANGE PASSWORDS, A SYSTEM
     C    KEY VARIABLE IS PROVIDED WHICH SHOULD BE RANDOMLY SET FOR EACH
SYSTEM.
     C    THE SYSTEM KEY SHOULD BE SET TO ZERO FOR INTERCHANGE AND A SECRET
VALUE
     C    FOR NO INTERCHANGE.  IDENTICAL TRANSFORMATIONS ARE USED FOR THE
     C    USER-ID AND PASSPHRASE.
     C
     C
     C    THE USER-ID AND THE PASSPHRASE CAN EACH CONTAIN UP TO 64 CHARACTERS.
     C    PASSPHASES AND LONG USER-IDS (MORE THAN 8 CHARACTERS EACH)
     C    ARE TRANSFORMED TO 64 BIT VALUES.  THE RESULTS, CALLED THE VIRTUAL
     C    USER-ID AND VIRTUAL PASSWORD, ARE THEN USED TO PRODUCE AN ENCRYPTED
     C    PASSWORD USING A ONE-WAY ENCRYPTION FUNCTION.
     C
     C    A USER-ID AND A PASSPHRASE (PASSWORD/PASS KEY) ARE ENTERED BY A
     C    PERSON DESIRING USE OF A SYSTEM.  THE USER-ID AND PASSPHRASE ARE
     C    TRANSFORMED. THE VIRTUAL PASSWORD IS USED AS A KEY TO ENCRYPT
     C    THE VIRTUAL USER-ID AND THE RESULT IS COMPARED WITH THE STORED
     C    VALUE FOR THE AUTHORIZED USER OF THE SYSTEM.
     C
     C    BOTH THE PASSWORD ENCRYPTION AND PASSPHASE TRANSFORMATION OPERATIONS
     C    USE THE DATA ENCRYPTION STANDARD (DES) ALGORITHM, BUT ANY BLOCK
     C    ENCIPHERING ALGORITHM CAN BE USED.
     C
     C    CALLS TRANSF, PARITY, CBC, HEXKEY, PACK, UNPBIN, DES AND SETKEY
ROUTINES
     C    DESCNT IS THE NUMBER OF TIMES TO ENCRYPT PASSWORD (ODD *).
          INTEGER DESCNT/5/
          INTEGER USERID(64) , PASSWD(64) . SYSKEY(8)
          INTEGER SPACE /' '/,IDLEN, PWLEN , HEXFLG
          INTEGER IDBIN(64) ,KEYBIN(64) , SYSBIN(64)
     C    THE SYSTEM KEY SHOULD BE ALL ZEROS FOR INTERCHANGE WITH OTHER
SYSTEMS.
     C    FOR SYSTEMS THAT WILL NOT INTERCHANGE PASSWORDS WITH OTHER SYSTEMS,
     C    THE SYSTEM KEY SHOULD BE SET TO RANDOM EVEN NUMBERS BETWEEN O AND
254
     C    DECIMAL (INCLUSIVE) IN EACH OF THE EIGHT ENTRIES.  THIS IS THE
EQUIVALENT
     C    OF A DES KEY WITH THE RIGHT-MOST BIT OF EACH OCTET RESERVED FOR
PARITY.
     C    **NOTE:  THE FOLLOWING SHOULD BE CHANGED FOR EACH SYSTEM
INSTALLATION.**
          DATA SYSKEY/120,98,46,76,22,2,254,128/
     C    INITIALIZE USER-ID AND PASSPHRASE VECTORS
     1    DO 4 1=1,64
          USERID( I) =0
     4    PASSWD(I)-O

     C    GET USER ID AND PASSPHRASE AND DETERMINE THEIR LENGTHS
     5    WRITE(6,800)
     800  FORMAT(//' ENTER USER ID: ')
          READ(S, 100) USERID
          CALL TSTVAL( 64 , USERID, IDLEN)
          IF(IDLEN.LE.0) STOP

C    FOLLOWING STATEMENT IS PROGRAM DEBUG STATEMENT
C    WRITE(6,500) (USERID(M),M=1,IDLEN)
500  FORMAT(' ASCII= ',8Z2.2)
10   WRITE(6,900)
900  FORMAT(' ENTER PASSWORD, PASSPHRASE OR 16-DIGIT HEX KEY ')
100  FORMAT(64A1)
     HEXFLG=0
     READ(s, 100)PASSWD
     CALL TSTVAL( 64, PASSWD, PWLEN)
     IF (PWLEN.LT.4) GO TO 10
C    CHECK FOR A PASSWORD ENTERED AS A HEXADECIMAL KEY IF (PWLEN. EQ. 16) CALL
     HEXKEY(PWLEN, PASSWD,HEXFLG)
C    PASSWORD MUST BE DIFFERENT THAN USER-ID; CHECK AND REPORT.
     IF (IDLEN.NE.PWLEN) GO TO 23 DO 22 I=1,IDLEN
                   IF (PASSWD(I).NE.USERID(I)) GO TO 23
22             CONTINUE
               WRITE(6,200)
200            FORMAT(' PASSWORD MUST NOT EQUAL THE USER ID')
               GO TO 10
23   CONTINUE
C    FOLLOWING STATEMENT IS FOR PROGRAM DEBUG. WRITE(6.500)
     (PASSWD(M),M=1,PWLEN)
C    TRANSFORM LONG USER-ID INTO VIRTUAL USER-ID IF REQUIRED.
     IF (IDLEN .LE. 8) GO TO 43 CALL TRANSF( IDLEN , USERID)
C              FOLLOWING STATEMENT IS FOR PROGRAM DEBUG.
C              WRITE(6,650)(USERID(I),I=l,8)
650            FORMAT(' VIRTUAL USER ID IN 95 CHARACTER SET IS ',8A1)
43   CONTINUE
C    HEXFLG IS A 1 IF SIXTEEN HEX CHARACTERS WERE ENTERED.
C    SIXTEEN HEX CHARACTERS ARE USED AS A KEY, NOT A PASSPHRASE IF (HEXFLG .EQ.
     1) GOTO 46
C    TRANSFORM PASSPHRASE INTO VIRTUAL PASSWORD IF MORE THAN 
          8 CHARACTERS. IF (PWLEN .LE. 8) GO TO 44
               CALL TRANSF(PWLEN, PASSWD)
               WRITE(6,660) (PASSWD(I),I=1,8)
660            FORMAT(' VIRTUAL PASSWORD IN 95 CHARACTER SET IS ',8A1)
C              SHIFT EACH BYTE LEFT ONE BIT FOR DES PARITY BIT COMPUTATION
44        DO 45 1=1,8
               PASSWD(I) = 2*PASSWD(I)
45        CONTINUE
               IF (PWLEN .LE. 8)GO TO 46 WRITE(6,670) (PASSWD(I),I=1,8)
670            FORMAT(' THE PASSWORD IN HEXADECIMAL IS ',8Z2.2)
46   CONTINUE
C    CALL SUBROUTINE TO UNPACK PASSWORD INTO BINARY VECTOR, ONE BIT PER WORD.
     CALL UNPBIN(8 ,8, PASSWD,KEYBIN)
C    CALL SUBROUTINE TO UNPACK SYSTEM KEY MASK INTO BINARY VECTOR. CALL UNPBIN(8
     ,8, SYSKEY, SYSBIN)
C    EXCLUSIVE OR THE PASSWORD AND THE SYSTEM KEY TO MAKE AN ENCRYPTION KEY DO
     24 1=1,64
24   KEYBIN(I)=MOD(KEYBIN(I)+SYSBIN(I),2)
C    SET PARITY OF KEY CORRECTLY BEFORE USING
     CALL PARITY(KEYBIN)
C    THE FOLLOWING TWO STATEMENTS MAY BE USED FOR PROGRAM DEBUG.
C    CALL PACK(8,8,KEYBIN,PASSWD(9))
C    WRITE(6,510) (PASSWD(M),M=9,16)
510  FORMAT(' THE KEY FOR PASSWORD ENCRYPTION IS: ',8Z2.2)
C    NOW LOAD THE KEY
     CALL SETKEY(KEYBIN)
C    UNPACK THE USER ID OR VIRTUAL ID INTO IDBIN FOR ENCRYPTION CALL UNPBIN(8,8
     ,USERID, IDBIN)
C    NOW CALL THE DES ROUTINE THE NUMBER OF TIMES SPECIFIED. DO 30 I=1,DESCNT
C    THIS CALLS THE DES ROUTINE AND ONE-WAY ENCRYPTS IDBIN INTO IDBIN.

30          CALL DES(0.IDBIN,IDBIN)
C           NOW PACK UP THE RESULTS OF THE ENCRYPTION INTO
PASSWD. CALL PACK( 8,8, IDBIN,
            PASSWD)
C           ENCRYPTED PASSWORD NAY NOW BE STORED (PRINTED
FOR DEMONSTRATION). WRITE(6,300)
            (PASSWD(M),M-1,8)
C           Z FORMAT PRINTS HEXADECIMAL CHARACTERS.
300         FORMAT(' THE ENCRYPTED PASSWORD IS: ,8Z2.2)
            GO TO 1
            END



            SUBROUTINE TRANSF(LEN, STRING)
C           TRANSFORM A LONG STRING INTO A STRING OF 8
CHARACTERS INTEGER LEN,STRING(*),KEYBIN(64)
            ,TEMP(128), IV(64)

C           LOAD THE FIRST 8 BYTES AS KEY AFTER SHIFTING EACH
BYTE LEFT,
C           UNPACKING AND COMPUTING ODD PARITY.
         DO 10 1-1,8
10          TEMP(I)-2*STRING(I)
            CALL UNPBIN( 8 , 8 , TEMP , KEYBIN)
            CALL PARITY(KEYBIN)
C           CALL PACK(8,8,KEYBIN,TEMP)
C           WRITE(6,500) (TEMP(M),M=1,8)
500         FORMAT(' THE KEY FOR THE VIRTUAL TRANSFORMATION
IS: ',8Z2.2) CALL SETKEY(KEYBIN)

C           CBC ENCRYPT THE REST OF THE STRING
            DO 20 1=1,64
20          IV(I)=O
            CALL CBC(IV,LEN-8,STRING(9) STRING)

C           DETERMINE THE VIRTUAL ENTITY.  ACCEPT ONLY THE 95
LEGAL CHARACTERS C (32-126)
            CALL UNPBIN( 8 , 8, STRING, TEMP) J=1
            DO 50 1=1,8
C           GET ADDITIONAL BITS IF NECESSARY 
30          IF(J.GE.59) CALL DES(0,TEMP,TEMP(65)) 
C           EXTRACT 7 ASCII BITS AND CHECK FOR VALIDITY
            CALL PACK(1,7,TEMP(J),STRING(I))
            IF((STRING(I).EQ.127).OR.(STRING(I).LT.32)) THEN 
C        SHIFT TO NEXT 7-BIT SET IF ILLEGAL
            J=J+1
            GO TO 30
            ENDIF
C           OTHERWISE, SHIFT TO NEXT 7-BIT SET
50          J=J+7
            RETURN
            END


            SUBROUTINE CBC(IV,LEN, PLAIN,MAC)
C           COMPUTES A 64-BIT MAC ON PACKED PLAINTEXT
(LENGTH-LEN) 
C           LEN MUST BE A MULTIPLE OF 8 AND PLAIN MUST BE
PADDED.
            INTEGER IV(64).LEN,PLAIN(*),MAC(8).INP(64).OUTP(64)
C           USE INITIAL VECTOR

       10   DO 10 1-1,64
            DO 30 I-1,LEN,8
            CALL UNPBIN(8,8,PLAIN(I) .INP)
            DO 20 J-1,64
       20   INP(J)-MOD(OUTP(J)+INP(J),2)
       30   CALL DES(0,INP,OUTP)
            CALL PACK(8,8,OUTP,MAC)
            RETURN
            END
          


         SUBROUTINE HEXKEY(PWLEN, STRING,HEXFLG)
C        CHECK WHETHER THE ENTERED STRING IS HEXADECIMAL
WITH CORRECT PARITY
         TO SERVE AS A KEY
         INTEGER PWLEN, STRING( *) ,HEXFLG,TEMP(8) ,TEMPI(64)

C        TEST FOR HEXADECIMAL. RETURN IF NOT, ELSE CONVERT
         HEXFLG=0
         DO 5 1=1,8
 5       TEMP(I)=0
         DO 10 1=1,16

         TEMP(J)=16*TEMP(J)+STRING(I)
         IF((STRING(I).GE.48).AND.(STRING(I).LE.57)) THEN
                   TEMP(J)=TEMP(J)-48
                   ELSE IF((STRING(I).GE.65).AND.(STRING(I).LE.70)) THEN
                   TEMP(J)=TEMP(J)-55
                   ELSE IF((STRING(I).GE.97).AND.(STRING(I).LE.102)) THEN
                   TEMP(J)=TEMP(J)-'87
                   ELSE
                   RETURN
                   ENDIF
10       CONTINUE

         HEXFLG= 1
            PWLEN=8
            DO 30 I=1,8
       30   STRING(I)=TEMP(I)
            RETURN
            END


            SUBROUTINE TSTVAL( LEN, BUFFER, STATUS)
C           MASK CHARACTERS, CHECK FOR VALIDITY AND
DETERMINE BUFFER LENGTH INTEGER
         LEN, BUFFER(*) , STATUS
            STATUS=0
            DO 10 I=LEN,1,-1
            BUFFER(I)=BUFFER(I)-(BUFFER(I)/128) *128
            IF((BUFFER(I).EQ.127).OR.(BUFFER(I).LT.32)) THEN
                   WRITE(6, 100) BUFFER(I)
100                FORMAT(' UNACCEPTABLE ASCII CHARACTER: ,Z2.2) 
                   DO 5 J=1,LEN
5                  BUFFER(J)='
                   STATUS=- 1
                   RETURN
                   ENDIF
         IF((STATUS.EQ.O).AND.(BUFFER(I).NE.32)) STATUS=I
10       CONTINUE
         RETURN
         END

         SUBROUTINE PACK(LEN, BPW, BINARY, PACKED)
C        SUBROUTINE TO PACK FROM BINARY VECTOR TO PACKED
C        VECTOR OF LENGTH LEN FILLING THE LEAST SIGNIFICANT
BPW BITS. INTEGER
         BINARY( *) , PACKED( *)
         INTEGER LEN,BPW
         K=0
         DO 20 I=1,LEN
         ITEM=0
         DO 10 J=1,BPW
         K=K+1
10       ITEM=ITEM*2+MOD(BINARY(K) ,2)
20       PACKED(I)=ITEM 
         END

SUBROUTINE UNPBIN (LEN, BPW,PACKED, BINARY)
O                               SUBROUTINE TO UNPACK INTO BINARY VECTOR
O                                              FROM PACKED VECTOR OF LENGTH N
CONTAINING BPW BITS IN EACH WORD. INTEGER
         PACKED(*), BINARY(*)
                                               INTEGER LEN,BPW
                                               K=0
                                               DO 100 I=1,LEN
                                               ITEM=MOD(PACKED(I) ,2**BPW)
                                               DO 100 J-1,BPW
                                               IEX=2**(BPW-J)
                                               IBIT=ITEM/ IEX
                                               K-K+1
                                               BINARY(K)=IBIT
100                                            ITEM=ITEM-IBIT*IEX
                                               END


                                               SUBROUTINE PARITY (VECTOR)
C                                              COMPUTE ODD PARITY ON A 64-BIT
UNPACKED VECTOR INTEGER VECTOR( 64)
                                               DO 10 1=8,64,8
                                               VECTOR(I)=1
                                               DO 10 J=1,7
10                                            
VECTOR(I)=MOD(VECTOR(I)+VECTOR(I+J-8) ,2) RETURN
                                               END


C                                              PROGRAMS PRODUCED BY THE
NATIONAL BUREAU OF STANDARDS
C                                              NOT SUPPORTED BY NBS AND NOT
SUBJECT TO COPYRIGHT
C                                              SUBROUTINE TO PERFORM THE DATA
ENCRYPTION STANDARD ALGORITHM SUBROUTINE
                                               DES ( SWITCH, INPUT , OUTPUT)
C                                              SWITCH = O CAUSES ENCRYPTION;
SWITCH = 1 CAUSES DECRYPTION.
C                                              INPUT IS PLAINTEXT FOR ENCRYPTION,
CIPHERTEXT FOR DECRYPTION.
C                                              OUTPUT IS CIPHERTEXT AFTER
ENCRYPTION. PLAINTEXT AFTER DECRYPTION.

C                                              CALL DES(0,PT,CT) IS AN EXAMPLE OF
CALL TO ENCRYPT PT INTO CT
C
C                                              CALL DES(1,CT,PT) IS AN EXAMPLE OF
CALL TO DECRYPT CT INTO PT
C
C                                              THIS PROGRAM SHOULD NOT BE
EXPORTED FROM THE UNITED STATES. IMPLICIT INTEGER (A-
                                               z)
                                               INTEGER INPUT(64) ,OUTPUT(64)
                                               INTEGER KS(48,16)
O                                              KS IS AN ARRAY TO HOLD THE 16
SUBKEYS FOR 16 ROUNDS OF DES
C                                              KS IS COMPUTED BY SETKEY
SUBROUTINE WHICH MUST BE CALLED BEFORE
C                                              THE DES SUBROUTINE IS CALLED. 
SETKEY IS CALLED ONCE TO SET THE
C                                              KEY AND THEN DOES NOT HAVE TO BE
CALLED AGAIN UNTIL THE KEY IS
C                                              CHANGED.
C
                                               COMMON KS
                                               INTEGER LR(64),L(32),R(32)
                                               EQUIVALENCE (LR(1),L(1)), (LR(33),R(1))
                                               INTEGER TEMPL(32),EX(48),F(32)
C                                              IP IS THE INITIAL PERMUTATION FOR
THE DATA INTEGER IP(64)/
         1 58,50,42,34,26,18,10,02.
         1 60,52,44.36.28.20.12,04,
         1 62,54,46,38,30,22,14,06,
         1 64,56,48,40,32,24,16,08,
         1 57,49,41,33,25,17,09,01,
         1 59,51,43,35,27,19,11,03,
         1 61,53,45,37,29,21,13,05,
         1 63,55,47,39,31,23,15,07/

C        IPINV IS THE INVERSE OF THE INITIAL PERMUTATION
C        INTEGER IPINV(64)/
C        1 40,08,48,16,56,24,64,32,
C        1 39,07,47,15,55,23,63,31,
C        1 38,06,46,14,54,22,62.30,
C        1 37,05,45,13,53,21,61,29,
C        1 36,04,44,12,52,20,60,28,
C        1 35,03,43,11,51,19,59,27,
C        1 34,02,42,10,50,18,58,26,
C        1 33,01,41,09,49,17,57,25/
C        NOTE:   THE REVERSED 1P INVERSE TABLE -REVIPI- IS USED
BECAUSE
C        IT SAVES THE TIME OF REVERSING THE L AND R REGISTERS.
            INTEGER REVIPI (64)/
C        1 08,40,16,48,24,56,32,64,
            1 07,39,15,47,23,55,31,63,
         1 06,38,14,46,22,54,30,62,
         1 05,37,13,45,21,53,29,61,
         1 04,36,12,44,20,52,28,60,
         1 03,35,11,43,19,51,27,59,
         1 02,34,10,42,18,50,26,58,
         1 01,33,09,41,17,49,25,57/
C        E IS THE EXPANSION OPERATION WHICH EXPANDS 32 BITS
TO 48 BITS
            INTEGER E(48)/
         1 32,01,02,03,04,05,
         1 04,05,06,07,08,09,
         1 08,09,10,11,12,13,
         1 12,13,14,15,16,17,
         1 16,17,18,19,20,21,
         1 20,21,22,23,24,25,
         1 24,25,26,27,28,29,
         1 28,29,30,31,32,01/
C        P IS THE PERMUTATION USED IN THE MAIN DES FUNCTION
            INTEGER P(32)/
         1 16,07,20,21,
         1 29,12,28,17,
         1 01,15,23,26,
         1 05,18,31,10,
         1 02,08,24,14,
         1 32,27,03,09,
         1 19,13,30,06,
         1 22,11,04,25/
C        THE EIGHT SUBSTITUTION TABLES ARE USED IN THE DES TO
SUBSTITUTE 4 BITS
C           FOR SIX BITS.  ONE S TABLE IS USED FOR EACH 6 BIT TO 4
BIT TRANSFORMATION. INTEGER
            5(64,8)
            EQUIVALENCE (S(1,1),S1(1)), (S(1,2),S2(1))
            EQUIVALENCE (S(1,3),S3(1)), (S(1,4),S4(1))
            EQUIVALENCE (S(1,5),S5(1)), (S(1,6),S6(1))
            EQUIVALENCE (S(1,7),S7(1)), (S(1,8),S8(1))
            INTEGER SI(64)/
         1 14,04,13,01,02,15,11,08,03,10,06,12,05,09,00,07,
         1 00,15,07,04,14,02,13,01,10,06,12,11,09,05,03,08,
         1 04,01,14,08,13,06,02,11,15,12,09,07,03,10,05,00,
         1 15,12,08,02,04,09,01,07,05,11,03,14,1O,00,06,13/
            INTEGER S2(64)/
         1 15,01,08,14,06,11,03,04,09,07,02,13,12,00,05,10,
         1 03,13,04,07,15,02,08,14,12,00,01,10,06,09,11,05,
         1 00,14,07,11,10,04,13,01,05,08,12,06,09,03,02,15,
         1 13,08,10,01,03,15,04,02,11,06,07,12,00,05,14,09/
            INTEGER S3(64)/
         1 10,00,09,14,06,03,15,05,01,13,12,07,11,04,02,06,
         1 13,07,00,09,03,04,06,10,02,08,05,14,12,11,15,01,
         1 13,06,04,09,08,15,03,00,11,01,02,12,05,10,14,07,
         1 01,10,13,00,06,09,08,07,04,15,14,03,11,05,02,12/
                 INTEGER S4(64)/
            1 07,13,14,03,00,06,09,10,01,02,08,05,11,12,04,15,
            1 13,08,11,05,06,15,00,03,04,07,02,12,01,10,14,09,
            1 10,06,09,00,12,11,07,13,15,01,03,14,05,02,08,04,
            1 03,15,00,06,10,01,13,08,09,04,05,11,12,07,02,14/
                 INTEGER SS(64)/
            1 02,12,04,01,07,10,11,06,08,05,03,15,13,00,14,09.
            1 14,11,02,12,04,07,13,01,05,00,15,10,03,09,08,06.
            1 04,02,01,11,10,13,07,08,15,09,12,05,06,03,00,14,
            1 11,08,12.07,01,14,02,13,06,15,00,09,10,04,05,03/
                 INTEGER S6(64)/
            1 12,01,10,15,09,02.06,08,00, 13,03,04,14,07,05,11,
            1 10,15,04,02,07.12,09,05,06,01, 13,14,00,11,03,08,
            1 09,14,15,05,02,08,12,03.07,00,04,10,01,13,11,06,
            1 04,03,02,12,09,05,15,10,11,14,01,07,06,00,08,13/
                 INTEGER S7(64)/
            1 04,11,02, 14,15,00,08,13,03,12,09,07,05,10,08,01,
            1 13,00,11,07,04,09,01,10, 14,03,05,12,02,15,08,06.
            1 01,04,11,13,12,03,07,14,10, 15,06,08,00,05,09.02.
            1 06. 11,13,08,01,04,10.07,09,05,00,15,14,02,03,12/
                 INTEGER S8(64)/
            1 13,02,08,04,06,15,11,01,10,09,03,14,05,00,12,07,
            1 01,15,13,08,10,03,07,04,12.05,06.11,00, 14,09,02,
            1 07,11,04,01,09,12,14,02,00,08,10,13,15,03,05,08,
            1 02,01.14.07,04.10,08,13,15,12,09.00,03,05.06,11/


C
C*** SWITCH=0 IS ENCRYPTION; SWITCH=1 IS DECRYPTION MODE
C
            N1=1
            N2=16
            N3=1
                 IF (SWITCH .EQ. 0)GO TO 20
            N1=16
            N2=1
            N3=-1
C                LOOP WHICH DOES THE INITIAL PERMUTATION OF THE
INPUT
20               DO 50 1=1,64
50               LR(I)=INPUT(IP(I))
C                MAIN LOOP WHICH ENCRYPTS OR DECRYPTS FOR 16
ROUNDS
                 DO 500 N=N1,N2,N3
C                LOOP WHICH SAVES THE R REGISTER DO 75 1=1,32
75               TEMPL(I)=R(I)
C                LOOP WHICH EXPANDS THE R REGISTER USING THE E
FUNCTION
C                AND DOES THE XOR OF THE KEY SCHEDULE SUBKEY
AND THE EXPANDED R. DO 100
                 1=1,48
                 EX(I)=1
100              IF(R(E(I)) .EQ. KS(I.N)) EX(I)=0
C                LOOP WHICH DOES THE SUBSTITUTIONS USING THE 8 S
TABLES.
            DO 200 J=0,7
                 K=J*6+1
                 IN=EX(K) *32+EX(K+5) * 16+EX(K+1 ) *8+EX(K+2) *4+EX(K+3)
*2+EX(K+4)
                 SUB=S(IN+1 .J+1)
                 K=J*4
                 F(K+1) = SUB/8
                 F(K+2) = MOD(SUB,8)/4
                 F(K+3) = MOD(SUB,4)/2
         200 F(K+4) - MOD(SUB,2)
C                LOOP WHICH DOES THE P PERMUTATION OPERATION TO
THE 32-BIT RESULT
C                AND ALSO DOES THE XOR OF THE OLD L AND THE NEW
RESULT OF THE F FUNCTION.
                 DO 300 J=1,32
            R(J)-1
300              IF (L(J) .EQ. F(P(J))) R(J)-0

C           SETS THE NEW L TO BE THE OLD R THAT HAD BEEN SAVED.
            DO 400 J=1,32
400         L(J)=TEMPL(J)
500         CONTINUE
C           DOES THE INVERSE PERMUTATION AFTER THE 16 ROUNDS
TO COMPLETE THE DES. DO
            600 J=1,64
600         OUTPUT(J)=LR(REVIPI(J))
            END
            SUBROUTINE SETKEY (KEY)
C           SUBROUTINE TO PERFORM DES KEY SCHEDULE
C           PRODUCED BY THE NATIONAL BUREAU OF STANDARDS
C           NOT SUBJECT TO COPYRIGHT - NOT SUPPORTED BY NBS
            IMPLICIT INTEGER (A-Z)
            INTEGER KEY(64)
C           KS IS THE COMMON AREA WITH THE DES SUBROUTINE. 
SETKEY MUST SET KS
C           BEFORE THE DES IS CALLED OR GARBAGE WILL RESULT
FROM THE DES. INTEGER
            KS(48.16).CD(56).C(28).D(28)
            COMMON KS
            EQUIVALENCE (CD(1), C(1)), (CD(29),D(1))
C           PCI IS THE PERMUTED CHOICE 1 DEFINED IN THE DES
            INTEGER PCI(56)/
         1 57,49,41,33,25,17,09,
         1 01,58,50,42,34,26,18,
         1 10,02,59,51,43,35,27,
         1 19,11,03,60.52,44,36,
         1 63,55,47,39,31,23,15,
         1 07,62,54,46,38,30,22,
         1 14,06,61,53,45,37,29,
         1 21,13,05,28,20,12,04/
C           PC2 IS THE PERMUTED CHOICE 2 DEFINED IN THE DES.
            INTEGER PC2(48)/
            1 14,17,11,24,01,05,
         1 03,28,15,06,21,10,
         1 23,19,12,04,26,08,
         1 16,07,27,20,13,02,
         1 41,52,31,37,47,55,
         1 30,40,51,45,33,48,
         1 44,49,39,56,34,53,
         1 46,42,50,36,29,32/
C           KSFT IS THE KEY SHIFT VECTOR DEFINED IN THE DES.
         INTEGER KSFT(16)/1.1,2,2,2,2,2.2,1,2,2,2,2,2,2,1/
C           LOOP WHICH PERFORMS THE FIRST PERMUTATION ON
THE KEY, REMOVING THE
C           PARITY BITS AND SETTING UP THE C AND D REGISTERS.
         DO 100 1=1,56
100         OD(I)=KEY(PCI(I))
C           LOOP WHICH COMPUTES THE KS ARRAY FOR THE DES. 
THIS TECHNIQUE USES
C           LOTS OF MEMORY BUT RUNS FAST.  THE KS NEED ONLY BE
COMPUTED ONCE
C           FOR ALL THE ENCRYPT AND DECRYPT OPERATIONS
WHICH USE THIS KEY. DO 500
            1=1,16
            DO 300 J=1,KSFT(I)
            CT=C(1)
            DT=D(1)

         DO 200 K=1,27
            C(K)=C(K+1)
200         D(K)=D(K+1)
         C(28)=DT
300      D(28)=DT
         DO 400 J=1,48
400         KS(J,I)=CD(PC2(J))
500         CONTINUE 
END