Author Topic: CHR$(26)  (Read 322 times)

CHR$(26)
« on: April 08, 2018, 08:57:58 AM »
I am writing a small  cryptography program (one time pad) where I need to read byte by byte a sequential file with random numbers (created separately - see Random.org).
I am having a problem with CHR(26) (hex 1A) read as EOF. When CHR(26) is reached the reading of the random number file ends.

If I remove the CHR(26) everything works fine using the statements:
OPEN FOR INPUT
followed by
randomnumber$ = INPUT$(1, #1):randomnumber% = ASC(randomnumber$)

I also tried with
OPEN FOR BINARY
followed by
GET #1, , randomnumber%%
but, from that terrible 26 on i have only got zeroes.

Does anyone know a way around this problem?

P.S.: I tried to register on "official" QB64 forum but I couldn't, neither from Windows nor from Linux nor from Android. And I haven't found either  an e-mail address to ask for help. Does anyone know  what to do?

Offline FellippeHeitor

  • QB64 Developer
  • LET IT = BE
    • QB64.org
Re: CHR$(26)
« Reply #1 on: April 08, 2018, 10:18:42 AM »
Can you provide a sample file and a minimal subset of working code (in case you don't want to share the actual program given its nature) so we can try and find a workaround? Char 26 is traditionally an end of file marker and qb64 even needed extra work to comply with the legacy behavior, but I recall having been able to read through it with no problems recently.

Re: CHR$(26)
« Reply #2 on: April 08, 2018, 04:44:57 PM »
No problem. One time pad is known since 1915~1920: is very easy, fast and NSA proof.
Here is the heart of the program. There are two input files, the readable one and the key, and an output file: the coded one.

  OPEN "I", #1, FILEIN$:LFILEIN# = LOF(1)
  OPEN "I", #2, FILECHIAVE$:LFILECHIAVE# = LOF(2)

IF LFILEIN# < LFILECHIAVE# THEN CONTA# = LFILEIN# ELSE END

  OPEN "O", #3, FILEOUT$
   
     FOR NCARATTERE# = 1 TO CONTA#
       CARATTEREIN$ = INPUT$(1, #1)
       CARATTERECHIAVE$ = INPUT$(1, #2)
       NUMEROIN% = ASC(CARATTEREIN$)
       NUMEROCIFRA% = ASC(CARATTERECHIAVE$)
       NUMEROCIFRATO% = NUMEROIN% XOR NUMEROCIFRA%
       CARATTERECIFRATO$ = CHR$(NUMEROCIFRATO%)
       PRINT #3, CARATTERECIFRATO$;
     NEXT
     
  CLOSE

Decoding uses the same program, with the the coded file as input.
Coding/decodig statement is the one with XOR inside.
My problem is the coded file that may include EVERY byte from 0 to 255, I can "clean" the key but NOT the the coded file.

Tha attachment is a BINARY file with a short example, open with an Hex editor, NOT with a text editor.

Re: CHR$(26)
« Reply #3 on: April 08, 2018, 04:55:14 PM »
I wrote a similar program, and my solution is to input numbers as a comma delimited file, where each byte is input sequentially. Or, if the file to be input and then encrypted is meant to be ASCII characters, then I input the characters as one, long, string variable, space delimited.

In the code below, type$ = "a" is used in the input, to tell the program that the input is a string of ASCII characters.

Code: [Select]
    OPEN "..\CipherShortIn.ini" FOR INPUT AS #1


    IF type$ = "a" THEN
        INPUT #1, Astring$
        PRINT Astring$
        NumBytes = LEN(Astring$)
        PRINT #2, Astring$
        FOR i = 1 TO NumBytes
            Plaintext(i) = ASC(Astring$, i)
        NEXT i
    ELSE
        DO
            i = i + 1
            INPUT #1, Plaintext(i)
            IF Plaintext(i) > 255 THEN EXIT DO
        LOOP
        NumBytes = i - 1
    END IF

In either case, you are creating an array of input values, range 0 to 255, which the program then manipulates in a couple of ways, to create the cipher text. If the input was ASCII characters, the decoding process re-creates the ASCII characters (which, by the way, could be a long string of ASCII numbers if you want). If the input was numbers, the decode process will not convert the decrypted array to ASCII.

From what you describe, it sounds like you should just create that comma-delimited input file, where each field is a value from 0 to 255. To end the array, just enter a number greater than 255, to indicate end-of-file. Like I did in the ELSE statements above.
« Last Edit: April 08, 2018, 05:15:46 PM by Bert22306 »

Offline FellippeHeitor

  • QB64 Developer
  • LET IT = BE
    • QB64.org
Re: CHR$(26)
« Reply #4 on: April 08, 2018, 05:12:30 PM »
This should do the same as your original snippet above:

Code: [Select]
fileIn$ = "encoded.bin"
fileChiave$ = "key.bin"
fileOut$ = "fileout.txt"

OPEN fileIn$ FOR BINARY AS #1
OPEN fileChiave$ FOR BINARY AS #2

lFileIn& = LOF(1)
lFileChiave& = LOF(2)

IF lFileIn& <= lFileChiave& THEN conta& = lFileIn& ELSE END

OPEN fileOut$ FOR BINARY AS #3

FOR nCarattere& = 1 TO conta&
    a$ = SPACE$(1)
    GET #1, nCarattere&, a$

    b$ = SPACE$(1)
    GET #2, nCarattere&, b$

    numeroCifrato% = ASC(a$) XOR ASC(b$)

    c$ = CHR$(numeroCifrato%)
    PUT #3, nCarattere&, c$
NEXT

CLOSE

Coded this way it works even if either file contains CHR$(26) in it. You were having issues because you were using INPUT for a binary file and GET/PUT deal with each byte properly, ignoring CHR$(26) as EOF marker.

I'm attaching an encoded file and a key file that contains several CHR$(26) in it (the first 100 bytes are CHR$(26) if you look closely). Use the code above to decode it, if you want to check it for yourself.

Re: CHR$(26)
« Reply #5 on: April 09, 2018, 04:20:02 PM »
Thank you, FellippeHeitor.
OPEN FOR BINARY and GET works fine.  8)))

Mmmmm ....
LET IT =  BE ?
ALL RIGHT! Beatles forever!!