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

Authenticate two computers against each other

Started by Calimore, 30 May 2013 - 02:11 AM
Calimore #1
Posted 30 May 2013 - 04:11 AM
Hi there…

I'm looking for a way to authenticate two computers against each other. I think this does not have to be highly secure but should offer some more protection than just transmit a shared password in plain-text. E.g. I know how IKE works in a IPSec VPN but this is just too much…

Does anyone have an idea for a straightforward mechanism to do something like this?

Thanks for any hints…
bbqroast #2
Posted 30 May 2013 - 04:45 AM
http://www.computercraft.info/forums2/index.php?/topic/6003-cc-146-computercraft-crypto-rev1/

That's an API that provides public/private key authentication. It's quite useful, public private key encryption creates two seperate keys, one for encrypting and one for decryption.

If you want to "authenticate" a computer (ie know it is who it says it is).
You first need to create a key pair, give the decryption key to any computer you wish to talk to (ie the public key) and keep the encryption key (ie the private key).
When the computer wants to send a message it encrypts it first, and the receiving computers who decrypt the message know it was sent by the computer because it was encrypted using your encryption key, which is kept private. The public key (decryption key) in this case is often called a certificate.
To expand on this, you can provide all computers with the decryption key of a master server, when they want to connect to another computer the master server (after authenticating with them) provides them with the decryption key of the other computer, that way you can have a large network of computers that can expand dynamically (as long as they all trust the central master server).

If you want to send a message securely the receiver (after being notified of the incoming message) simply creates a key pair, sends the encryption key over plain text to the sender who then encrypts the message and sends it back. The main risk here is an attacker can pretend to be the receiver, to secure against this do two things: quickly share a "secret" using the encrypted line so the receiver can verify any further communications (this way the attacker can't wait for the sender to send some valuable information (eg a password), the attacker can't get the number but it can send some spoofed information (for example a command that requires the password to be entered). If they have a shared secret then the receiving computer knows that it is the same computer talking), however this does not prevent an attacker from starting the conversation from the start (and pretending to be the server) so using a "certificate" (as outlined above) is a good measure.
Calimore #3
Posted 30 May 2013 - 05:12 AM
Hi bbqroast,

thanks for your reply. This is great… In general I know how this works but I never tried to implement something like this. I am more of a tech guy than a coder… :rolleyes:/>

There's something I don't get right away… The above link is for an AES implementation which is a symmetric crypto cipher (so the same key is used for en/decryption). In your post above you claim that the API "provides public/private key auth". What am I missing…?
Calimore #4
Posted 30 May 2013 - 06:36 AM
Hmmm… I think I'd need something like this (http://en.wikipedia....nge#Description)
After that I could use AES (or any other sort of symmetric cipher) to send encrypted messages without the need to pre-share secrets before program startup.

The code for this DH-algorithm looks reasonable but the calculated numbers used for this start to get quite big even for low primes… what's the largest number lua can handle? I guess I'll have to handle variable overflow which puts me way out of my comfort zone…
Bomb Bloke #5
Posted 30 May 2013 - 08:00 AM
I gather it can use 64bit double-precision floats. I suspect it often does.

Assuming you're talking about RedNet, and "computer" authentication as opposed to "user" authentication, would it not just be sufficient to rely on the computer ID numbers transmitted with each signal? I'm sure they could be spoofed, but I doubt most CC programmers would understand the concept, let alone know how it's done, let alone figure out it needs to be done to breach your setup.
Calimore #6
Posted 30 May 2013 - 11:41 AM
would it not just be sufficient to rely on the computer ID numbers transmitted with each signal? I'm sure they could be spoofed, but I doubt most CC programmers would understand the concept, let alone know how it's done, let alone figure out it needs to be done to breach your setup.

OK let's step back from the coding stuff for a minute…

I agree with you that relying on the senderid would be sufficient for my scenario.

To be honest I'm completely thrown off by the concept of how communication is handled by ComputerCraft.

Let's have a look at the wiki. If "As of ComputerCraft 1.5, the Rednet API is just a wrapper for modems and channels", why is it that I don't get any other info from the modem API that rednet is wrapping.

When reading directly from a modem event I get event, modemSide, senderChannel, replyChannel, message, senderDistance but no info regarding who sent this message.
if I use rednet.receive I get a "senderid" alright but no other information like the senderChannel or the replyChannel.

Is it just me or is this really strange behaviour? When I think of computer to computer communication (and the way TCP/IP works might have a big influence on my thinking) I would say the most important stuff I can get from both APIs (modem and rednet) are:

sender, receiver, receiverchannel and maybe a replychannel

Why is some of this vital information lost when using either API? :unsure:/>

EDIT: One could argue that channels are not necessary for communication… The concept of reducing load from all computer within WLAN range by using channels to address only a single/few computers makes perfect sense. So the question remains… Why…?

EDIT 2: Btw… Again it might just be me but using rednet.receive and having my program waiting for something to happen or timeout is just ugly… -_-/> What if the receiver program should do something and maybe change behaviour when it receives a message telling it to do something else
Bomb Bloke #7
Posted 30 May 2013 - 07:02 PM
You've got three ways of sending messages:

One is a Rednet API broadcast. This sends the message to all computers in range, so is inherantly unsecure.

Another is a Rednet API send. This sends the message to one specific computer, and best I can make out, can't be intercepted.

The third is a Modem API transmit. This acts like a broadcast (so it's easily intercepted), but it flags its messages with a port number, offering a simple way for other machines to get some idea of what the message is about. I wasn't actually aware of this method of doing things until reading your above post.

For general communications, sending tables seems to be the way to go (textutils.serialize them before transmission, textutils.unserialize them on receipt):

message = {os.getComputerID(), myChannel, myMessage}

This would allow you to easily include senderIDs in a standard format when using the modem API, and if you have a use for channels (… and unless your servers are making communications about more then one subject, I don't think you do), then it'd give you an easy way to specify those when using the Rednet API.

TL;DR version: I think ComputerCraft transmissions are more akin to sending/receiving using MAC addresses than IP addresses. You can simulate something like TCP/IP, but it's probably more effort then it's worth to build a DHCP server (unless dealing with a large amount of computers that come and go on a regular basis). Building something similar to a WINS server is a good idea if you have ANY amount of computers coming and going, but mostly pointless if you only want two specific computers to talk exclusively to each other.

Anyway, regarding the rednet.receive timeout issue, it seems it IS possible to have a program multi-task so it's always listening for incoming messages, even while executing other functions. However, the quick'n'dirty fix is to have the sender wait for a reply, time out, and resend in a loop until it gets it. Think of it as allowing you to simulate either TCP or UDP. ;)/>
bbqroast #8
Posted 31 May 2013 - 02:18 AM
Hi bbqroast,

thanks for your reply. This is great… In general I know how this works but I never tried to implement something like this. I am more of a tech guy than a coder… :rolleyes:/>

There's something I don't get right away… The above link is for an AES implementation which is a symmetric crypto cipher (so the same key is used for en/decryption). In your post above you claim that the API "provides public/private key auth". What am I missing…?
Complete fail on my behalf sorry, I'll try and find a asymmetric encryption addon/API. This: http://pastebin.com/8T1Vh18R appears to have support for asymmetrical encryption. (my bad, apart from the version checks and stuff it seems completely incomplete).

The main issue with the use of computer IDs as authentication is that you're trying to build a watertight wrapper, as opposed to a waterproof package. If you build a waterproof package (so to speak) then you can transport information with as much negligence as you want (even letting it fly through enemy systems) and it will remain safe and secure. More importantly, if you're using Computer IDs you can't get the message over long distances (admittedly, a node based send only "secure" system was something I have been thinking of).

Also, I'm not really understanding the documentation right now but I believe that the Rednet API uses port numbers for send function. This would mean that an attacker can simply listen in on "private" communications using the send() function by listening to the correct port number.
Bomb Bloke #9
Posted 31 May 2013 - 07:47 AM
Also, I'm not really understanding the documentation right now but I believe that the Rednet API uses port numbers for send function. This would mean that an attacker can simply listen in on "private" communications using the send() function by listening to the correct port number.
The modem API uses channels (or port numbers) for its transmissions. It's rather like a radio-frequency based transmission system - anything that "tunes in" can send/receive to anything else that's on that channel, but has to put up with the "noise" from anything else on that channel…

The Rednet API doesn't have any concept of port numbers that I can see, but does have an "open port" detection system in rednet.send that could be misleading you - the documentation is rather ambiguous as to what it actually does, but if I'm reading it correctly, it'll block the program and auto-resend until the receiving computer is actually trying to receive a message before halting transmission (rather then "just sending it", and potentially having the message lost because the receiver was doing something else at the time). I'd have to test it to be sure.
bbqroast #10
Posted 31 May 2013 - 05:22 PM
Also, I'm not really understanding the documentation right now but I believe that the Rednet API uses port numbers for send function. This would mean that an attacker can simply listen in on "private" communications using the send() function by listening to the correct port number.
The modem API uses channels (or port numbers) for its transmissions. It's rather like a radio-frequency based transmission system - anything that "tunes in" can send/receive to anything else that's on that channel, but has to put up with the "noise" from anything else on that channel…

The Rednet API doesn't have any concept of port numbers that I can see, but does have an "open port" detection system in rednet.send that could be misleading you - the documentation is rather ambiguous as to what it actually does, but if I'm reading it correctly, it'll block the program and auto-resend until the receiving computer is actually trying to receive a message before halting transmission (rather then "just sending it", and potentially having the message lost because the receiver was doing something else at the time). I'd have to test it to be sure.
I've used Rednet.send a few updates ago, and that basically sends the message once, but only the specified computer can receive it.

The issue is that I think Rednet.send uses port numbers to achieve the computer to computer comms, but now the modem API is open someone can listen into rednet.send.
Bomb Bloke #11
Posted 31 May 2013 - 07:34 PM
Testing it out, I see you're right: The modem API breaks any security the rednet API had to offer. Knowing that a server on my network had an ID of 13 and my turtle was going to be "rednet.send"ing to it, I had a third machine "modem.open(13)" and waited for it to pull a "modem_message" event. Sure enough, it got the message the turtle sent to the server, and was also able to record the ID of the sending machine as the "replyChannel".

Knowing this, the modem API also makes it fairly clear that it can be used to (very easily) spoof sender IDs when having it transmit information back to computers that're using "rednet.receive".

Well, back to the drawing board!