'===========================================================================
' Subject: DATA ENCRYPTION STANDARD           Date: 02-17-98 (20:06)       
'  Author: Scott Spiker                       Code: QB, QBasic, PDS        
'  Origin: pspiker@concentric.net           Packet: ALGOR.ABC
'===========================================================================
DEFINT A-Z
DECLARE FUNCTION Des$ (EncryptFlag%, Key$, Txt$)

'It is suggested that this module be loaded into a main module and the DES
'function called from the main (or other) modules. Do not added code to this
'module.
'
'This is not the fastest implementation of DES. However, it does work and
'it is implemented strictly in QB45 to show that it can be. There are
'plenty of areas to improve this routine for speed without going to ASM
'code. But ASM DES routines are significantly faster than this one.


'Initial Permutaion Table
DATA 58,50,42,34,26,18,10,02,60,52,44,36,28,20,12,04
DATA 62,54,46,38,30,22,14,06,64,56,48,40,32,24,16,08
DATA 57,49,41,33,25,17,09,01,59,51,43,35,27,19,11,03
DATA 61,53,45,37,29,21,13,05,63,55,47,39,31,23,15,07

'Key Permutaion Table
DATA 57,49,41,33,25,17,09,01,58,50,42,34,26,18
DATA 10,02,59,51,43,35,27,19,11,03,60,52,44,36
DATA 63,55,47,39,31,23,15,07,62,54,46,38,30,22
DATA 14,06,61,53,45,37,29,21,13,05,28,20,12,04

'Compression Permutaion Table
DATA 14,17,11,24,01,05,03,28,15,06,21,10
DATA 23,19,12,04,26,08,16,07,27,20,13,02
DATA 41,52,31,37,47,55,30,40,51,45,33,48
DATA 44,49,39,56,34,53,46,42,50,36,29,32

'Expansion Permutation Table
DATA 32,01,02,03,04,05,04,05,06,07,08,09
DATA 08,09,10,11,12,13,12,13,14,15,16,17
DATA 16,17,18,19,20,21,20,21,22,23,24,25
DATA 24,25,26,27,28,29,28,29,30,31,32,01

'P-Box Table
DATA 16,07,20,21,29,12,28,17,01,15,23,26,05,18,31,10
DATA 02,08,24,14,32,27,03,09,19,13,30,06,22,11,04,25

'Final Permution Table
DATA 40,08,48,16,56,24,64,32,39,07,47,15,55,23,63,31
DATA 38,06,46,14,54,22,62,30,37,05,45,13,53,21,61,29
DATA 36,04,44,12,52,20,60,28,35,03,43,11,51,19,59,27
DATA 34,02,42,10,50,18,58,26,33,01,41,09,49,17,57,25

'S-Boxes
'S-Box 1
DATA 14,04,13,01,02,15,11,08,03,10,06,12,05,09,00,07
DATA 00,15,07,04,14,02,13,01,10,06,12,11,09,05,03,08
DATA 04,01,14,08,13,06,02,11,15,12,09,07,03,10,05,00
DATA 15,12,88,02,04,09,01,07,05,11,03,14,10,00,06,13

'S-Box 2
DATA 15,01,08,14,06,11,03,04,09,07,02,13,12,00,05,10
DATA 03,13,04,07,15,02,08,14,12,00,01,10,06,09,11,05
DATA 00,14,07,11,10,04,13,01,05,08,12,06,09,03,02,15
DATA 13,08,10,01,03,15,04,02,11,06,07,12,00,05,14,09

'S-Box 3
DATA 10,00,09,14,06,03,15,05,01,13,12,07,11,04,02,08
DATA 13,07,00,09,03,04,06,10,02,08,05,14,12,11,15,01
DATA 13,06,04,09,08,15,03,00,11,01,02,12,05,10,14,07
DATA 01,10,13,00,06,09,08,07,04,15,14,03,11,05,02,12

'S-Box -4
DATA 07,13,14,03,00,06,09,10,01,02,08,05,11,12,04,15
DATA 13,08,11,05,06,15,00,03,04,07,02,12,01,10,14,09
DATA 10,06,09,00,12,11,07,13,15,01,03,14,05,02,08,04
DATA 03,15,00,06,10,01,13,08,09,04,05,11,12,07,02,14

'S-Box 5
DATA 02,12,04,01,07,10,11,06,08,05,03,15,13,00,14,09
DATA 14,11,02,12,04,07,13,01,05,00,15,10,03,09,08,06
DATA 04,02,01,11,10,13,07,08,15,09,12,05,06,03,00,14
DATA 11,08,12,07,01,14,02,13,06,15,00,09,10,04,05,03

'S-Box 6
DATA 12,01,10,15,09,02,06,08,00,13,03,04,14,07,05,11
DATA 10,15,04,02,07,12,09,05,06,01,13,14,00,11,03,08
DATA 09,14,15,05,02,08,12,03,07,00,04,10,01,13,11,06
DATA 04,03,02,12,09,05,15,10,11,14,01,07,06,00,08,13

'S-Box 7
DATA 04,11,02,14,15,00,08,13,03,12,09,07,05,10,06,01
DATA 13,00,11,07,04,09,01,10,14,03,05,12,02,15,08,06
DATA 01,04,11,13,12,03,07,14,10,15,06,08,00,05,09,02
DATA 06,11,13,08,01,04,10,07,09,05,00,15,14,02,03,12

'S-Box 8
DATA 13,02,08,04,06,15,11,01,10,09,03,14,05,00,12,07
DATA 01,15,13,08,10,03,07,04,12,05,06,11,00,14,09,02
DATA 07,11,04,01,09,12,14,02,00,06,10,13,15,03,05,08
DATA 02,01,14,07,04,10,08,13,15,12,09,00,03,05,06,11

FUNCTION Des$ (EncryptFlag%, Key$, Txt$) STATIC
     'EncryptFlag%     1=Encrypt
     '                 0=Decrypt
     'Key$             Char value of key
     'Txt$             Char value of text to encrypt/decrypt

     DIM k$(0 TO 16)
     DIM IpTbl(64)
     DIM KpTbl(65)
     DIM PBoxTbl(32)
     DIM CPTbl(48)
     DIM EpTbl(48)
     DIM FpTbl(64)
     DIM SBox(8, 4, 16)

     IF LEN(LastKey$) = 0 THEN                    'Set up first time thru
          'Initialize strings used in the routine
          'to get them to the correct length.
          'It is much faster to use MID$(A$...)=g$
          'than using a$ = g$
         
          Zero$ = STRING$(64, "0")                'Set up a zero buffer
          TextBits$ = Zero$                       'Set up buffers for correct length
          KeyBits$ = Zero$
          InvIp$ = Zero$
          cd$ = MID$(Zero$, 1, 58)
          Ep$ = MID$(Zero$, 1, 48)
          TxtL$ = MID$(Zero$, 1, 32)
          TxtR$ = TxtL$
          Tmp$ = TxtL$
          PermP$ = TxtL$

          LastKey$ = MID$(Zero$, 1, 8)
          b$ = MID$(Zero$, 1, 6)
          n$ = MID$(Zero$, 1, 4)
   
          FOR x = 0 TO 16
               k$(x) = SPACE$(56)
          NEXT x

          'Read in table data
          FOR x = 1 TO 64
               READ IpTbl(x)
          NEXT x

          FOR x = 1 TO 56
               READ KpTbl(x)
          NEXT x

          FOR x = 1 TO 48
               READ CPTbl(x)
          NEXT x

          FOR x = 1 TO 48
               READ EpTbl(x)
          NEXT x

          FOR x = 1 TO 32
               READ PBoxTbl(x)
          NEXT x

          FOR x = 1 TO 64
               READ FpTbl(x)
          NEXT x

          FOR x = 1 TO 8
               FOR y = 0 TO 3
                    FOR z = 0 TO 15
                         READ SBox(x, y, z)
                    NEXT z
               NEXT y
          NEXT x
     END IF

     '***** Initial Permutation of Clear Text
     ko = 0                                       'kOffset
     MID$(TextBits$, 1, 64) = Zero$

     FOR x = 1 TO 8
          ByteVal = ASC(MID$(Txt$, x, 1))
          o = 8                                   'Offset, Start at right most bit
   
          WHILE ByteVal > 0
               Bit = ByteVal MOD 2
               ByteVal = ByteVal \ 2
               IF Bit THEN
                    MID$(TextBits$, ko + o, 1) = "1"
               END IF
               o = o - 1
          WEND
          ko = ko + 8
     NEXT x
 
     FOR x = 1 TO 32
          MID$(TxtL$, x, 1) = MID$(TextBits$, IpTbl(x), 1)
          MID$(TxtR$, x, 1) = MID$(TextBits$, IpTbl(x + 32), 1)
     NEXT x
 
     IF LastKey$ <> Key$ THEN                     'Get key schedule
          ko = 0
          MID$(KeyBits$, 1, 64) = Zero$           'Pre-load with zeors
          FOR x = 1 TO 8
               ByteVal = ASC(MID$(Key$, x, 1))
               o = 8                              'Start at right most bit
               WHILE ByteVal > 0
                    Bit = ByteVal MOD 2
                    ByteVal = ByteVal \ 2
                    IF Bit THEN
                         MID$(KeyBits$, ko + o, 1) = "1"
                    END IF
                    o = o - 1
               WEND
               ko = ko + 8
          NEXT x
   
          '***** Key Permutation
          FOR x = 1 TO 28
               MID$(cd$, x, 1) = MID$(KeyBits$, KpTbl(x), 1)
               MID$(cd$, x + 28, 1) = MID$(KeyBits$, KpTbl(x + 28), 1)
          NEXT x
   
          '***** Calculate key schedule k[1] - k[16]
          FOR i = 1 TO 16
               SELECT CASE i
                    CASE 1, 2, 9, 16              'Single shift for these iterations
                         MID$(cd$, 57, 1) = MID$(cd$, 1, 1)
                         MID$(cd$, 1, 27) = MID$(cd$, 2, 27)
                         MID$(cd$, 28, 1) = MID$(cd$, 57, 1)

                         MID$(cd$, 57, 1) = MID$(cd$, 29, 1)
                         MID$(cd$, 29, 27) = MID$(cd$, 30, 27)
                         MID$(cd$, 56, 1) = MID$(cd$, 57, 1)
         
                    CASE ELSE                     'Double shift for rest
                         MID$(cd$, 57, 2) = MID$(cd$, 1, 2)
                         MID$(cd$, 1, 26) = MID$(cd$, 3, 26)
                         MID$(cd$, 27, 2) = MID$(cd$, 57, 2)

                         MID$(cd$, 57, 2) = MID$(cd$, 29, 2)
                         MID$(cd$, 29, 26) = MID$(cd$, 31, 26)
                         MID$(cd$, 55, 2) = MID$(cd$, 57, 2)
               END SELECT
 
               FOR x = 1 TO 48
                    MID$(k$(i), x, 1) = MID$(cd$, CPTbl(x), 1)
               NEXT x
          NEXT i
     END IF
 
     IF EncryptFlag THEN
          PStart = 1
          PEnd = 16
          Direction = 1
     ELSE
          PStart = 16
          PEnd = 1
          Direction = -1
     END IF

     FOR i = PStart TO PEnd STEP Direction
          '***** Expand Permutaion
          FOR x = 1 TO 48
               MID$(Ep$, x, 1) = MID$(TxtR$, EpTbl(x), 1)
          NEXT x
    
          'XOR Ep$ with k$(i), result into Ep$
          FOR x = 1 TO 48
               Bit1 = ASC(MID$(Ep$, x, 1))
               Bit2 = ASC(MID$(k$(i), x, 1))
               IF Bit1 XOR Bit2 THEN
                    MID$(Ep$, x, 1) = "1"
               ELSE
                    MID$(Ep$, x, 1) = "0"
               END IF
          NEXT x
   
          o = 1                                    'Offset into Ep$
          tmpo = o                                 'Offset into Tmp$
          FOR j = 1 TO 8
               MID$(b$, 1, 6) = MID$(Ep$, o, 6)
               o = o + 6
     
               MID$(n$, 1, 1) = MID$(b$, 1, 1)
               MID$(n$, 2, 1) = MID$(b$, 6, 1)
     
               m = 0
               FOR k = 2 TO 1 STEP -1
                    Cmp = ASC(MID$(n$, k, 1))
                    IF Cmp = 49 THEN                     '49 = "1"
                         m = m + (2 ^ (2 - k))
                    END IF
               NEXT k
     
               MID$(n$, 1, 4) = MID$(b$, 2, 4)
     
               n = 0
               FOR k = 4 TO 1 STEP -1
                    Cmp = ASC(MID$(n$, k, 1))
                    IF Cmp = 49 THEN                     '49 = "1"
                         n = n + (2 ^ (4 - k))
                    END IF
               NEXT k
     
               'Borrow LaskKey$ since its length is 8
               MID$(LastKey$, 1, 8) = "00000000"  'Preload with "0"'s, ten only
                                                  'only have to update "1"'s

               nm = SBox(j, m, n)
               bo = 8                                 'Start at right most bit
               WHILE nm > 0
                    Bit = nm MOD 2
                    nm = nm \ 2
                    IF Bit THEN
                         MID$(LastKey$, bo, 1) = "1"
                    END IF
                    bo = bo - 1
               WEND

               MID$(Tmp$, tmpo, 4) = MID$(LastKey$, 5, 4)
               tmpo = tmpo + 4
          NEXT j
   
          FOR x = 1 TO 32
               MID$(PermP$, x, 1) = MID$(Tmp$, PBoxTbl(x), 1)
          NEXT x
    
          'I am done with Tmp$, so I can reuse it here
    
 
          'XOR TxtL$ with PermP$, result into Tmp$ since I am done with
          'it in previous loop
          FOR x = 1 TO 32
               Bit1 = ASC(MID$(TxtL$, x, 1))
               Bit2 = ASC(MID$(PermP$, x, 1))
               IF Bit1 XOR Bit2 THEN
                    MID$(Tmp$, x, 1) = "1"
               ELSE
                    MID$(Tmp$, x, 1) = "0"
               END IF
          NEXT x
   
          MID$(TxtL$, 1, 32) = TxtR$
          MID$(TxtR$, 1, 32) = Tmp$
     NEXT i
 
     '***** Inverse Initial Permutation
     MID$(TextBits$, 1, 32) = TxtR$
     MID$(TextBits$, 33, 32) = TxtL$
     FOR x = 1 TO 64
          MID$(InvIp$, x, 1) = MID$(TextBits$, FpTbl(x), 1)
     NEXT x


     'Convert the string of "1"s and "0"s to the character format
     'will borrow LastKey$ since its length is 8.
     o = 0
     FOR x = 1 TO 64 STEP 8
          o = o + 1
          Byte$ = MID$(InvIp$, x, 8)
   
          ByteVal = 0
          FOR k = 8 TO 1 STEP -1
               Cmp = ASC(MID$(Byte$, k, 1))
               IF Cmp = 49 THEN                         '49 = "1"
                    ByteVal = ByteVal + (2 ^ (8 - k))
               END IF
          NEXT
   
          MID$(LastKey$, o, 1) = CHR$(ByteVal)
     NEXT x
 
     Des$ = LastKey$
     MID$(LastKey$, 1, 8) = Key$
END FUNCTION

SUB DES.Read.Me
'***********************************************************************
'***** I Found this great description on implementing DES on the   *****
'***** internet. I can't remember where, but a search should find  *****
'***** it again. I used this to learn and write this module.       *****
'***** Thanks Matthew Fischer for the great document.              *****
'***********************************************************************
'
'                          How to implement the            
'                      DATA Encryption Standard (DES)
'
'                        A step by step tutorial
'                              Version 1.24
'
'
'The Data Encryption Standard (DES) algorithm, adopted by the U.S.
'government in 1977, is a block cipher that transforms 64-bit data
'blocks under a 56-bit secret key, by means of permutation and
'substitution. It is officially described in FIPS PUB 46. The DES
'algorithm is widely used and is still considered reasonably secure.
'
'This is a tutorial designed to be clear and compact, and to provide a
'newcomer to the DES with all the necessary information to implement it
'himself, without having to track down printed works or wade through C
'source code. I welcome any comments.
' Matthew Fischer <mfischer@heinous.music.uiowa.edu>
'
'
'Here's how to do it, step by step:
'
' 1  Process the key.
'
' 1.1  Get a 64-bit key from the user. (Every 8th bit (the least
'significant bit of each byte) is considered a parity bit. For a key to
'have correct parity, each byte should contain an odd number of "1"
'bits.) This key can be entered directly, or it can be the result of
'hashing something else. There is no standard hashing algorithm for this
'purpose.
'
' 1.2  Calculate the key schedule.
'
' 1.2.1  Perform the following permutation on the 64-bit key. (The
'parity bits are discarded, reducing the key to 56 bits. Bit 1 (the most
'significant bit) of the permuted block is bit 57 of the original key,
'bit 2 is bit 49, and so on with bit 56 being bit 4 of the original key.)
'
'                        Permuted Choice 1 (PC-1)
'
'                          57 49 41 33 25 17  9
'                           1 58 50 42 34 26 18
'                          10  2 59 51 43 35 27
'                          19 11  3 60 52 44 36
'                          63 55 47 39 31 23 15
'                           7 62 54 46 38 30 22
'                          14  6 61 53 45 37 29
'                          21 13  5 28 20 12  4
'
' 1.2.2  Split the permuted key into two halves. The first 28 bits are
'called C[0] and the last 28 bits are called D[0].
'
' 1.2.3  Calculate the 16 subkeys. Start with i = 1.
'
' 1.2.3.1  Perform one or two circular left shifts on both C[i-1] and
'D[i-1] to get C[i] and D[i], respectively. The number of shifts per
'iteration are given in the table below.
'
'    Iteration #   1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16
'    Left Shifts   1  1  2  2  2  2  2  2  1  2  2  2  2  2  2  1
'
' 1.2.3.2  Permute the concatenation C[i]D[i] as indicated below. This
'will yield K[i], which is 48 bits long.
'
'                        Permuted Choice 2 (PC-2)
'
'                           14 17 11 24  1  5
'                            3 28 15  6 21 10
'                           23 19 12  4 26  8
'                           16  7 27 20 13  2
'                           41 52 31 37 47 55
'                           30 40 51 45 33 48
'                           44 49 39 56 34 53
'                           46 42 50 36 29 32
'
' 1.2.3.3  Loop back to 1.2.3.1 until K[16] has been calculated.
'
' 2  Process a 64-bit data block.
'
' 2.1  Get a 64-bit data block. If the block is shorter than 64 bits, it
'should be padded as appropriate for the application.
'
' 2.2  Perform the following permutation on the data block.
'
'                        Initial Permutation (IP)
'
'                        58 50 42 34 26 18 10  2
'                        60 52 44 36 28 20 12  4
'                        62 54 46 38 30 22 14  6
'                        64 56 48 40 32 24 16  8
'                        57 49 41 33 25 17  9  1
'                        59 51 43 35 27 19 11  3
'                        61 53 45 37 29 21 13  5
'                        63 55 47 39 31 23 15  7
'
' 2.3  Split the block into two halves. The first 32 bits are called
'L[0], and the last 32 bits are called R[0].
'
' 2.4  Apply the 16 subkeys to the data block. Start with i = 1.
'
' 2.4.1  Expand the 32-bit R[i-1] into 48 bits according to the
'bit-selection function below.
'
'                             Expansion (E)
'
'                           32  1  2  3  4  5
'                            4  5  6  7  8  9
'                            8  9 10 11 12 13
'                           12 13 14 15 16 17
'                           16 17 18 19 20 21
'                           20 21 22 23 24 25
'                           24 25 26 27 28 29
'                           28 29 30 31 32  1
'
' 2.4.2  Exclusive-or E(R[i-1]) with K[i].
'
' 2.4.3  Break E(R[i-1]) xor K[i] into eight 6-bit blocks. Bits 1-6 are
'B[1], bits 7-12 are B[2], and so on with bits 43-48 being B[8].
'
' 2.4.4  Substitute the values found in the S-boxes for all B[j]. Start
'with j = 1. All values in the S-boxes should be considered 4 bits wide.
'
' 2.4.4.1  Take the 1st and 6th bits of B[j] together as a 2-bit value
'(call it m) indicating the row in S[j] to look in for the substitution.
'
' 2.4.4.2  Take the 2nd through 5th bits of B[j] together as a 4-bit
'value (call it n) indicating the column in S[j] to find the substitution.
'
' 2.4.4.3  Replace B[j] with S[j][m][n].
'
'                       Substitution Box 1 (S[1])
'
'            14  4 13  1  2 15 11  8  3 10  6 12  5  9  0  7
'             0 15  7  4 14  2 13  1 10  6 12 11  9  5  3  8
'             4  1 14  8 13  6  2 11 15 12  9  7  3 10  5  0
'            15 12  8  2  4  9  1  7  5 11  3 14 10  0  6 13
'
'                                  S[2]
'
'            15  1  8 14  6 11  3  4  9  7  2 13 12  0  5 10
'             3 13  4  7 15  2  8 14 12  0  1 10  6  9 11  5
'             0 14  7 11 10  4 13  1  5  8 12  6  9  3  2 15
'            13  8 10  1  3 15  4  2 11  6  7 12  0  5 14  9
'
'                                  S[3]
'
'            10  0  9 14  6  3 15  5  1 13 12  7 11  4  2  8
'            13  7  0  9  3  4  6 10  2  8  5 14 12 11 15  1
'            13  6  4  9  8 15  3  0 11  1  2 12  5 10 14  7
'             1 10 13  0  6  9  8  7  4 15 14  3 11  5  2 12
'
'                                  S[4]
'
'             7 13 14  3  0  6  9 10  1  2  8  5 11 12  4 15
'            13  8 11  5  6 15  0  3  4  7  2 12  1 10 14  9
'            10  6  9  0 12 11  7 13 15  1  3 14  5  2  8  4
'             3 15  0  6 10  1 13  8  9  4  5 11 12  7  2 14
'
'                                  S[5]
'
'             2 12  4  1  7 10 11  6  8  5  3 15 13  0 14  9
'            14 11  2 12  4  7 13  1  5  0 15 10  3  9  8  6
'             4  2  1 11 10 13  7  8 15  9 12  5  6  3  0 14
'            11  8 12  7  1 14  2 13  6 15  0  9 10  4  5  3
'
'                                  S[6]
'
'            12  1 10 15  9  2  6  8  0 13  3  4 14  7  5 11
'            10 15  4  2  7 12  9  5  6  1 13 14  0 11  3  8
'             9 14 15  5  2  8 12  3  7  0  4 10  1 13 11  6
'             4  3  2 12  9  5 15 10 11 14  1  7  6  0  8 13
'
'                                  S[7]
'
'             4 11  2 14 15  0  8 13  3 12  9  7  5 10  6  1
'            13  0 11  7  4  9  1 10 14  3  5 12  2 15  8  6
'             1  4 11 13 12  3  7 14 10 15  6  8  0  5  9  2
'             6 11 13  8  1  4 10  7  9  5  0 15 14  2  3 12
'
'                                  S[8]
'
'            13  2  8  4  6 15 11  1 10  9  3 14  5  0 12  7
'             1 15 13  8 10  3  7  4 12  5  6 11  0 14  9  2
'             7 11  4  1  9 12 14  2  0  6 10 13 15  3  5  8
'             2  1 14  7  4 10  8 13 15 12  9  0  3  5  6 11
'
' 2.4.4.4  Loop back to 2.4.4.1 until all 8 blocks have been replaced.
'
' 2.4.5  Permute the concatenation of B[1] through B[8] as indicated below.
'
'                             Permutation P
'
'                              16  7 20 21
'                              29 12 28 17
'                               1 15 23 26
'                               5 18 31 10
'                               2  8 24 14
'                              32 27  3  9
'                              19 13 30  6
'                              22 11  4 25
'
' 2.4.6  Exclusive-or the resulting value with L[i-1]. Thus, all together,
'your R[i] = L[i-1] xor P(S[1](B[1])...S[8](B[8])), where B[j] is a 6-bit
'block of E(R[i-1]) xor K[i]. (The function for R[i] is more concisely
'written as, R[i] = L[i-1] xor f(R[i-1], K[i]).)
'
' 2.4.7  L[i] = R[i-1].
'
' 2.4.8  Loop back to 2.4.1 until K[16] has been applied.
'
' 2.5  Perform the following permutation on the block R[16]L[16]. (Note
'that block R precedes block L this time.)
'
'                       Final Permutation (IP**-1)
'
'                        40  8 48 16 56 24 64 32
'                        39  7 47 15 55 23 63 31
'                        38  6 46 14 54 22 62 30
'                        37  5 45 13 53 21 61 29
'                        36  4 44 12 52 20 60 28
'                        35  3 43 11 51 19 59 27
'                        34  2 42 10 50 18 58 26
'                        33  1 41  9 49 17 57 25
'
'
'This has been a description of how to use the DES algorithm to encrypt
'one 64-bit block. To decrypt, use the same process, but just use the keys
'K[i] in reverse order. That is, instead of applying K[1] for the first
'iteration, apply K[16], and then K[15] for the second, on down to K[1].
'
'Summaries:
'
' Key schedule:
'  C[0]D[0] = PC1(key)
'  for 1 <= i <= 16
'   C[i] = LS[i](C[i-1])
'   D[i] = LS[i](D[i-1])
'   K[i] = PC2(C[i]D[i])
'
' Encipherment:
'  L[0]R[0] = IP(plain block)
'  for 1 <= i <= 16
'   L[i] = R[i-1]
'   R[i] = L[i-1] xor f(R[i-1], K[i])
'  cipher block = FP(R[16]L[16])
'
' Decipherment:
'  R[16]L[16] = IP(cipher block)
'  for 1 <= i <= 16
'   R[i-1] = L[i]
'   L[i-1] = R[i] xor f(L[i], K[i])
'  plain block = FP(L[0]R[0])
'
'
'To encrypt or decrypt more than 64 bits there are four official modes
'(defined in FIPS PUB 81). One is to go through the above-described
'process for each block in succession. This is called Electronic Codebook
'(ECB) mode. A stronger method is to exclusive-or each plaintext block
'with the preceding ciphertext block prior to encryption. (The first
'block is exclusive-or'ed with a secret 64-bit initialization vector
'(IV). This IV is generally a random value that is kept with the key.)
'This is called Cipher Block Chaining (CBC) mode. The other two modes
'are Output Feedback (OFB) and Cipher Feedback (CFB).
'
'When it comes to padding the data block, there are several options. One
'is to simply append zeros. Two suggested by FIPS PUB 81 are, if the
'data is binary data, fill up the block with bits that are the opposite
'of the last bit of data, or, if the data is ASCII data, fill up the
'block with random characters and put the ASCII character for the number
'of pad characters in the last byte of the block.
'
'The DES algorithm can also be used to calculate cryptographic checksums
'up to 64 bits long (see FIPS PUB 113). If the number of data bits to be
'checksummed is not a multiple of 64, the last data block should be
'padded with zeros. If the data is ASCII data, the most significant bit
'of each byte should be set to 0. The data is then encrypted in CBC mode
'with IV = 0. The most significant n bits (where 16 <= n <= 64, and n is
'a multiple of 8) of the final ciphertext block are an n-bit checksum.
'
'(Matthew Fischer   November 1995)

END SUB
