Code archives/Algorithms/LCG 32bits Cipher

This code has been declared by its author to be Public Domain code.

Download source code

LCG 32bits Cipher by FlankerApril
A first simple cipher, based on 2 functions (lib), and a working GUI example (app). A little documentation in LCG 32bits_lib.bmx, more infos about LCG : https://en.wikipedia.org/wiki/Linear_congruential_generator



LCG 32bits Cipher_app.bmx
' LCG 32bits Cipher_lib.bmx
'
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Linear Congruential Generator (LCG) Cipher/Decipher
'
' LCG is an algorithm to generate a sequence of pseudorandom numbers. Each number in
' the sequence is based on the previous one. For the first number, a seed is used.
'
' number = (seed * a + c) Mod m
' then seed = number
' etc...
'
' Different parameters affect the quality of the randomness :
' - a : multiplier
' - c : increment
' - m : modulo
'
' You can find more infos about LCG and proven parameters on wikipedia :
' (linear congruential generator)
' 
' A cipher based on LCG is considered weak to frequency analysis because of the
' linearity wich permits to break m, a and c values with mathematics. However, it
' will be enough protection against a non initiated curious user, and combined with
' XOR it is suitable to protect non crucial files. Also, it's fast and light.
'
' Here, numbers are simply ciphered 4 bytes by 4 bytes (32 bits), using XOR and LCG.
' It could be extended to cipher 8 bytes by 8 bytes (64 bits), using Long, but one
' would break 64 bits as easily as 32 bits, if he knows what he is doing.
'
' Both functions work with banks, you can read a ciphered file with LoadBank(file$),
' call the decipher function and read the original file in the returned bank. You
' can write the original file back with SaveBank(decipherBank,file) if you want.
'
' The seed is like a secret key. It is the first number of the random sequence, so
' deciphering with a wrong key will mess up everything after. If you don't provide
' a key when ciphering (0), a random one is chosen and stored in the ciphered file.
' All you'll have to know to decipher are the parameters used to cipher. If you
' provide a key when ciphering, it won't be stored in the ciphered file so you'll
' have to remember and provide both key and parameters to decipher (stronger).
'
' Flanker, 2017 (this is my first try in ciphering, take it easy :)
'
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Function LCG32Cipher:TBank(dataIn:TBank,a:Int=16807,c:Int=2^31-1,m:Int=0,seed:Int=0)
	
	Local pollTimer:Int = MilliSecs() ' <<<<< Only used for the GUI example, remove if necessary
	
	Local dataHeader:Int
	Local dataOffset:Int
	
	Local dataSize:Int = BankSize(dataIn)
	Local dataOut:TBank = CreateBank(4 + dataSize)

	If dataSize Mod 4 > 0
		ResizeBank(dataIn,dataSize + 4-(dataSize Mod 4))
		ResizeBank(dataOut,BankSize(dataOut) + 4-(dataSize Mod 4))
	EndIf	
	
	PokeInt dataOut,dataOffset,dataSize
	dataOffset = dataOffset + 4
	
	If seed = 0
		seed = Rand(2^31-1)
		ResizeBank(dataOut,BankSize(dataOut)+4)
		PokeInt dataOut,dataOffset,seed
		dataOffset = dataOffset + 4
	EndIf
	
	dataHeader = dataOffset
	
	While dataOffset-dataHeader < BankSize(dataIn)
		
		Local valueIn:Int = PeekInt(dataIn,dataOffset-dataHeader)
		Local valueOut:Int = valueIn~seed ' XOR
		PokeInt(dataOut,dataOffset,valueOut)
		
		seed = ( seed * a + c ) Mod m
		dataOffset = dataOffset + 4
		
		' Only used for the GUI example >>>>>
		If MilliSecs()-pollTimer > 50
			UpdateProgBar(progressBar,Float(dataOffset-dataHeader)/Float(BankSize(dataIn)))
			PollSystem()
			pollTimer = MilliSecs()
		EndIf
		' <<<<< Only used for the GUI example
		
	Wend
	
	Return dataOut	
	
End Function

''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Function LCG32Decipher:TBank(dataIn:TBank,a:Int=16807,c:Int=2^31-1,m:Int=0,seed:Int=0)
	
	Local pollTimer:Int = MilliSecs() ' <<<<< Only used for the GUI example, remove if necessary
	
	Local dataHeader:Int
	Local dataOffset:Int
	
	Local dataSize:Int = PeekInt(dataIn,dataOffset)
	dataOffset = dataOffset + 4
	
	If dataSize < 0 Then Return CreateBank(0)
	
	Local dataOut:TBank = CreateBank(dataSize)
	
	If dataSize Mod 4 > 0 Then ResizeBank(dataOut,BankSize(dataOut) + 4-(dataSize Mod 4))
	
	If seed = 0
		seed = PeekInt(dataIn,dataOffset)
		dataOffset = dataOffset + 4
	EndIf
	
	dataHeader = dataOffset
	
	While dataOffset < BankSize(dataIn)
		
		If dataOffset-dataHeader > BankSize(dataOut) Then Return CreateBank(0)
		
		Local valueIn:Int = PeekInt(dataIn,dataOffset)
		Local valueOut:Int = valueIn~seed ' XOR
		PokeInt(dataOut,dataOffset-dataHeader,valueOut)
		
		seed = ( seed * a + c ) Mod m
		dataOffset = dataOffset + 4
		
		' Only used for the GUI example >>>>>
		If MilliSecs()-pollTimer > 50
			UpdateProgBar(progressBar,Float(dataOffset)/Float(BankSize(dataIn)))
			PollSystem()
			pollTimer = MilliSecs()
		EndIf
		' <<<<< Only used for the GUI example

	Wend

	ResizeBank(dataOut,dataSize)
	
	Return dataOut

End Function

Comments

None.

Code Archives Forum