Coding and decoding with XOR.

If you take plain-text and XOR every character with the SAME chosen byte, it becomes unreadable. It is 'encrypted'. It is however quickly decoded by knowing what byte was being used. If you don't know this ( ie are trying to 'break' the code) you can look at the letter frequencies. Whatever character is NOW most frequent almost certainly represents 'e'. Next most frequent wil be 't'. 'etaoni' is the usual order in written English. You can now deduce the coding byte, XOR ALL the text with it, since XOR'ing twice gets you back the original, and you have your plain-text extracted. Simples.

A much harder code to break is to XOR every character with a DIFFERENT byte. This scrambles each letter to some ASCII code, but can only be decoded if you know the correct SEQUENCE of coding bytes. It has the side effect of spreading the letter frequency so all characters appear on average equally often.

So what we need is a string of bytes, statistically random, but repeatable. You could send someone this sequence as a file- not very secure. You can use your own PRNG, such as a switch-tail ring counter, or a Mersenne Twister. You can calculate Pi and use its digits- VERY slow. All are easy to program ( contact me if interested)

In Liberty BASIC, the function 'randomize 0.nnnnnn' seeds the random number generator so that calling rnd( n) then repeatedly generates a string of values. 'randomise' again with the same seed and you can repeat the same sequence.

The program below demonstrates how easy this is to do. In practice you'd run the coding and decoding sections on different machines.



    '   Uses the repeatability of the sequence generated by LB's PRNG
    '       to XOR each message character with a different byte.
    '   This also spreads the bytes uniformly across 0 <--> 255
    '       so letter-frequency info. is hidden.

    '   Decoding is simply to XOR again with the same sequence of #s.

    nomainwin

    WindowWidth   =1240
    WindowHeight  = 800

    graphicbox #w.gb1,  10,  30, 350, 300
    graphicbox #w.gb2, 430,  30, 350, 300
    graphicbox #w.gb3, 850,  30, 350, 300

    texteditor #w.te1,  10, 340, 350, 400
    texteditor #w.te2, 430, 340, 350, 400
    texteditor #w.te3, 850, 340, 350, 400

    menu #w, "File", "Help", [help]

    statictext #w.st1 "Original text                    Encoded text                   Decoded text", 100,   2, 1100,  20

    open "XOR stream encoding and decoding" for window as #w

    #w "trapclose [quit]"

    #w.st1 "!font courier 16 bold"

    #w.gb1 "down ; fill darkblue ; color white"
    #w.gb2 "down ; fill darkblue ; color white"
    #w.gb3 "down ; fill darkblue ; color white"

    v =0.1234567                                      '   Any # 0 <--> 0.9999

    randomize v

    dim LetterFreqyBins( 255)                        '   so bin( 65) counts 'A's.

    open "DofI.txt" for input as #i
        ToBeCoded$ =input$( #i, lof( #i))
        #w.te1 ToBeCoded$
    close #i

    Enc$ =right$( "0000000000" +str$( v), 10)

    for i =1 to len( ToBeCoded$)
        f                     =int( 256 *rnd( 1))
        ch                    =asc( mid$( ToBeCoded$, i, 1))
        LetterFreqyBins( ch)  =LetterFreqyBins( ch) +1   '   Keep count of this char's occurrence
        Enc$ =Enc$ +chr$( f xor ch)
    next i

    for k =0 to 255
        #w.gb1 "place "; 50 +k; "  "; 290 -LetterFreqyBins( k) /6
        #w.gb1 "goto  "; 50 +k; "  291"
    next k

    #w.gb1 "flush"

    #w.te2 Enc$

    open "DofIXOR.txt" for output as #o
        #o Enc$;
    close #o

    redim LetterFreqyBins( 255)

    for i =11 to len( Enc$)
        f      =int( 256 *rnd( 1))
        ch     =f xor asc( mid$( Enc$, i, 1))
        LetterFreqyBins( ch)  =LetterFreqyBins( ch) +1
        Dec$   =Dec$ +chr$( ch)
    next i

    for k =0 to 255
        #w.gb2 "place "; 50 +k; "  "; 290 -LetterFreqyBins( k) /6
        #w.gb2 "goto  "; 50 +k; "  291"
    next k

    #w.gb2 "flush"

    Dec$ =""

    f =val( left$( Enc$, 10))
    randomize f

    redim LetterFreqyBins( 255)

    for i =11 to len( Enc$)
        f      =int( 256 *rnd( 1))
        ch     =f xor asc( mid$( Enc$, i, 1))
        LetterFreqyBins( ch)  =LetterFreqyBins( ch) +1
        Dec$   =Dec$ +chr$( ch)
    next i

    #w.te3 Dec$

    for k =0 to 255
        #w.gb3 "place "; 50 +k; "  "; 290 -LetterFreqyBins( k) /6
        #w.gb3 "goto  "; 50 +k; "  291"
    next k

    #w.gb3 "flush"

    wait

    [help]
    WindowWidth   = 660
    WindowHeight  = 400

    texteditor #m.te,  10,  10, 600, 360

    open "XOR coder/decoder" for dialog_modal as #m

    #m "trapclose [q]"

    #m.te "!font arial 12"
    #m.te ""
    #m.te "     CODING and DECODING with XOR"
    #m.te ""
    #m.te " Each byte of the input is XOR'd with a new byte from a predictable stream."
    #m.te " This is generated by the LB pseudo-random number generator,"
    #m.te " The same sequence is generated if you seed it with the same number."
    #m.te " Look up 'randomize' in the Help file."
    #m.te ""
    #m.te " Since XOR'ing twice with the same number gets you back to the original"
    #m.te "    it is easily decoded."
    #m.te ""
    #m.te " I have chosen to encode the seed at the start of the encoded-string."
    #m.te " For greater security, distribute it separately."
    #m.te ""
    #m.te " As the character-frequency graphs show, the letter-frequency becomes"
    #m.te "    invisible, so you can't decode by knowing 'etaoni..'."

    wait
    [q]
    close #m

    wait

  [quit]
    close #w
    end

The second version is built around just one window. You select your source text file, and its XOR-transform is shown. It automatically adds an 'XOR' in front of a filename when creating and saving the encrypted file. It equally looks to see if you are loading a file whose name starts 'XOR...' and saves the decrypted file with the 'XOR' stripped off.

I also added an alteration to make sure the 'randomize' gets a correct 10-character seed in both directions.


    '   Uses the repeatability of the sequence generated by LB's PRNG
    '       to XOR each message character with a different byte.
    '   This also spreads the bytes uniformly across 0 <--> 255
    '       so letter-frequency info. is hidden.

    '   Decoding is simply to XOR again with the same sequence of #s.

    '   To-dos:-
    '       Menu and Help ( copy from earlier version)
    '       Display files in Notepad, so you have word-wrap.
    '       Add buttons to load & decode; clear displays; quit.         DONE


    nomainwin

    WindowWidth   = 1000
    WindowHeight  =  700

    texteditor #w.te1,  10,  60, 950, 500

    statictext #w.st1 "Input file Text",   100,  20,  950,  20

    button #w.b1, "Selct File", [select], LR, 850, 40

    open "XOR stream encoding and decoding" for window as #w

    #w "trapclose [quit]"

    #w.st1 "!font courier 16 bold"

    wait

  [select]
    filedialog "Load what file", "source.txt", fn$
    if fn$ ="" then close #w: end

    for k =len( fn$) to 1 step -1
        if mid$( fn$, k, 1) ="\" then posSlash =k: exit for
    next k

    path$ =left$( fn$, k)
    file$ =mid$(  fn$, posSlash +1)

    #w.st1 "'"; file$; "'    being XOR'ed to give "

    open fn$ for input as #i
        Source$ =input$( #i, lof( #i))
        #w.te1 Source$
    close #i

    timer 1000, [on]
    wait
    [on]
    timer 0

    #w.te1 "!cls"

    if left$( Source$, 2) <>"0." then
        v  =rnd( 1)
        v$ =str$( v)
        v  =val( left$( v$, 10))    '   ensure correct # of digits for seed
        randomize v
        Enc$ =left$( str$( v) +"000000000000", 12)
        for i =1 to len( Source$)
            f        =int( 256 *rnd( 1))
            ch       =asc( mid$( Source$, i, 1))
            Enc$     =Enc$ +chr$( f xor ch)
        next i
        #w.te1 Enc$
    else
        Enc$ =""
        v =val( left$( Source$, 10))
        randomize v
        for i =13 to len( Source$)
            f      =int( 256 *rnd( 1))
            ch     =f xor asc( mid$( Source$, i, 1))
            Enc$   =Enc$ +chr$( ch)
        next i
        #w.te1 Enc$
    end if

    if left$( file$, 3) ="XOR" then
        nf$ =mid$( file$, 4)
    else
        nf$ ="XOR" +file$
    end if

    #w.st1 "'"; file$; "'    being XOR'ed to give     '"; nf$; "'"

    open path$ +nf$ for output as #o
         #o Enc$;
    close #o

    wait

  [quit]
    close #w
    end

I can be contacted on mr dot john dot f at gmail dot com.