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
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