This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
KingofGamesYami's profile picture

SecureModem

Started by KingofGamesYami, 14 May 2014 - 01:29 AM
KingofGamesYami #1
Posted 14 May 2014 - 03:29 AM
So, as most everyone has noticed, there is no safe way of encoding/decoding modem messages. I have decided to make it as hard as possible to determine what it is that is being sent, so I created this. It will transmit parts of the message on 10 different, random channels. The number specified in each function needs to be the same or the message will not get through correctly.

Spoiler

function send(info, mchannel) --info is either a table or a string.  mchannel is any number that modems can be opened on, minus 128.  
 if type(info) == "table" then
  info = textutils.serialize(info)
 end

 for i = 1, #info, #info/10 do
  modem.transmit(math.floor(math.random(mchannel, mchannel + 128)), os.getComputerID(), info:sub(i, (#info/10) * i))
 end
end
function receive(mchannel)
 for i = mchannel, mchannel + 128 do
  modem.open(side, i)
 end
 local info = {}
 for i = 1, 10 do
  msg = {os.pullEvent("modem_message")}
  info[i] = msg[5]
 end
 info = table.concat(info)

 if type(textutils.unserialize(info)) == "table" then
  return textutuils.unserialize(info)
 else
  return info
 end
end
awsmazinggenius #2
Posted 14 May 2014 - 03:35 AM
Why not just have an agreed upon AES key to encrypt messages?
KingofGamesYami #3
Posted 14 May 2014 - 04:23 AM
Why not just have an agreed upon AES key to encrypt messages?
Never heard of it. Google searching did not turn up any results that I could figure out how to implement in lua.
awsmazinggenius #4
Posted 14 May 2014 - 05:12 AM
There is one implementation of it right on these very forums, so clearly you haven't looked very hard.
apemanzilla #5
Posted 14 May 2014 - 12:58 PM
Why not just have an agreed upon AES key to encrypt messages?
It would likely be a good amount slower.
theoriginalbit #6
Posted 14 May 2014 - 01:15 PM
in all honesty, you could fairly simply write a program to sniff out transmissions from a program using this.
skwerlman #7
Posted 14 May 2014 - 01:31 PM
in all honesty, you could fairly simply write a program to sniff out transmissions from a program using this.
Agreed. Unless you also obfuscate/encrypt the data, it's super easy to to just log all traffic and re-assemble it into it original form.
Since the target and number of messages is always the same, if you detect 10 messages fired one after another, and each is heading to the same place, and the first nine are the same length, there's a super high chance that it's coming from your algorithm, so we concatenate the messages. Viola, obfuscation circumvented.
Implementing even a basic rolling cypher instead makes communication less not secure (not quite safer); since it looks like 'normal' traffic it can't be singled out as easily. The best way to secure data is to do so without it looking secure.
KingofGamesYami #8
Posted 14 May 2014 - 01:43 PM
in all honesty, you could fairly simply write a program to sniff out transmissions from a program using this.
Agreed. Unless you also obfuscate/encrypt the data, it's super easy to to just log all traffic and re-assemble it into it original form.
Since the target and number of messages is always the same, if you detect 10 messages fired one after another, and each is heading to the same place, and the first nine are the same length, there's a super high chance that it's coming from your algorithm, so we concatenate the messages. Viola, obfuscation circumvented.
Implementing even a basic rolling cypher instead makes communication less not secure (not quite safer); since it looks like 'normal' traffic it can't be singled out as easily. The best way to secure data is to do so without it looking secure.
Ah, but the idea here is that it sends each message on a different channel! Hacking computer would have to open all 128 channels above the channel you used. I'm looking into converting to binary & using an algebraic equation to encode/decode it (yes I realize this would still be vulnerable, but if they only got 9/10 pieces…)
theoriginalbit #9
Posted 14 May 2014 - 02:20 PM
Ah, but the idea here is that it sends each message on a different channel! Hacking computer would have to open all 128 channels above the channel you used.
not a problem at all.
Wojbie #10
Posted 14 May 2014 - 02:33 PM
In this situation if all goes down to how many ender-pearls you want to spend on wireless modems.
128 channels per modem
65535/128=512 modems with one channel free ;D
6 modems per computer
86 computers and you are listening to it all.
5 modems plus one wired for database stuff
103 computers + one mainframe and you spy and record all
Doable if someone is bored ;D

Edit - is 0 a valid channel?
Edited on 14 May 2014 - 12:34 PM
theoriginalbit #11
Posted 14 May 2014 - 02:42 PM
In this situation if all goes down to how many ender-pearls you want to spend on wireless modems.
128 channels per modem
65535/128=512 modems with one channel free ;D
6 modems per computer
86 computers and you are listening to it all.
5 modems plus one wired for database stuff
103 computers + one mainframe and you spy and record all
Doable if someone is bored ;D

Edit - is 0 a valid channel?
not even really needed to go that overkill. I quickly whipped up a simple solution that has a fairly good chance of picking up the communications, but once it has picked up something it will always continue to pick it up… it uses 2 modems and ~27 lines of code. with a few more lines of code and no extra modems it could easily be improved to heighten the chance of initially picking up the communications.
Edited on 14 May 2014 - 01:12 PM
Wojbie #12
Posted 14 May 2014 - 03:14 PM
not even really needed to go that overkill. I wrote a simple solution that has a fairly good chance of picking up the communications, but once it has picked up something it will always continue to pick it up… it uses 2 modems and 27 lines of code. with a few more lines of code and no extra modems it could easily be improved to heighten the chance of initially picking up the communications.
Frequency scanner? You are jumping over frequencies and saving those that got used? Yea that would work too :)/> But overkill looks more awesome in-game :D/> When server has extended rednet range its even better :P/> As for rednet i for one prefer to use my enigma to encode my messages. If someone if preexistent they will break it but i will make them learn history to do it!
theoriginalbit #13
Posted 14 May 2014 - 04:31 PM
Frequency scanner? You are jumping over frequencies and saving those that got used?
Yes and no… threw it together in about a minute, so everything is fairly static, its just more of a proof of concept than something I'd actually put into use
Code

local m1, m2 = peripheral.wrap("left"), peripheral.wrap("right")
local max, messages = 65535, {}

local function close(modem)
  for i = 1, max do
	if modem.isOpen(i) then
	  modem.close(i)
	end
  end
end

local function open(modem, lower, upper, incr)
  close(modem)
  incr = incr or 1
  for i = lower, upper, incr do
	modem.open(i)
  end
end

open(m1, 1, 2048, 16)
open(m2, 2049, 4096, 16)

while true do
  local _, _, channel, _, msg  = coroutine.resume("modem_message")
  local maxPotential = math.max(channel + 128, max)
  local minPotential = math.min(1, channel - 128)

  open(m1, minPotential, channel)
  open(m2, channel, maxPotential)

  table.insert(messages, msg)
end
Edited on 15 May 2014 - 12:55 AM
Anavrins #14
Posted 14 May 2014 - 06:20 PM
Why not just have an agreed upon AES key to encrypt messages?
It would likely be a good amount slower.

I've tried with KillaVanilla AES-128 implementation, and with proper usage, it's fairly quick, quick enough for most uses at least.
KingofGamesYami #15
Posted 14 May 2014 - 10:40 PM
I'm not saying it's impossible to hack, I'm just saying it's harder to hack than normal. If the hacker is lazy, he won't have thought of listening on all channels. I could send it backwards, but I don't see the point in that. The point of this isn't to make unhackable, its to make it annoyingly difficult to hack.

PS: I'm not hating anyone here, just explaining what I'm trying to do.
RoD #16
Posted 14 May 2014 - 11:07 PM
I'm not saying it's impossible to hack, I'm just saying it's harder to hack than normal. If the hacker is lazy, he won't have thought of listening on all channels. I could send it backwards, but I don't see the point in that. The point of this isn't to make unhackable, its to make it annoyingly difficult to hack.

PS: I'm not hating anyone here, just explaining what I'm trying to do.
lazyness? well he can open a lot of channels at the same time. No need to test them all one by one.
theoriginalbit #17
Posted 15 May 2014 - 02:52 AM
The point of this isn't to make unhackable, its to make it annoyingly difficult to hack.
I don't think a minute of coding is really all that annoyingly difficult… I put an extra minute into it this morning and made a truly random scanner that locks onto the signal once found
Code

local m1, m2 = peripheral.wrap("left"), peripheral.wrap("right")
local max, channelFound, messages = 65535, false, {}

local function close(modem)
  for i = 1, max do
	if modem.isOpen(i) then
	  modem.close(i)
	end
  end
end

local function open(modem, lower, upper, incr)
  close(modem)
  incr = incr or 1
  for i = lower, upper, incr do
	modem.open(i)
  end
end

local function count(t)
  local c = 0
  for _ in pairs(t) do
	c = c + 1
  end
  return c
end

local function generateRandomSets()
  local rands = {}
  repeat
	rands[math.random(1, max)] = true
  until count(rands) == 256
  local i = 0
  local set1, set2 = {}, {}
  for k in pairs(rands) do
	i = i + 1
	table.insert(i <= 128 and set1 or set2, k)
  end
  return set1, set2
end

local function refreshModem(modem, channels)
  close(modem)
  for _,c in pairs(channels) do
	modem.open(c)
  end
end

local function refresh()
  local s1, s2 = generateRandomSets()
  refreshModem(m1, s1)
  refreshModem(m2, s2)
end

local refreshTimer = os.startTimer(1)

while true do
  if not channelFound then
	refresh()
  end

  local event, param, channel, _, msg  = coroutine.resume()

  if event == "modem_message" then
	if not channelFound then
	  local maxPotential = math.max(channel + 128, max)
	  local minPotential = math.min(1, channel - 128)
	  open(m1, minPotential, channel)
	  open(m2, channel, maxPotential)
	  print("Found signal in range ("..minPotential..","..maxPotential..")...")
	  print("Press 'r' to unlock from this range...")
	  channelFound = true
	end

	table.insert(messages, msg)
  elseif event == "key" and param == keys.r then
	channelFound = false
  end
end
Don't get me wrong, I do like the thinking outside of the box… just think a little further outside… ;)/>
Edited on 15 May 2014 - 01:05 AM
KingofGamesYami #18
Posted 15 May 2014 - 01:43 PM
The point of this isn't to make unhackable, its to make it annoyingly difficult to hack.
I don't think a minute of coding is really all that annoyingly difficult… I put an extra minute into it this morning and made a truly random scanner that locks onto the signal once found
Code

local m1, m2 = peripheral.wrap("left"), peripheral.wrap("right")
local max, channelFound, messages = 65535, false, {}

local function close(modem)
  for i = 1, max do
	if modem.isOpen(i) then
	  modem.close(i)
	end
  end
end

local function open(modem, lower, upper, incr)
  close(modem)
  incr = incr or 1
  for i = lower, upper, incr do
	modem.open(i)
  end
end

local function count(t)
  local c = 0
  for _ in pairs(t) do
	c = c + 1
  end
  return c
end

local function generateRandomSets()
  local rands = {}
  repeat
	rands[math.random(1, max)] = true
  until count(rands) == 256
  local i = 0
  local set1, set2 = {}, {}
  for k in pairs(rands) do
	i = i + 1
	table.insert(i <= 128 and set1 or set2, k)
  end
  return set1, set2
end

local function refreshModem(modem, channels)
  close(modem)
  for _,c in pairs(channels) do
	modem.open(c)
  end
end

local function refresh()
  local s1, s2 = generateRandomSets()
  refreshModem(m1, s1)
  refreshModem(m2, s2)
end

local refreshTimer = os.startTimer(1)

while true do
  if not channelFound then
	refresh()
  end

  local event, param, channel, _, msg  = coroutine.resume()

  if event == "modem_message" then
	if not channelFound then
	  local maxPotential = math.max(channel + 128, max)
	  local minPotential = math.min(1, channel - 128)
	  open(m1, minPotential, channel)
	  open(m2, channel, maxPotential)
	  print("Found signal in range ("..minPotential..","..maxPotential..")...")
	  print("Press 'r' to unlock from this range...")
	  channelFound = true
	end

	table.insert(messages, msg)
  elseif event == "key" and param == keys.r then
	channelFound = false
  end
end
Don't get me wrong, I do like the thinking outside of the box… just think a little further outside… ;)/>
hmm… what if I generated some random stuff on random channels? It wouldn't be too hard to implement.
apemanzilla #19
Posted 15 May 2014 - 01:56 PM
The point of this isn't to make unhackable, its to make it annoyingly difficult to hack.
I don't think a minute of coding is really all that annoyingly difficult… I put an extra minute into it this morning and made a truly random scanner that locks onto the signal once found
Code

local m1, m2 = peripheral.wrap("left"), peripheral.wrap("right")
local max, channelFound, messages = 65535, false, {}

local function close(modem)
  for i = 1, max do
	if modem.isOpen(i) then
	  modem.close(i)
	end
  end
end

local function open(modem, lower, upper, incr)
  close(modem)
  incr = incr or 1
  for i = lower, upper, incr do
	modem.open(i)
  end
end

local function count(t)
  local c = 0
  for _ in pairs(t) do
	c = c + 1
  end
  return c
end

local function generateRandomSets()
  local rands = {}
  repeat
	rands[math.random(1, max)] = true
  until count(rands) == 256
  local i = 0
  local set1, set2 = {}, {}
  for k in pairs(rands) do
	i = i + 1
	table.insert(i <= 128 and set1 or set2, k)
  end
  return set1, set2
end

local function refreshModem(modem, channels)
  close(modem)
  for _,c in pairs(channels) do
	modem.open(c)
  end
end

local function refresh()
  local s1, s2 = generateRandomSets()
  refreshModem(m1, s1)
  refreshModem(m2, s2)
end

local refreshTimer = os.startTimer(1)

while true do
  if not channelFound then
	refresh()
  end

  local event, param, channel, _, msg  = coroutine.resume()

  if event == "modem_message" then
	if not channelFound then
	  local maxPotential = math.max(channel + 128, max)
	  local minPotential = math.min(1, channel - 128)
	  open(m1, minPotential, channel)
	  open(m2, channel, maxPotential)
	  print("Found signal in range ("..minPotential..","..maxPotential..")...")
	  print("Press 'r' to unlock from this range...")
	  channelFound = true
	end

	table.insert(messages, msg)
  elseif event == "key" and param == keys.r then
	channelFound = false
  end
end
Don't get me wrong, I do like the thinking outside of the box… just think a little further outside… ;)/>/>
hmm… what if I generated some random stuff on random channels? It wouldn't be too hard to implement.
What if you used encryption? :3
theoriginalbit #20
Posted 15 May 2014 - 02:38 PM
hmm… what if I generated some random stuff on random channels? It wouldn't be too hard to implement.
That was just a proof of concept to prove the ease of intercepting your communications with the simplest of scripts. Could easily implement one with a timeout after getting a message, say wait 0.2 seconds, if another message is not received then scan the channels again. Etc etc.
RoD #21
Posted 15 May 2014 - 05:44 PM
I may give a try at originalbit's code. It seems pretty safe to use in wireless comunication :)/>
hbomb79 #22
Posted 12 June 2014 - 11:50 PM
How do you intercept/log rednet messages if they are only being sent to a certain PC ID and if the PC your sending it to only read messages from the correct id, that how my system work, the main PC send messages to id 6 and it sees if the message came from id 2 if it did I allows it through other wise, it won't and will throw up an error telling me what I said, what protocol it had and where it came from…
Anavrins #23
Posted 13 June 2014 - 12:30 AM
You can open all 65535 channels by having a setup of multiple computers with 5 modems on them, connected to a "master" computer via wired modem.
I have a pair of programs that does just that, so this channel hopping strategy is kinda pointless.

Your best bet if to use encryption (There's AES by KillaVanilla)
theoriginalbit #24
Posted 13 June 2014 - 01:53 AM
How do you intercept/log rednet messages if they are only being sent to a certain PC ID and if the PC your sending it to only read messages from the correct id, that how my system work, the main PC send messages to id 6 and it sees if the message came from id 2 if it did I allows it through other wise, it won't and will throw up an error telling me what I said, what protocol it had and where it came from…
In the latest ComputerCraft there is no direct messaging anymore, messages are sent on channels, so if you have the channel open you can hear the message, as such the channels that rednet open are the ID of the computer. As such it means any computer can easily spoof the ID they've come from and negate your validation.
RoD #25
Posted 13 June 2014 - 01:52 PM
FlagHacker gave my a really good tip:
Encryption uses keys. This key needs to be the same in the other computer. But like that the hacker can send the encrypted message and the other computer will think that it was an authentic message and will do the normal procedure. However, if this key is a random number (not really random but alaways changing) you can encrypt messages and they will work only once. this can be achieved using os.getTime() and os.day(). You use these as keys and they only work once. BTW: you may want to change the length of the os.getTime() because is so fast that the key will be diferent (os.getTime() includes milliseconds).
theoriginalbit #26
Posted 13 June 2014 - 02:03 PM
FlagHacker gave my a really good tip:
Encryption uses keys. This key needs to be the same in the other computer. But like that the hacker can send the encrypted message and the other computer will think that it was an authentic message and will do the normal procedure. However, if this key is a random number (not really random but alaways changing) you can encrypt messages and they will work only once. this can be achieved using os.getTime() and os.day(). You use these as keys and they only work once. BTW: you may want to change the length of the os.getTime() because is so fast that the key will be diferent (os.getTime() includes milliseconds).
but then you cannot decrypt it. this is a very silly method of encryption, just look into asymmetric keys.
RoD #27
Posted 13 June 2014 - 03:43 PM
FlagHacker gave my a really good tip:
Encryption uses keys. This key needs to be the same in the other computer. But like that the hacker can send the encrypted message and the other computer will think that it was an authentic message and will do the normal procedure. However, if this key is a random number (not really random but alaways changing) you can encrypt messages and they will work only once. this can be achieved using os.getTime() and os.day(). You use these as keys and they only work once. BTW: you may want to change the length of the os.getTime() because is so fast that the key will be diferent (os.getTime() includes milliseconds).
but then you cannot decrypt it. this is a very silly method of encryption, just look into asymmetric keys.
As i said, the other computer will decrypt using the same key (the key is the time and if the message is sent right after being encrypted, it will send encrypted to the other computer, then this computer can decrypt using the time)
theoriginalbit #28
Posted 13 June 2014 - 04:22 PM
As i said, the other computer will decrypt using the same key (the key is the time and if the message is sent right after being encrypted, it will send encrypted to the other computer, then this computer can decrypt using the time)
and if the send/receive time isn't the same? i.e. it has gone through several repeating computers? this is why asymmetric keys are better, they're not dependent on anything changeable, they're static (well static-ish).
RoD #29
Posted 13 June 2014 - 04:53 PM
the send/receive time is the same, the encryption time isnt, but just by a few miliseconds (thats why i use string.sub() to remove the last 3 digits of the os.getTime()) in the case of repeating trough various computers, you can decrypt the mssage and encrypt with the new time.