Jump to content




Problem with encrypting messages


  • You cannot reply to this topic
6 replies to this topic

#1 TheOddByte

    Lazy Coder

  • Members
  • 1,607 posts
  • LocationSweden

Posted 19 December 2014 - 01:43 PM

Hey, I'm trying todo a secure rednet connection between two computers, the host and the client. When I tried this I noticed that sometimes it doesn't work, it seems the encryption gets a nil value. Here's the test scripts I used
Server
Client
You should know that I'm using GravityScore's SHA256 script, and SquidDev's AES encryption API. I found the Base64 encoder here

This is the result I got from running the scripts above, don't say that it's because I'm using an emulator I'm getting this result.
I have tried it in-game as well, I got the same result there. ( and I don't know why it happens :/ )
Posted Image

#2 SquidDev

    Frickin' laser beams | Resident Necromancer

  • Members
  • 1,427 posts
  • LocationDoes anyone put something serious here?

Posted 19 December 2014 - 07:15 PM

I've done a bit of debugging with this. I'm using the un-minified version of Aes (DMx8M0LP). I'll post my findings so far, if I make any progress then I'll write add it to this:

At about line 1512 there is a function called decryptString. This is called by aes.decrypt. The trouble is, the string being passed is less than 16 characters long, resulting in the buffer never being filled, so nil is returned, so the validation fails, so everything blows up.

16 characters are passed as the value is never b64 decoded. Hmm.


UPDATE:
I've found why. This is your current code:

local function decrypt( data, key )
  if type( data ) == "table" then
    for k, v in pairs( data ) do
      local index = base64.decode( k )
      local value = base64.decode( v )
      data[AES.decrypt( key, index )] = AES.decrypt( key, value )  -- <== LOOK!
    end
  elseif type( data ) == "string" then
    data = base64.decode( data )
    data = AES.decrypt( key, data )
  end
  return data
end
The line kinda highlighted above shows the problem. You are assigning to the same table as before. So if the decrypted version occurs after the encrypted version in the table it attempts to decrypt it twice. Changing the output data to be called result, or dataResult or whatever would solve everything.

Edited by SquidDev, 19 December 2014 - 07:31 PM.


#3 TheOddByte

    Lazy Coder

  • Members
  • 1,607 posts
  • LocationSweden

Posted 20 December 2014 - 12:04 PM

View PostSquidDev, on 19 December 2014 - 07:15 PM, said:

...
Thanks, it works without the tables getting corrupted now! :D

#4 TheOddByte

    Lazy Coder

  • Members
  • 1,607 posts
  • LocationSweden

Posted 20 December 2014 - 07:17 PM

Okay, another question. I don't know why but when I have connected the client to the server and try to send a message to it, it returns a nil message
Server
Client
SNet API
Anyone have a clue what the problem is here?

#5 Bomb Bloke

    Hobbyist Coder

  • Moderators
  • 7,099 posts
  • LocationTasmania (AU)

Posted 21 December 2014 - 07:23 AM

I haven't read all your code, but the SNet:receive() function stood out to me as a bit of a mess; if a timeout higher than one second is specified, it'll fail to respect it (as you only ever run one timer for one second, then fail to start a new one when it ends). Either way, it never tries to decrypt the right variable. You could re-write it like so:

function SNet:receive( timeout )
	if type(timeout) == "number" then timeout = os.startTimer(timeout) end
	
	while true do
		local e = { os.pullEvent() }
		if e[1] == "rednet_message" and self:isValidID( e[2] ) and e[4] == self.protocol then
			return e[2], decrypt( e[3], self.key )
		elseif e[1] == "timer" and e[2] == timeout then return nil end
	end
end

Regarding the problem at hand, I'd stick print statements into the decrypt function to 1) determine if it's getting called when you think it's getting called 2) indicate what data's being passed to it 3) indicate what data it thinks it's passing back. Depending on what the results tell you, you should be able to track down where the logic jumps off the expected rails.

#6 TheOddByte

    Lazy Coder

  • Members
  • 1,607 posts
  • LocationSweden

Posted 21 December 2014 - 12:49 PM

View PostBomb Bloke, on 21 December 2014 - 07:23 AM, said:

I haven't read all your code, but the SNet:receive() function stood out to me as a bit of a mess; if a timeout higher than one second is specified, it'll fail to respect it (as you only ever run one timer for one second, then fail to start a new one when it ends). Either way, it never tries to decrypt the right variable. You could re-write it like so:

function SNet:receive( timeout )
	if type(timeout) == "number" then timeout = os.startTimer(timeout) end
	
	while true do
		local e = { os.pullEvent() }
		if e[1] == "rednet_message" and self:isValidID( e[2] ) and e[4] == self.protocol then
			return e[2], decrypt( e[3], self.key )
		elseif e[1] == "timer" and e[2] == timeout then return nil end
	end
end

Regarding the problem at hand, I'd stick print statements into the decrypt function to 1) determine if it's getting called when you think it's getting called 2) indicate what data's being passed to it 3) indicate what data it thinks it's passing back. Depending on what the results tell you, you should be able to track down where the logic jumps off the expected rails.
Well thanks, But I've never really used that function yet as I planned on fixing it later. The real problems is in the SNet:handle function. It seems something goes wrong with the encryption there and it returns a nil message on the server when decrypting.

#7 TheOddByte

    Lazy Coder

  • Members
  • 1,607 posts
  • LocationSweden

Posted 21 December 2014 - 06:26 PM

Just found out what was wrong
local function decrypt( data, key )
	local result = {}
	if type( data ) == "table" then
   result = {}
   for k, v in pairs( data ) do
   local index = base64.decode( k )
index = AES.decrypt( key, index )
local value = base64.decode( v )
value = AES.decrypt( key, value )
   result[index] = value
end

elseif type( data ) == "string" then
   result = base64.decode( data )
result = AES.decrypt( key, data ) -- this line of code was trying to decrypt the base64 encoded string
end
	return result
end
local function decrypt( data, key )
	local result = {}
	if type( data ) == "table" then
   result = {}
   for k, v in pairs( data ) do
   local index = base64.decode( k )
index = AES.decrypt( key, index )
local value = base64.decode( v )
value = AES.decrypt( key, value )
   result[index] = value
end

elseif type( data ) == "string" then
   result = base64.decode( data )
result = AES.decrypt( key, result ) -- now that's more like it :3
end
	return result
end
Thanks for the help everyone, and thanks for cleaning up my code Bomb Bloke ^^

Posted Image

Edited by TheOddByte, 21 December 2014 - 06:30 PM.






1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users