Encryption/decryption. Transpose rail cipher & poly-alphabet

This code should be runnable from the command line, or standing alone. For command line use, REM out BOTH the suggested lines. Move to suitable directory in a MS or Linux command console and type in a suitable string. For test/debugging, REM out ONE of the two lines to do an encoding or a decoding run.

To encode, it runs four polyalphabet passes, using the key string, then the key reversed, then the key plus extra increments, twice. Then it does a rail transpose. Decode is the inverse.

The input file can hold any ASCII characters from 0 to 255. The key can be any length, any ASCII char from 0 to 255.

The file length is padded for the rails, so that there are the same number of characters on each rail.

The number of rails is taken as the length of the key string.

If you put chr$( 0) as the key string, the first two passes should make no change. ( see first output example)


''--------------------------------------------------------------!!Command Line Initialisation!!--------------------------------------------------------''

Inputcmd$ = CommandLine$                                                    ''  Normal usage is from command line.
                                                                            '   Un-rem one of the next two lines for testing
Inputcmd$ = "commLineCyphDecyph.bas -e XYZZY plainText.txt encyph.txt"      '   typical encyphering             UN-REM one of these lines |
'Inputcmd$ = "commLineCyphDecyph.bas -d XYZZY encyph.txt decrypted.txt"      '   typical decyphering             UN-REM one of these lines |

'Inputcmd$ = "as h yh ary ay ts54 4us6z"                                    '   unacceptable gobbledegook if no '-d' or '-e' in it.

print
print Inputcmd$
print
print "   NB screen output, for debugging, shows ASCII control codes as '*'"
print "   symbols and displays only first 80 chars while storing them all."
print


programname$    =word$( Inputcmd$, 1)
Choice$         =word$( Inputcmd$, 2)
key$            =word$( Inputcmd$, 3): key$ =chr$( 0) +chr$( 0)             '   for testing
filename$       =word$( Inputcmd$, 4)
Fileoutput$     =word$( Inputcmd$, 5)

if not( instr( Inputcmd$, "-e")) and not( instr( Inputcmd$, "-d")) then print Inputcmd$: notice "GIGO!": end

i = len( key$)

do until i =0
    keyChar$    =mid$( key$, i, 1)                  ''Generating the second key (reversed key)
    key2$       =key2$ + keyChar$
    i =i -1
loop

keyLength      =len( key$)                          ''Key Length

Select case Choice$                                 ''Select Case to find choice
    case "-d"
        print "   Decrypting"
        goto [Decryption]
    case "-e"
        print "   Encrypting"
        goto [Encryption]
    case else
        goto [Quit]
end select

''--------------------------------------------------------------!!Encryption Section!!--------------------------------------------------------''
[Encryption]                                        ''Opening the file using CL input
open filename$ for input as #inFile
    plainText$ =input$( #inFile, lof( #inFile))       'opening the file for input, put contents into string variable
close #inFile
print "   Received plain text"
call safePrint plainText$
print "   Key & reversed key ( control ASCII codes shown as '*'"
call safePrint ( key$ +"    " +key2$)
print

''--------------------------------------------------------------!!Polyalphabetic Rounds!!--------------------------------------------------------''
index = 1                                                   ''Resetting Index

for i =1 to len( plainText$)                                'loop until end of PT
    plainChar$        =mid$( plainText$, i, 1)              'Finding ASCII of character
    plainCharNum      =asc( plainChar$)                     'Putting this into a variable
    increment         =asc( mid$( key$, index, 1))          'Increment becomes the ascii value of key
    cypherText$       =cypherText$ +chr$( ( plainCharNum +increment) mod 256)   'Incrementing one by the other
    index             =index +1                             'Increasing the index
    if index >keyLength then index =1                       'Resetting the key according to length.
next i
print "   first  round"
call safePrint cypherText$

''ROUND TWO FIGHT!
index = 1 ''Resetting Index

for i =1 to len( cypherText$)    'loop until end of Cypher Text 1
    plainChar$        =mid$( cypherText$, i, 1)  'Finding ASCII of character
    plainCharNum      =asc( plainChar$)     'Putting this into a variable
    increment         =asc( mid$( key2$, index, 1))  'Increment becomes the ascii value of key
    cypherText2$       =cypherText2$ +chr$( ( plainCharNum +increment) mod 256)   'Incrementing one by the other
    index             =index +1 'Increasing the index
    if index >keyLength then index =1   'Resetting the key according to length.
next i
print "   second round"
call safePrint cypherText2$

''ROUND THREE FIGHT
index = 1

for i =1 to len( cypherText2$)    'loop until end of cypherText2 !
    plainChar$        =mid$( cypherText2$, i, 1)  'Finding ASCII of character
    plainCharNum      =asc( plainChar$)     'Putting this into a variable
    increment         =asc( mid$( key$, index, 1))  'Increment becomes the ascii value of key
    increment2        =increment + keyLength    'adding a further increment for another round.
    cypherText3$      =cypherText3$ +chr$( ( plainCharNum + increment + increment2) mod 256)   'Incrementing one by the other
    index             =index +1 'Increasing the index
    if index >keyLength then index =1   'Resetting the key according to length.
next i
print "   third  round"
call safePrint cypherText3$

''FINAL ROUND FIGHT
for i =1 to len( cypherText3$)    'loop until end of Cypher Text 1
    plainChar$        =mid$( cypherText3$, i, 1)  'Finding ASCII of character
    plainCharNum      =asc( plainChar$)     'Putting this into a variable
    increment         =asc( mid$( key2$, index, 1))  'Increment becomes the ascii value of key
    increment2        =increment + keyLength    'Again adding another incrementation to the backward key
    cypherText4$      =cypherText4$ +chr$( ( plainCharNum +increment+increment2) mod 256)   'Incrementing one by the other
    index             =index +1 'Increasing the index
    if index >keyLength then index =1   'Resetting the key according to length.
next i
print "   fourth round"
call safePrint cypherText4$
print

''--------------------------------------------------------------!!Rail Fence Cipher!!--------------------------------------------------------''

''Transposition Rail Cipher
 transposeByN    =keyLength ''use the key to give us the transposition number

    LPT =len( cypherText4$) ''Length of the cypher text

    pad =LPT mod transposeByN ''Finding the amount of "padding" needed to make the plaintext divisible by the keyLength

    if pad <>0 then                                                         '   <<<<<<<< NB was calculating wrongly here ????
        print "Padding by "; pad; " characters so length is raised from "; LPT; " to "; len( plainText$) +transposeByN -pad; " so now divisible by "; transposeByN
        for i =1 to transposeByN -pad
            cypherText4$ =cypherText4$ +"$" ''Adding the Pad
        next i
    end if

    print "   Padded text"
    call safePrint cypherText4$ ''Print the cyphertext with the pad
    print

    dim part$( transposeByN) ''Creating array for the "parts" of the encrypted text

    lenPT  =len( cypherText4$)

    for i =1 to lenPT +1 step transposeByN
        for j =1 to transposeByN
            part$( j) =part$( j) +mid$( cypherText4$, i +j -1, 1) ''Creating the rails to the cypher
        next j
    next i

    print "  Rail fence Transposition cyphered. Number of rails ="; transposeByN

    for bin =1 to transposeByN
        print   "     Rail "; bin
        call safePrint part$( bin)
    next bin
    print

    for bin =1 to transposeByN
        cypherText5$ =cypherText5$ +part$( bin) ''Adding the rails together to create cyphertext
    next bin

    numRails$ = chr$( transposeByN)                                 '<<<<<<< is this quite what you thought??? SHOULD BE chr$, (not str$ ).. one byte????
                       '<<<<<<<<<keyLength then index =1
next i
print "   3"
call safePrint cypherText3$

index = 1

for i =1 to len( cypherText3$)
    recoveredChar$    =mid$( cypherText3$, i, 1)
    recoveredCharNum  =asc( recoveredChar$)
    decrement         =( asc( mid$( key$, index, 1)))
    decrement2        =decrement + keyLength
    pointer           =recoveredCharNum -decrement - decrement2
    if pointer <0 then pointer =pointer +256
    cypherText2$      =cypherText2$ +chr$( pointer)
    index             =index +1
    if index >keyLength then index =1
next i
print "   2"
call safePrint cypherText2$

index = 1

for i =1 to len( cypherText2$)
    recoveredChar$    =mid$( cypherText2$, i, 1)
    recoveredCharNum  =asc( recoveredChar$)
    decrement         =( asc( mid$( key2$, index, 1)))
    pointer           =recoveredCharNum -decrement
    if pointer <0 then pointer =pointer +256
    cypherText$       =cypherText$ +chr$( pointer)
    index             =index +1
    if index >keyLength then index =1
next i
print "   1"
call safePrint cypherText$

index = 1

for i =1 to len( cypherText$)
    recoveredChar$    =mid$( cypherText$, i, 1)
    recoveredCharNum  =asc( recoveredChar$)
    decrement         =( asc( mid$( key$, index, 1)))
    pointer           =recoveredCharNum -decrement
    if pointer <0 then pointer =pointer +256
    recoveredText$    =recoveredText$ +chr$( pointer)
    index             =index +1
    if index >keyLength then index =1
next i

print
print "   Recovered text is"
print recoveredText$    '   No need for safe print since will be ASCII above 31, printable...

open  Fileoutput$ for output as #MyOutput
    #MyOutput, recoveredText$;
close #MyOutput

''--------------------------------------------------------------!!End of Program!!--------------------------------------------------------''
[Quit]
    print
    print "   Exiting."
    end
'   _______________________________________________________________________
sub safePrint in$
    for i =1 to len( in$)
        c$ =mid$( in$, i, 1)
        if asc( c$) >31 then print c$; else print "*";
        if i >80 then print "....etc..etc..": exit for
    next i
    print
end sub
'   _______________________________________________________________________

Typical outputs

...with un-printable key-string, NUL NUL, ie chr$( 0) +chr$( 0).

NB The first two passes therefore do nothing. The next two just shift all characters by the same amount through the alphabet of ASCII chars.

   Encrypting
   Received plain text
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz 0123456789**This is the plai....etc..etc..

   Key & reversed key ( control ASCII codes shown as '*'
**    **

   first  round
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz 0123456789**This is the plai....etc..etc..

   second round
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz 0123456789**This is the plai....etc..etc..

   third  round
CDEFGHIJKLMNOPQRSTUVWXYZ[\cdefghijklmnopqrstuvwxyz{|"23456789:;**Vjku"ku"vjg"rnck....etc..etc..

   fourth round
EFGHIJKLMNOPQRSTUVWXYZ[\]^efghijklmnopqrstuvwxyz{|}~$456789:;<=**Xlmw$mw$xli$tpem....etc..etc..


   Padded text
EFGHIJKLMNOPQRSTUVWXYZ[\]^efghijklmnopqrstuvwxyz{|}~$456789:;<=**Xlmw$mw$xli$tpem....etc..etc..


  Rail fence Transposition cyphered. Number of rails =2
     Rail 1
EGIKMOQSUWY[]egikmoqsuwy{}$579;=*lwm$l$pm$ix*Xm$wxiterx|2*lwm$l$pm$ix*Xm$wxiterx|....etc..etc..

     Rail 2
FHJLNPRTVXZ\^fhjlnprtvxz|~468:<*Xm$wxiterx|2*lwm$l$pm$ix*Xm$wxiterx|2*lwm$l$pm$ix....etc..etc..


    Encrypted text is
EGIKMOQSUWY[]egikmoqsuwy{}$579;=*lwm$l$pm$ix*Xm$wxiterx|2*lwm$l$pm$ix*Xm$wxiterx|....etc..etc..


   Exiting.






   Decrypting
   Whole length 340   Section length 170 repeated 2 times.
   File to decrypt
EGIKMOQSUWY[]egikmoqsuwy{}$579;=*lwm$l$pm$ix*Xm$wxiterx|2*lwm$l$pm$ix*Xm$wxiterx|....etc..etc..



   Text Recovery
   4
EFGHIJKLMNOPQRSTUVWXYZ[\]^efghijklmnopqrstuvwxyz{|}~$456789:;<=**Xlmw$mw$xli$tpem....etc..etc..

   3
CDEFGHIJKLMNOPQRSTUVWXYZ[\cdefghijklmnopqrstuvwxyz{|"23456789:;**Vjku"ku"vjg"rnck....etc..etc..

   2
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz 0123456789**This is the plai....etc..etc..

   1
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz 0123456789**This is the plai....etc..etc..


   Recovered text is
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz 0123456789
This is the plain text.
This is the plain text.
This is the plain text.
This is the plain text.
This is the plain text.
This is the plain text.
This is the plain text.
This is the plain text.
This is the plain text.
This is the plain text.
This is the plain text.

   Exiting.



Better key

....here is a messsage being processed with a 5-character key of printable characters, 'XYZZY'.


commLineCyphDecyph.bas -e XYZZY plainText.txt encyph.txt

   NB screen output, for debugging, shows ASCII control codes as '*'
   symbols and displays only first 80 chars while storing them all.

   Encrypting
   Received plain text
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz 0123456789**This is the plai....etc..etc..

   Key & reversed key ( control ASCII codes shown as '*'
XYZZY    YZZYX

   first  round
™›žžž ¢£££¥§¨¨¨ª¬­­­¯±²²²º¼½½½¿ÁÂÂÂÄÆÇÇÇÉËÌÌÌÎÐÑÑÑÓzŠŠŠŒŽ‘“gc¬ÁÃÍyÁÌzÎÁ½yÊƺÁ....etc..etc..

   second round
òõ÷÷ö÷úüüûüÿ*************************  * #%%$%(**)*-ÔãâãæèèçèëíÀ»***&Ñ*&Ô'**Ó$***....etc..etc..

   third  round
§¬°°­¬±µµ²±¶ºº·¶»¿¿¼»ÀÄÄÁÀËÏÏÌËÐÔÔÑÐÕÙÙÖÕÚÞÞÛÚßããàß䍜™˜¡¡ž¢¦yrºÒÖ߈ÏݍàÐˊÝØÉÏ....etc..etc..

   fourth round
^eigbcjnlghosqlmtxvqry}{vw„ˆ†‚‰‹†‡Ž’‹Œ“—•‘˜œš•–FSNOVZXST[_0'q‹–=†–F—…‚C–~†....etc..etc..


   Padded text
^eigbcjnlghosqlmtxvqry}{vw„ˆ†‚‰‹†‡Ž’‹Œ“—•‘˜œš•–FSNOVZXST[_0'q‹–=†–F—…‚C–~†....etc..etc..


  Rail fence Transposition cyphered. Number of rails =5
     Rail 1
^chmrw‚‡Œ‘–OTq†‚†•q†‚†•q†‚†•q†‚†•q†‚†•q†‚†•q†‚†•q†‚†•q†‚†•q†‚†•q†‚†•
     Rail 2
ejoty„‰Ž“˜V[‹–C‘—‹–C‘—‹–C‘—‹–C‘—‹–C‘—‹–C‘—‹–C‘—‹–C‘—‹–C‘—‹–C‘—‹–C‘—
     Rail 3
insx}ˆ’—œFZ_F–FTF–FTF–FTF–FTF–FTF–FTF–FTF–FTF–FTF–FTF–FT
     Rail 4
glqv{†‹•šSX0–——0–——0–——0–——0–——0–——0–——0–——0–——0–——0–——0
     Rail 5
bglqv†‹•NS'=…~‚'=…~‚'=…~‚'=…~‚'=…~‚'=…~‚'=…~‚'=…~‚'=…~‚'=…~‚'=…~‚'

    Encrypted text is
^chmrw‚‡Œ‘–OTq†‚†•q†‚†•q†‚†•q†‚†•q†‚†•q†‚†•q†‚†•q†‚†•q†‚†•q†‚†•q†‚†•ejoty„‰Ž“˜V[....etc..etc..


   Exiting.





commLineCyphDecyph.bas -d XYZZY encyph.txt decrypted.txt

   NB screen output, for debugging, shows ASCII control codes as '*'
   symbols and displays only first 80 chars while storing them all.

   Decrypting
   Whole length 340   Section length 68 repeated 5 times.
   File to decrypt
^chmrw‚‡Œ‘–OTq†‚†•q†‚†•q†‚†•q†‚†•q†‚†•q†‚†•q†‚†•q†‚†•q†‚†•q†‚†•q†‚†•ejoty„‰Ž“˜V[....etc..etc..



   Text Recovery
   4
^eigbcjnlghosqlmtxvqry}{vw„ˆ†‚‰‹†‡Ž’‹Œ“—•‘˜œš•–FSNOVZXST[_0'q‹–=†–F—…‚C–~†....etc..etc..

   3
§¬°°­¬±µµ²±¶ºº·¶»¿¿¼»ÀÄÄÁÀËÏÏÌËÐÔÔÑÐÕÙÙÖÕÚÞÞÛÚßããàß䍜™˜¡¡ž¢¦yrºÒÖ߈ÏݍàÐˊÝØÉÏ....etc..etc..

   2
òõ÷÷ö÷úüüûüÿ*************************  * #%%$%(**)*-ÔãâãæèèçèëíÀ»***&Ñ*&Ô'**Ó$***....etc..etc..

   1
™›žžž ¢£££¥§¨¨¨ª¬­­­¯±²²²º¼½½½¿ÁÂÂÂÄÆÇÇÇÉËÌÌÌÎÐÑÑÑÓzŠŠŠŒŽ‘“gc¬ÁÃÍyÁÌzÎÁ½yÊƺÁ....etc..etc..


   Recovered text is
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz 0123456789
This is the plain text.
This is the plain text.
This is the plain text.
This is the plain text.
This is the plain text.
This is the plain text.
This is the plain text.
This is the plain text.
This is the plain text.
This is the plain text.
This is the plain text.

   Exiting.