'===========================================================================
' Subject: RC4 INIT VECTOR ENCRYPTION         Date: 03-10-00 (13:16)       
'  Author: Randall L. Glass                   Code: PB                     
'  Origin: rlglass@yahoo.com                Packet: PB.ABC
'===========================================================================
'---------------------------------------------------------------------------
'                   RC4 Initalization Vector Encryption
'
'                           By Randall L Glass
'                             Copyright 2000
'
' Permission is given to use RC4 Initalization Vector Encryption in any way
' you want as long as you give me credit somewhere in your program or
' documentation.
'---------------------------------------------------------------------------
' RC4IVE gives an medium amount of security.
'
' For maxium security see my Pretty Good Encryption program.
'
' RC4IVE produces almost completely an random output. Some think that the NSA
' can break RC4.
'
' RC4IVE starts out by choosing random numbers for an Initialization Vector.
'
' It then encrypts the IV producing a Feedback String.
'
' RC4IVE then XOR'S the Feedback String with the Plain Text block. Thus even
' if the snoop had choosen an Plain Text;their Plain Text just got encrypted.
' It won't do him any good.
'
' Then we use RC4 to substitute one number for an other by XORing an random
' number output with a number produced by the previous XOR.
'
' The Encrypted string block then becomes then new Feedback String.
'
' After the Plain Text is encrypted, the IV is then attached to the beggining
' of the encrypted text.
'
' You might think that we should of encrypted the IV before attaching It to
' the encrypted string; BUT that would have SERVERLY WEAKEN the security of
' the encrypted string !
'
' We do not want anyone to know what the inital Feedback String is.
'
' By using an different Initialization Vector each time, you can use the same
' key over and over again and still be fairly secure.
'
' You should always use an key length of 256 bytes for maxium security.
'
'---------------------------------------------------------------------------

$CPU 80386
DEFINT A-Z
DECLARE FUNCTION GetStrLoc(BYVAL AllocHandle%) AS LONG

CLS

' You can change the block size by changing %blocksize and %Shift8

%BlockSize = 8: %Shift8 = 3:%DoubleWords = 8\4    'Shift = 2^3

DIM Rc4Key%(255),FeedBack AS SHARED STRING * %BlockSize
SHARED RI?,RJ?
SHARED Rc4Key%()

RANDOMIZE TIMER

FLEXCHR$ = CHR$(0)

CodeKey$ = "TEST KEY"                       '  Set a key
                                            '  should be 256 bytes long
CLS                                         '  to get the maxium security

InitKey CodeKey$
Rc4Init                                   'Initialize the key schedule

PlainText$ = "ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ"

Encrypt PlainText$,CipherText$          'Encrypt the string

Rc4Init                                 're-Initialize the key
Decrypt CipherText$,PlainText2$         'Decrypt the string
END

SUB Encrypt(PlainText AS STRING,CipherText AS STRING)
  ' This uses an feedback mode to prevent choosen plaintext attacks and
  ' enables one to use the same key over and over again
 STATIC InitFlag%
 IF InitFlag% = 0 THEN
	IV$ = RndIV$
        EncryptedIV$ = IV$
        CodeString EncryptedIV$,0
        LSET FeedBack$ = EncryptedIV$
 END IF

 CipherText$ = PlainText$

 Ln?? = LEN(CipherText$)
 ExtraLetters% = Ln?? MOD %BlockSize

 IF ExtraLetters% THEN
        AddPadding% = %BlockSize - ExtraLetters%
        CipherText$ = CipherText$ + STRING$(AddPadding%,0)
        INCR Ln??,AddPadding%
 END IF

 Strings% = Ln??\%BlockSize

 FOR I% = 0 TO Strings% -1
        XorStr CipherText$, FeedBack$, I%
        CodeString CipherText$,I%
        LSET FeedBack$ =  MID$(CipherText$,I% * %BlockSize + 1,%BlockSize)
 NEXT I%

 IF InitFlag% = 0 THEN
        CipherText$ = IV$ + CipherText$
        InitFlag% = 1
 END IF
END SUB

FUNCTION Decrypt$(CipherText$,PlainText$)
 DIM Temp AS STRING * %BlockSize
 STATIC InitFlag%
 StartString% = 0
 IF InitFlag% = 0 THEN
        IV$ = LEFT$(CipherText$,%BlockSize)
        EncryptedIV$ = IV$
        CodeString EncryptedIV$,0
        LSET FeedBack$ = EncryptedIV$
        StartString% = 1
 END IF

 PlainText$ = CipherText$
 Strings% = LEN(CipherText$)\%BlockSize

 FOR I% = StartString% TO Strings% -1
        LSET Temp$ = MID$(PlainText$,I% * %BlockSize + 1,%BlockSize)
        CodeString PlainText$,I%
        XorStr PlainText$,FeedBack$,I%
        LSET FeedBack$ = Temp$
 NEXT I%
 IF InitFlag% = 0 THEN
        PlainText$ = MID$(PlainText$,%BlockSize+1)
        InitFlag% = 1
 END IF
 PlainText$ = RTRIM$(PlainText$,CHR$(0))
END FUNCTION

FUNCTION RndIV$
 PRINT "Enter the word Secret And press Enter"
 DO
	DO
	        ky$ = inkey$
		RndNum&& = RND(1,1000000000000)
	LOOP UNTIL Ky$ <> ""

        PRINT Ky$;
        RANDOMIZE RndNum&&
 LOOP UNTIL ky$ = CHR$(13)

FOR I% = 1 TO %BlockSize
        Temp$ = Temp$ + CHR$(RND(0,255))
NEXT I%
RndIV$ = Temp$
END FUNCTION

SUB InitKey(CodeKey$)
  DIM StringStart AS WORD
  ! LES BX, CodeKey$
  ! MOV AX,ES:[BX]
  ! PUSH AX
  ! CALL GetStrLoc          ; find where the data is located
  ! MOV ES, DX              ; put segment in ES
  ! MOV DI, AX              ; put offset in DI
  ! MOV StringStart??,DI
  ! DEC StringStart??
  ! MOV SI,DI
  ! ADD SI,CX               ;SI = end of CodeKey$
  ! DEC SI
  ! MOV CX,256
  ! MOV BX,0
InitKeyStr:
  ! MOV AL,ES:[DI]
  ! MOV KeyBlock?[BX],AL
  ! CMP DI,SI
  ! JNE Skip
  ! MOV DI,StringStart??
  Skip:
  ! INC BX
  ! INC DI
  ! LOOP InitKeyStr
END SUB

SUB Rc4Init()
RI? = 0:RJ? = 0
FeedBack$ = STRING$(8,CHR$(255))
! MOV BX,0             ;BL = I
! MOV CX,256
InitSBlock:
! MOV SBLOCK?[BX],BL   ;SBlock?(I) = I
! INC BL
! LOOP InitSBlock

! MOV BX,0      ;BX = J
! MOV DI,0      ;DI = I
! MOV CX,256
InitSblock2:
! ADD BL,SBlock?[DI]
! ADD BL,KeyBlock?[DI]
! MOV AL,SBlock[BX]
! MOV AH,SBLOCK[DI]
! MOV SBlock[BX],AH
! MOV SBLOCK[DI],AL
! INC DI
! LOOP InitSblock2
END SUB

SUB XorStr(Str1 AS STRING ,Str2 AS STRING * %BlockSize,BYVAL Index%)
! LES BX, Str1$
! MOV AX,ES:[BX]
! PUSH AX
! CALL GetStrLoc          ; find where the data is located
! MOV ES, DX              ; put segment in ES
! MOV DI, AX              ; put offset in DI
! MOV AX,Index%
! MOV CL,%Shift8          ;Multiply AX by %BlockSize
! SHL AX,CL
! ADD DI,AX               ;adjust address
! PUSH DS
! LDS SI,Str2$
! MOV CX, %DoubleWords
XorLoop2:
! DB &H66         ;LODSD
! DB &HAD
! DB &H66         ;XOR ES:[DI],EAX
! DB &H26
! DB &H31
! DB &H05
! ADD DI,4
! LOOP XorLoop2
! POP DS
END SUB

SUB CodeString(CText$,BYVAL Index%)

! LES DI,CText$
! MOV AX,ES:[DI]
! PUSH AX
! CALL GetStrLoc          ; find where the data is located
! MOV ES, DX              ; put segment in ES
! MOV DI, AX              ; put offset in DI
! MOV BX,Index%
! MOV CL,%Shift8          ;Multiply AX by %BlockSize
! SHL BX,CL
! ADD DI,BX               ;adjust address

! MOV CX,%BlockSize
EncodeIt:
! PUSH DI
! CALL RC4K
! POP DI
! XOR ES:[DI],AL
! INC DI
! LOOP EncodeIt

EXIT SUB
Rc4K:
 ! MOV AX,RI?
 ! INC AL
 ! MOV RI?,AX
 ! MOV DI,AX
 ! MOV DX,RJ?
 ! ADD DL,SBLOCK?[DI]
 ! MOV SI,DX
 ! MOV RJ? ,DX
 ! MOV BL,SBLOCK?[DI]
 ! MOV BH,SBLOCK?[SI]
 ! MOV SBLOCK?[DI],BH
 ! MOV SBLOCK?[SI],BL
 ! ADD BL,BH
 ! MOV BH,0
 ! MOV AL,SBLOCK?[BX]
 ! RETN
END SUB

SBlock:
! DB 0
! DB 1
! DB 2
! DB 3
! DB 4
! DB 5
! DB 6
! DB 7
! DB 8
! DB 9
! DB 10
! DB 11
! DB 12
! DB 13
! DB 14
! DB 15
! DB 16
! DB 17
! DB 18
! DB 19
! DB 20
! DB 21
! DB 22
! DB 23
! DB 24
! DB 25
! DB 26
! DB 27
! DB 28
! DB 29
! DB 30
! DB 31
! DB 32
! DB 33
! DB 34
! DB 35
! DB 36
! DB 37
! DB 38
! DB 39
! DB 40
! DB 41
! DB 42
! DB 43
! DB 44
! DB 45
! DB 46
! DB 47
! DB 48
! DB 49
! DB 50
! DB 51
! DB 52
! DB 53
! DB 54
! DB 55
! DB 56
! DB 57
! DB 58
! DB 59
! DB 60
! DB 61
! DB 62
! DB 63
! DB 64
! DB 65
! DB 66
! DB 67
! DB 68
! DB 69
! DB 70
! DB 71
! DB 72
! DB 73
! DB 74
! DB 75
! DB 76
! DB 77
! DB 78
! DB 79
! DB 80
! DB 81
! DB 82
! DB 83
! DB 84
! DB 85
! DB 86
! DB 87
! DB 88
! DB 89
! DB 90
! DB 91
! DB 92
! DB 93
! DB 94
! DB 95
! DB 96
! DB 97
! DB 98
! DB 99
! DB 100
! DB 101
! DB 102
! DB 103
! DB 104
! DB 105
! DB 106
! DB 107
! DB 108
! DB 109
! DB 110
! DB 111
! DB 112
! DB 113
! DB 114
! DB 115
! DB 116
! DB 117
! DB 118
! DB 119
! DB 120
! DB 121
! DB 122
! DB 123
! DB 124
! DB 125
! DB 126
! DB 127
! DB 128
! DB 129
! DB 130
! DB 131
! DB 132
! DB 133
! DB 134
! DB 135
! DB 136
! DB 137
! DB 138
! DB 139
! DB 140
! DB 141
! DB 142
! DB 143
! DB 144
! DB 145
! DB 146
! DB 147
! DB 148
! DB 149
! DB 150
! DB 151
! DB 152
! DB 153
! DB 154
! DB 155
! DB 156
! DB 157
! DB 158
! DB 159
! DB 160
! DB 161
! DB 162
! DB 163
! DB 164
! DB 165
! DB 166
! DB 167
! DB 168
! DB 169
! DB 170
! DB 171
! DB 172
! DB 173
! DB 174
! DB 175
! DB 176
! DB 177
! DB 178
! DB 179
! DB 180
! DB 181
! DB 182
! DB 183
! DB 184
! DB 185
! DB 186
! DB 187
! DB 188
! DB 189
! DB 190
! DB 191
! DB 192
! DB 193
! DB 194
! DB 195
! DB 196
! DB 197
! DB 198
! DB 199
! DB 200
! DB 201
! DB 202
! DB 203
! DB 204
! DB 205
! DB 206
! DB 207
! DB 208
! DB 209
! DB 210
! DB 211
! DB 212
! DB 213
! DB 214
! DB 215
! DB 216
! DB 217
! DB 218
! DB 219
! DB 220
! DB 221
! DB 222
! DB 223
! DB 224
! DB 225
! DB 226
! DB 227
! DB 228
! DB 229
! DB 230
! DB 231
! DB 232
! DB 233
! DB 234
! DB 235
! DB 236
! DB 237
! DB 238
! DB 239
! DB 240
! DB 241
! DB 242
! DB 243
! DB 244
! DB 245
! DB 246
! DB 247
! DB 248
! DB 249
! DB 250
! DB 251
! DB 252
! DB 253
! DB 254
! DB 255

KeyBlock:
! DB 0
! DB 1
! DB 2
! DB 3
! DB 4
! DB 5
! DB 6
! DB 7
! DB 8
! DB 9
! DB 10
! DB 11
! DB 12
! DB 13
! DB 14
! DB 15
! DB 16
! DB 17
! DB 18
! DB 19
! DB 20
! DB 21
! DB 22
! DB 23
! DB 24
! DB 25
! DB 26
! DB 27
! DB 28
! DB 29
! DB 30
! DB 31
! DB 32
! DB 33
! DB 34
! DB 35
! DB 36
! DB 37
! DB 38
! DB 39
! DB 40
! DB 41
! DB 42
! DB 43
! DB 44
! DB 45
! DB 46
! DB 47
! DB 48
! DB 49
! DB 50
! DB 51
! DB 52
! DB 53
! DB 54
! DB 55
! DB 56
! DB 57
! DB 58
! DB 59
! DB 60
! DB 61
! DB 62
! DB 63
! DB 64
! DB 65
! DB 66
! DB 67
! DB 68
! DB 69
! DB 70
! DB 71
! DB 72
! DB 73
! DB 74
! DB 75
! DB 76
! DB 77
! DB 78
! DB 79
! DB 80
! DB 81
! DB 82
! DB 83
! DB 84
! DB 85
! DB 86
! DB 87
! DB 88
! DB 89
! DB 90
! DB 91
! DB 92
! DB 93
! DB 94
! DB 95
! DB 96
! DB 97
! DB 98
! DB 99
! DB 100
! DB 101
! DB 102
! DB 103
! DB 104
! DB 105
! DB 106
! DB 107
! DB 108
! DB 109
! DB 110
! DB 111
! DB 112
! DB 113
! DB 114
! DB 115
! DB 116
! DB 117
! DB 118
! DB 119
! DB 120
! DB 121
! DB 122
! DB 123
! DB 124
! DB 125
! DB 126
! DB 127
! DB 128
! DB 129
! DB 130
! DB 131
! DB 132
! DB 133
! DB 134
! DB 135
! DB 136
! DB 137
! DB 138
! DB 139
! DB 140
! DB 141
! DB 142
! DB 143
! DB 144
! DB 145
! DB 146
! DB 147
! DB 148
! DB 149
! DB 150
! DB 151
! DB 152
! DB 153
! DB 154
! DB 155
! DB 156
! DB 157
! DB 158
! DB 159
! DB 160
! DB 161
! DB 162
! DB 163
! DB 164
! DB 165
! DB 166
! DB 167
! DB 168
! DB 169
! DB 170
! DB 171
! DB 172
! DB 173
! DB 174
! DB 175
! DB 176
! DB 177
! DB 178
! DB 179
! DB 180
! DB 181
! DB 182
! DB 183
! DB 184
! DB 185
! DB 186
! DB 187
! DB 188
! DB 189
! DB 190
! DB 191
! DB 192
! DB 193
! DB 194
! DB 195
! DB 196
! DB 197
! DB 198
! DB 199
! DB 200
! DB 201
! DB 202
! DB 203
! DB 204
! DB 205
! DB 206
! DB 207
! DB 208
! DB 209
! DB 210
! DB 211
! DB 212
! DB 213
! DB 214
! DB 215
! DB 216
! DB 217
! DB 218
! DB 219
! DB 220
! DB 221
! DB 222
! DB 223
! DB 224
! DB 225
! DB 226
! DB 227
! DB 228
! DB 229
! DB 230
! DB 231
! DB 232
! DB 233
! DB 234
! DB 235
! DB 236
! DB 237
! DB 238
! DB 239
! DB 240
! DB 241
! DB 242
! DB 243
! DB 244
! DB 245
! DB 246
! DB 247
! DB 248
! DB 249
! DB 250
! DB 251
! DB 252
! DB 253
! DB 254
! DB 255
