Is it Possible to Password protect a Program External DATA File ?

If you have questions about any aspect of QBasic programming, or would like to help fellow programmers solve their problems, check out this board!

Moderators: Pete, Mods

Post Reply
User avatar
Anthony.R.Brown
Veteran
Posts: 157
Joined: Thu Mar 27, 2014 1:03 pm

Is it Possible to Password protect a Program External DATA File ?

Post by Anthony.R.Brown »

OK I would like to know if it's possible to Password protect an external DATA File ? I am running a Program in real time and the program reads and writes to the external file which is in the form of a .txt File,so maybe it can be a different type of File if the first method does not work ?
The Password idea was the first idea I thought of when thinking about how to do this ? so every time you want to access the File for reading and writing it would have to load the Password...which is not so convenient :( so maybe there is another way to do it ?
I would like to do this to protect the External DATA and of course it has to also be protected from other ways of accessing the File ?



A.R.B :)
User avatar
burger2227
Veteran
Posts: 2466
Joined: Mon Aug 21, 2006 12:40 am
Location: Pittsburgh, PA

Re: Is it Possible to Password protect a Program External DATA File ?

Post by burger2227 »

You could rewrite the file shifting the text to another ASCII symbol if it is not something critical. I did that for a game I made by adding 30 to the ASC value into CHR$ and printing it into the file so a user would not cheat with famous quotes in a Crypto game.

Another way to do it is to actually have the program hold the DATA and have your program create the text file when run, but that may slow the program down if the data is large. Qbasic in DOS can write new data to the end of your program too...
Please acknowledge and thank members who answer your questions!
QB64 is a FREE QBasic compiler for WIN, MAC(OSX) and LINUX : https://www.qb64.org/forum/index.php
Get my Q-Basics demonstrator: https://www.dropbox.com/s/fdmgp91d6h8ps ... s.zip?dl=0
User avatar
Anthony.R.Brown
Veteran
Posts: 157
Joined: Thu Mar 27, 2014 1:03 pm

Re: Is it Possible to Password protect a Program External DATA File ?

Post by Anthony.R.Brown »

burger2227 wrote: Tue Feb 16, 2021 5:53 pm You could rewrite the file shifting the text to another ASCII symbol if it is not something critical. I did that for a game I made by adding 30 to the ASC value into CHR$ and printing it into the file so a user would not cheat with famous quotes in a Crypto game.

Another way to do it is to actually have the program hold the DATA and have your program create the text file when run, but that may slow the program down if the data is large. Qbasic in DOS can write new data to the end of your program too...

Hi burger2227

It would be a really great solution if it was possible as you say "Another way to do it is to actually have the program hold the DATA and have your program create the text file when run" :)
And as you mentioned it may Slow the program down :( which I imagine it would and the program I am talking about needs to be as fast as possible! as it would be reading and writing to thousands of lines of DATA. Maybe if the DATA could be compressed it might work faster ?



A.R.B :)
Erik
Veteran
Posts: 72
Joined: Wed Jun 20, 2007 12:31 pm
Location: LI, NY
Contact:

Re: Is it Possible to Password protect a Program External DATA File ?

Post by Erik »

It's not password protecting but what about using BSAVE/BLOAD to save and load the data files? That way it's stored in binary so you can't just open it up in a text editor to see the contents and it's also faster than regular reading/writing to text files using the old "OPEN filename for INPUT AS #1..." as you can load the whole file into an array when you BLOAD.

I guess you could add another layer of obfuscation by doing a ROT13 type idea like Burger's first suggestion on top of BSAVE/BLOAD.

Another idea is still use BSAVE/BLOAD but instead of hard coding the ROT number, base the ROT encrypt/decrypt on the password provided by the user. That way you don't actually store any password, but it's still the key to unscramble the data in the data file.

Here's a quick example I threw together that works.. though with any home grown encryption, it's not really secure.

Code: Select all

DECLARE SUB loadEncDataFile (fileName AS STRING)
DECLARE SUB saveEncDataFile (fileName AS STRING)
DECLARE SUB rotData (dataStr AS STRING, cipherKey AS INTEGER)
DECLARE FUNCTION getKey% (password AS STRING)
DECLARE FUNCTION unrotData$ (cipherKey AS INTEGER)
CLS

DIM SHARED encData(1 TO 512) AS INTEGER

dataStr$ = "This is a data string and it is currently not scrambled."

PRINT "DATA: "; dataStr$
INPUT "Enter a password: ", password$

cipherKey% = getKey%(password$)

CALL rotData(dataStr$, cipherKey%)

CALL saveEncDataFile("data.dat")

PRINT "Clearing memory..."
CLEAR

CALL loadEncDataFile("data.dat")

INPUT "Enter password to decode: ", password$

cipherKey% = getKey%(password$)

finalData$ = unrotData$(cipherKey%)
PRINT "Decoded: "; finalData$

END

FUNCTION getKey% (password AS STRING)

    cipherKey% = 0

    FOR i% = 1 TO LEN(password)
        char$ = MID$(password, i%, 1)
        cipherKey% = cipherKey% + ASC(char$) * i%
    NEXT i%

    PRINT "Cipher key: "; cipherKey%

    getKey% = cipherKey%

END FUNCTION

SUB loadEncDataFile (fileName AS STRING)

    DEF SEG = VARSEG(encData(1))
    BLOAD fileName, VARPTR(encData(1))
    DEF SEG

    PRINT "Loaded file: "; fileName

END SUB

SUB rotData (dataStr AS STRING, cipherKey AS INTEGER)

    FOR i% = 1 TO LEN(dataStr)
        IF i% < UBOUND(encData) THEN
            rotChar% = ASC(MID$(dataStr, i%, 1)) + cipherKey
            encData(i%) = rotChar%
        END IF
    NEXT i%

END SUB

SUB saveEncDataFile (fileName AS STRING)

    bytes% = LEN(encData(1)) * UBOUND(encData) + 1
    DEF SEG = VARSEG(encData(1))
    BSAVE fileName, VARPTR(encData(1)), bytes%
    DEF SEG

    PRINT "Saved file: "; fileName

END SUB

FUNCTION unrotData$ (cipherKey AS INTEGER)

    outData$ = ""

    FOR i% = 1 TO UBOUND(encData)
        charVal% = encData(i%) - cipherKey
        IF charVal% > 0 AND charVal% < 255 THEN
            char$ = CHR$(charVal%)
            outData$ = outData$ + char$
        END IF
    NEXT i%

    unrotData$ = outData$

END FUNCTION
The program takes the data string and adds the password key to each character. Then saves it using bsave and clears the memory. After that, it loads the data back into memory using bload and attempts to undo the scramble using the 2nd prompted for password.

On success, it displays the unscrambled string. On failures, it will either display nothing if the calculated integer value is too large or small to be represented as ASCII or potentially garbage characters based on a wrong calculated offset.

Example successful output:

Code: Select all

DATA: This is a data string and it is currently not scrambled.
Enter a password: password
Cipher key: 3970
Saved file: data.dat
Clearing memory...
Loaded file: data.dat
Enter password to decode: password
Cipher key: 3970
Decoded: This is a data string and it is currently not scrambled.
Example of wrong decrypt password:

Code: Select all

DATA: This is a data string and it is currently not scrambled.
Enter a password: password
Cipher key: 3970
Saved file: data.dat
Clearing memory...
Loaded file: data.dat
Enter password to decode: wrong
Cipher key: 1635
Decoded: 
What it looks like if you try to view contents of data.dat outsite of bload/bsave:
Image
User avatar
Anthony.R.Brown
Veteran
Posts: 157
Joined: Thu Mar 27, 2014 1:03 pm

Re: Is it Possible to Password protect a Program External DATA File ?

Post by Anthony.R.Brown »

Erik wrote: Tue Feb 23, 2021 12:23 am It's not password protecting but what about using BSAVE/BLOAD to save and load the data files? That way it's stored in binary so you can't just open it up in a text editor to see the contents and it's also faster than regular reading/writing to text files using the old "OPEN filename for INPUT AS #1..." as you can load the whole file into an array when you BLOAD.

I guess you could add another layer of obfuscation by doing a ROT13 type idea like Burger's first suggestion on top of BSAVE/BLOAD.

Another idea is still use BSAVE/BLOAD but instead of hard coding the ROT number, base the ROT encrypt/decrypt on the password provided by the user. That way you don't actually store any password, but it's still the key to unscramble the data in the data file.

Here's a quick example I threw together that works.. though with any home grown encryption, it's not really secure.

Code: Select all

DECLARE SUB loadEncDataFile (fileName AS STRING)
DECLARE SUB saveEncDataFile (fileName AS STRING)
DECLARE SUB rotData (dataStr AS STRING, cipherKey AS INTEGER)
DECLARE FUNCTION getKey% (password AS STRING)
DECLARE FUNCTION unrotData$ (cipherKey AS INTEGER)
CLS

DIM SHARED encData(1 TO 512) AS INTEGER

dataStr$ = "This is a data string and it is currently not scrambled."

PRINT "DATA: "; dataStr$
INPUT "Enter a password: ", password$

cipherKey% = getKey%(password$)

CALL rotData(dataStr$, cipherKey%)

CALL saveEncDataFile("data.dat")

PRINT "Clearing memory..."
CLEAR

CALL loadEncDataFile("data.dat")

INPUT "Enter password to decode: ", password$

cipherKey% = getKey%(password$)

finalData$ = unrotData$(cipherKey%)
PRINT "Decoded: "; finalData$

END

FUNCTION getKey% (password AS STRING)

    cipherKey% = 0

    FOR i% = 1 TO LEN(password)
        char$ = MID$(password, i%, 1)
        cipherKey% = cipherKey% + ASC(char$) * i%
    NEXT i%

    PRINT "Cipher key: "; cipherKey%

    getKey% = cipherKey%

END FUNCTION

SUB loadEncDataFile (fileName AS STRING)

    DEF SEG = VARSEG(encData(1))
    BLOAD fileName, VARPTR(encData(1))
    DEF SEG

    PRINT "Loaded file: "; fileName

END SUB

SUB rotData (dataStr AS STRING, cipherKey AS INTEGER)

    FOR i% = 1 TO LEN(dataStr)
        IF i% < UBOUND(encData) THEN
            rotChar% = ASC(MID$(dataStr, i%, 1)) + cipherKey
            encData(i%) = rotChar%
        END IF
    NEXT i%

END SUB

SUB saveEncDataFile (fileName AS STRING)

    bytes% = LEN(encData(1)) * UBOUND(encData) + 1
    DEF SEG = VARSEG(encData(1))
    BSAVE fileName, VARPTR(encData(1)), bytes%
    DEF SEG

    PRINT "Saved file: "; fileName

END SUB

FUNCTION unrotData$ (cipherKey AS INTEGER)

    outData$ = ""

    FOR i% = 1 TO UBOUND(encData)
        charVal% = encData(i%) - cipherKey
        IF charVal% > 0 AND charVal% < 255 THEN
            char$ = CHR$(charVal%)
            outData$ = outData$ + char$
        END IF
    NEXT i%

    unrotData$ = outData$

END FUNCTION
The program takes the data string and adds the password key to each character. Then saves it using bsave and clears the memory. After that, it loads the data back into memory using bload and attempts to undo the scramble using the 2nd prompted for password.

On success, it displays the unscrambled string. On failures, it will either display nothing if the calculated integer value is too large or small to be represented as ASCII or potentially garbage characters based on a wrong calculated offset.

Example successful output:

Code: Select all

DATA: This is a data string and it is currently not scrambled.
Enter a password: password
Cipher key: 3970
Saved file: data.dat
Clearing memory...
Loaded file: data.dat
Enter password to decode: password
Cipher key: 3970
Decoded: This is a data string and it is currently not scrambled.
Example of wrong decrypt password:

Code: Select all

DATA: This is a data string and it is currently not scrambled.
Enter a password: password
Cipher key: 3970
Saved file: data.dat
Clearing memory...
Loaded file: data.dat
Enter password to decode: wrong
Cipher key: 1635
Decoded: 
What it looks like if you try to view contents of data.dat outsite of bload/bsave:
Image


That looks Amazing! Eric :)
Post Reply