NAME: RC4
CREATOR: Ron Rivest / RSA Laboratories
PB AUTHOR: Scott Slater
DESCRIPTION: RC4 is a variable key-size stream cipher with byte-oriented operations. The algorithm is based on the use of a random permutation.
NOTES: Susceptible to bit-flipping attacks; RC4 has no error detection and changing 1 byte in the ciphertext doesn't affect any other data except that byte
SOURCE: http://www.summitcn.com/powerbasic.html
Viewing source from rc4.bas   7812 bytes   Last modified Wed, 20 September 2006

' ---------------------------------------------------------
' RC4 Encrypt/Decrypt Routine: Returns 1 on Error,
'                                      0 for Success
'
'  nLen = Input String Len. NOTE: Buffer Lengths Must Be
'  equal to or greater than this size.  We want To be able
'  to encrypt Ascii Zero's so we can't look for These for
'  the end of the string mark as you normally would with
'  this type of data.
'
' NOTE: If you are calling from PB you are better off using
' the wrapper function below to use BASIC Strings.
' ---------------------------------------------------------
Function EnDeCrypt Alias "EnDeCrypt"(InString As Asciiz, Passwd As Asciiz, _
                   OutString As Asciiz, ByVal nLen As Dword) Export As Long

   Local S   As Asciiz * 256
   Local K   As Asciiz * 256
   Local rtn As Long

   ! push ebx                 ; save ebx
   ! push esi                 ; save esi
   ! push edi                 ; save edi
   ! mov esi, InString        ; Input String Address
   ! and esi, esi             ; null pointer check
   ! jz EnDeCryptDone         ; exit function
   ! mov edi, OutString       ; Output String Address
   ! and edi, edi             ; null pointer check
   ! jz EnDeCryptDone         ; exit function
   ! mov edx, Passwd          ; Password String Address
   ! and edx, edx             ; null pointer check
   ! jz EnDeCryptDone         ; exit function

   ! push esi                 ; save it for temp use
   ! push edi                 ; save it for temp use
   ! push edx                 ; save original pw address
   ! xor eax, eax             ; zero eax
   ! lea esi, S               ; address of S
   ! lea edi, K               ; address of K

   EnDeCryptInitS:
   ! mov [esi+eax], al        ; store char in S
   ! mov bl, [edx]            ; get byte from password
   ! cmp bl, 0                ; see if its a null terminator
   ! je EnDeCryptFixPw        ; if so adjust it
   ! mov [edi+eax], bl        ; store char in K
   ! inc edx                  ; increment pw pointer
   ! inc eax                  ; increment ascii pointer
   ! cmp eax, 256             ; see if we're done
   ! jl EnDeCryptInitS        ; get next character
   ! jmp EnDeCryptCreateTable ; go to next step

   EnDeCryptFixPw:
   ! pop edx                  ; get starting address of pw
   ! push edx                 ; save it again
   ! mov bl, [edx]            ; get first char again
   ! mov [edi+eax], bl        ; store it in K
   ! inc edx                  ; increment pw pointer
   ! inc eax                  ; increment ascii pointer
   ! cmp eax, 256             ; see if we're done
   ! jl EnDeCryptInitS        ; get next character

   EnDeCryptCreateTable:
   ! xor ecx, ecx             ; zero ecx
   ! xor edx, edx             ; zero edx

   EnDeCryptTableLoop:
   ! mov al, [esi+ecx]        ; get S char into al
   ! mov ah, [edi+ecx]        ; get K char into ah
   ! add al, ah               ; add them together
   ! mov ah, dl               ; dl to ah
   ! add al, ah               ; add them together
   ! mov edx, eax             ; save it to edx
   ! and edx, 255             ; filter off high bits
   ! mov bl, [esi+ecx]        ; get S char to bl
   ! mov al, [esi+edx]        ; get K char to al
   ! mov [esi+ecx], al        ; swap the values
   ! mov [esi+edx], bl        ; swap the values
   ! inc ecx                  ; increment counter
   ! cmp ecx, 256             ; see if we're done
   ! jl EnDeCryptTableLoop    ; get next character

   ! pop edx                  ; restore password address
   ! pop edi                  ; restore Output address
   ! pop esi                  ; restore Input address
   ! xor eax, eax             ; zero eax
   ! xor ebx, ebx             ; zero ebx
   ! xor ecx, ecx             ; zero ecx
   ! xor edx, edx             ; zero edx

   EnDeCryptMainLoop:
   ! mov eax, 1234            ; normal exit code checked on exit
   ! cmp edx, nLen            ; See if we've reached the end yet
   ! jge EnDeCryptDone        ; if so we're done
   ! mov al, [esi+edx]        ; get char from input
   ! inc ch                   ; increment ch
   ! and ch, 255              ; range 0-255
   ! push esi                 ; save esi
   ! lea esi, S               ; address of S
   ! push eax                 ; save eax
   ! push ebx                 ; save ebx
   ! xor eax, eax             ; zero eax
   ! mov ah, ch               ; get ch
   ! shr eax, 8               ; move to al
   ! mov ebx, eax             ; copy it to ebx
   ! mov al, [esi+ebx]        ; get byte
   ! add cl, al               ; add them up
   ! and cl, 255              ; range 0-255
   ! pop ebx                  ; restore ebx
   ! xor eax, eax             ; zero eax
   ! mov al, cl               ; cl to al
   ! mov bl, [esi+eax]        ; swap table bytes
   ! mov al, ch               ; ch to al
   ! mov bh, [esi+eax]        ; swap table bytes
   ! mov [esi+eax], bl        ; swap table bytes
   ! mov al, cl               ; cl to al
   ! mov [esi+eax], bh        ; swap table bytes
   ! pop eax                  ; restore eax
   ! add bl, bh               ; add the bytes together
   ! and ebx, 255             ; range 0-255
   ! mov bh, [esi+ebx]        ; get xor Var
   ! shr ebx, 8               ; move it to bl
   ! xor al, bl               ; xor the value
   ! mov [edi+edx], al        ; store the encrypted char
   ! pop esi                  ; restore input address
   ! inc edx                  ; increment character counter
   ! jmp EnDeCryptMainLoop    ; get next character

   EnDeCryptDone:
   ! cmp eax, 1234            ; see if our normal exit code
   ! je EnDeCryptExitLab      ; got us here, if so exit
   ! mov eax, 1               ; if not return error code
   ! mov rtn, eax             ; to caller

   EnDeCryptExitLab:
   ! pop edi                  ; restore edi
   ! pop esi                  ; restore esi
   ! pop ebx                  ; restore ebx

   Function = rtn

End Function


' ---------------------------------------------------------
' Wrapper Function that Calls EnDeCrypt and handles
' Conversions of Input And output to regular basic
' style strings instead of Asciiz.
'
'                     Returns:  String on Success
'                               Empty String on Error
' ---------------------------------------------------------
Function CryptStr Alias "CryptStr" (StringIn As String, Pw As String) _
                  Export As String

   Local pBuff As String
   Local oBuff As String

   pBuff = Pw & Chr$(0)              ' pad pw with a chr 0
   oBuff  = Space$(Len(StringIn))    ' set outbuff len

   ! push ebx                ; save ebx
   ! mov eax, StringIn       ; Get Input Buffer Handle to eax
   ! mov eax, [eax]          ; get address of data
   ! and eax, eax            ; null pointer check
   ! jz CryptStrDone         ; leave the function

   ! lea ebx, pBuff          ; pBuff's handle to ebx
   ! mov ebx, [ebx]          ; pBuff's address to ebx
   ! lea ecx, oBuff          ; oBuff's handle to ecx
   ! mov ecx, [ecx]          ; oBuff's address to ecx
   ! mov edx, [eax-4]        ; StringIn's Length to edx

   ! push edx                ; last parameter for call
   ! push ecx                ; 3rd parameter for call
   ! push ebx                ; 2nd parameter for call
   ! push eax                ; 1st paramter for call
   ! call EnDeCrypt          ; call the master function

   ! cmp eax, 0              ; make sure there were no errors
   ! jne CryptStrDone        ; if so then exit

   Function = oBuff          ' set output

   CryptStrDone:
   ! pop ebx                 ; restore ebx

End Function


Back to The Archives