The Arduino is a wonderful little device. It’s versitile, inexpensive, and surrounded by a large community. These qualities have led to a wide variety of add-ons, like the Ethernet shield which provides the Arduino with network capabilities.
I’m currently working on an Arduino device for managing access to a beer keg, called PourLogic, inspired by the Kegbot project. This Arduino-based device acts as a web client (like your web browser) that makes requests to a remote web server.
For instance, when a patron swipes his/her RFID tag, the Arduino asks the server whether the owner of the RFID tag can have some beer. The web server decides and replies with the amount the person can pour, from zero (he/she cannot pour) to infinity (he/she can have as much as he/she wants). Once the person finishes pouring, the amount of beer he/she has poured is sent to the web server to be recorded.
Communication between the Arduino and the web server is essential for this system to operate effectively. When the Arduino asks the server if a patron can have some beer, the Arduino is trusting that the end-point it is connecting to is trust-worthy. However, imagine if somebody posed as the server (i.e. tricked the Arduino into connecting to it, instead of our nice little server) and this fake server responded to every reply with “Yes, you can drink as much as you want.” In such a case, any RFID would allow the beer to be poured, bypassing all effort to prevent this. To avoid this kind of scenario, the Arduino must be able to authenticate responses from the server.
After a patron has finished pouring, the volume poured is sent back to the server for some (lovely) record-keeping. Now, not just anybody should be able to post this type of data to the web server. If this was a regular website, like publishing to an essay to a blog, or posting a tweet to a Twitter account, this type of request would necessarily require the user to authenticate his/herself (i.e. enter a username and password). Thus, the server needs to authenticate all requests from its clients.
Imagine now that the previous two problems are solved. If a third party were to, again, trick the Arduino into connecting to it instead of the real server, it may be able to simply play as proxy to the valid communication between the Arduino and the real server. Any valid request would be sent to the fake server, the fake server would forward the request to the real server, get the real response and forward the real response back to the Arduino. In this process the fake server can view and remember the valid exchanges between the Arduino and the server. Two problems need to be avoided here. First, the third party should not be able to alter any request data and have the message still be valid. Second, if the prior problem is solved, the third party should not be able to recall a previous valid message and use it at a later time. This second issue can become a problem when a valid response to a pour request, which cannot be altered, is “Yes, you can have as much as you want and this is really the server talking here.” The fake server can reply with such a message at any time once observed.
In the typical situation (webmail, etc.), these four issues would be remedied with the use of SSL/TLS, the de-facto standard for providing both authentication and encryption between two end-points over TCP. The Arduino, being a cute little thing, is not very powerful. As a consequence, the use of SSL/TLS with the Arduino is not feasible.
How can the two end-points authenticate without public key cryptography and all the fun stuff that requires more computing power than the Arduino provides?
[TO BE CONTINUED]