Sometimes we need to protect data, without introducing over-complex routines. A perfect example is High Score tables. It would not be wise to save the information in a plain text file. Conversely, we need to be able to read and write the information efficiently. We'll use the example of saving high score data to illustrate how data can be encrypted and decrypted very easily. Along the way, we'll introduce reading from and writing to files, using bitwise operations and the advantages of not-so random numbers.

Full tutorial and Project files in Newsletter:

http://www.thegamecreators.com/data/newsletter/newsletter_issue_35.html#10

Language: 
Dark Basic Pro
Code: 
`The types required...

remstart
tHiScoreGlobal
File Name, Number of scores to remember
keyword and length of keyword
seed for random number
remend
type tHiScoreGlobal
	file$
	count
	keyword$
	keylength
	seed
endtype

remstart
tHiScore
Player Name, score
remend
type tHiScore
	name$
	score
endtype
 
function HiScoreInit()
remstart
@C Create the necessary variables and arrays
@C Bear in mind that this include file is Self-Contained
@C In other words, it does not rely on any external elements
remend

	global gHSG as tHiScoreGlobal
	gHSG.file$ = "hiscore.dat"
	gHSG.count = 10
	
	dim gHiScore() as tHiScore
	add to queue gHiScore()

	` For encypted files, we need a keyword
	gHSG.KeyWord$ = "TheGameCreators"
	gHSG.KeyLength = len(gHSG.KeyWord$)
		
endfunction
 
function HiScoreSetFile(file$)
remstart
@C Sets the file name to use for Hi Score data
remend	

	gHSG.file$ = file$
	
endfunction
	 
function HiScoreSetCount(count)
remstart
@C Sets the number of Hi Scores to remember
remend	

	gHSG.count = count
	
endfunction
	 
function HiScoreLoad()
remstart
@C Load the Hi Scores from the Hi Score File
@C The format of the file is Name, Score, Name, Score
@C If the file does not exist, it will skip this section of code.
@C If the file doesn't exist, or the file doesn't contain enough hi scores,
@C they will be added.
@C The datea is encrypted
@C The first value is the seed.  Each entry is then a length, value and name
remend	
	
	` If the Hi Score array is already populated, clear it.
	if array count(gHiScore()) > 1
		empty array gHiScore()
		add to queue gHiScore()
	endif
	
	` Find a free file number
	if file exist(gHSG.file$)
		filenum = getFreeFile()
		open to read filenum, gHSG.file$
		` The first byte is the "seed".  This seed ensures the encryption changes
		` every time we save the file.
		read long filenum, gHSG.seed
		while not file end(filenum)
			add to queue gHiScore()
			read long filenum, valueLength
			read long filenum, var
			gHiScore().score = HiScoreDecryptValue(var)
			var$ = ""
			for n = 1 to ValueLength
				read byte filenum, in
				var$ = var$ + chr$(in)
			next n
			gHiScore().name$ = HiScoreDecrypt(var$)
		endwhile
		close file filenum
	endif	
	
	` Call the function to ensure the table is fully populated
	HiScoreAddDefaultEntries()
	
endfunction

function HiScoreSave()
remstart
@C Save the Hi Scores to the Hi Score File
@C The format of the file is Name, Score, Name, Score
@C If the file already exists, it will delete it first
@C The values will first be encrypted.
@C Because we can't predict the values, we can't simply write a string.
@C Some values may be line ending values, which will "break" our table.
@C To resolve this, we will writ ethe values character by character,
@C After first recording the length of the value.
remend	
	
	` If the Hi Score array isn't populated, create default scores
	if array count(gHiScore()) < array count(gHiScore())
		HiScoreAddDefaultEntries()
	endif
	
	` Find a free file number
	if file exist(gHSG.file$) then delete file gHSG.file$

	filenum = getFreeFile()
	open to write filenum, gHSG.file$
	HiScoreGenerateSeed()
	write long filenum, gHSG.seed
	for n = 1 to array count(gHiScore())
		write long filenum, len(gHiScore(n).name$)
		write long filenum, HiScoreEncryptValue(gHiScore(n).score)
		result$ = HiScoreEncrypt(gHiScore(n).name$)
		for m = 1 to len(result$)
			write byte filenum, asc(mid$(result$,m,1))
		next m
	next n
	close file filenum
	
endfunction

function hiScoreGetName(position)
remstart
@C Returns the name at the specified position
@C If the position is not valid, it will return "#"
remend
	
	if position > 0 and position <= array count(gHiScore())
		name$ = gHiScore(position).name$
	else
		name$ = "#"
	endif	
	
endfunction name$

function hiScoreGetScore(position)
remstart
@C Returns the score at the specified position
@C If the position is not valid, it will return -1
remend
	
	if position > 0 and position <= array count(gHiScore())
		score = gHiScore(position).score
	else
		score = -1
	endif	
	
endfunction score


function hiScoreAddDefaultEntries()
remstart
@C This function simply populates the hiscore array
@C with defaault values to ensure it contains the 
@C desired number of entries
remend
	
	` If the number of hi scores < the desired amount, add more
	` The Hi Scores are in descending order, so we can make these scores 0
	if array count(gHiScore())	< gHSG.count
		for n = (array count(gHiScore()) + 1) to gHSG.count
			add to queue gHiScore()
			gHiScore().name$ = "Anon"
			gHiScore().score = 0
		next n
	endif

endfunction

function hiScoreCheckScore(score)
remstart
@C Takes the score parameter and checks if it is higher
@C than current low score.  If yes, return position
@C If no, return -1
remend
	
	position = -1
	for n = gHSG.count to 1 step -1
		if score < gHiScore(n).score then exit
		position = n
	next n

endfunction position

function hiScoreAddScore(name$, score)
remstart
@C Check the position, and add the score
@C We achieve this by shifting all lower scores down by 1,
@C and inserting our new score
remend	
	
	position = hiScoreCheckScore(score)
	if position <> -1
		for n = gHSG.count - 1 to position step - 1
			gHiScore(n + 1).name$ = gHiScore(n).name$
			gHiScore(n + 1).score = gHiScore(n).score
		next n
		gHiScore(position).name$ = name$
		gHiScore(position).score = score
	endif
	
endfunction

function HiScoreEncrypt(txt$)
remstart
@C Encrypt the value and return the result
@C Use the KeyWord, the random seed and bitwise operations
remend	
	
	randomize gHSG.seed
	for n = 1 to len(txt$)
		char1 = asc(mid$(txt$,n,1))
		char2 = asc(mid$(gHSG.KeyWord$,rnd(KeyLength - 1) + 1,1))
		result$ = result$ + chr$(char1 ~~ char2)
	next n
	
endfunction result$

function HiScoreDeCrypt(txt$)
remstart
@C This is what is called "Smoke and Mirrors",
@C just to illustrate a point.  Encryption and Decryption is
@C exactly the same operation, so we will call the previous function
remend	
	
	result$ = HiScoreEncrypt(txt$)
		
endfunction result$

function HiScoreEncryptValue(value)
remstart
@C Encrypt the value and return the result
@C Use the KeyWord, the random seed and bitwise operations
remend	
	
	randomize gHSG.seed
	keyvalue = asc(mid$(gHSG.KeyWord$,rnd(KeyLength - 1) + 1,1))
	result = value ~~ keyValue
	
endfunction result

function HiScoreDeCryptValue(value)
remstart
@C This is what is called "Smoke and Mirrors",
@C just to illustrate a point.  Encryption and Decryption is
@C exactly the same operation, so we will call the previous function
remend	
	
	result = HiScoreEncryptValue(value)
		
endfunction result

function HiScoreGenerateSeed()
remstart
@C Generate the random seed for encryption
remend

	randomize timer()
	gHSG.seed = rnd(255)

endfunction

function getFreeFile()
remstart
@C Find a free file number to use
remend
	
	n = 1
	while file open(n) = 1
		inc n
	endwhile
	
endfunction n
	
	 
0
No votes yet