7

I am making an arduino project to open my garage door. I want to make it so users with the passphrase can open the door. Due to computational restrictions it is unlikely encryption is possible. Under the assumption that only hashing algorithms are available, what is a secure way of protecting the door? My thoughts:

Client sends request to open door. Server increments counter.
Server responds with current counter value, timestamp and date, with hmac of the above. Client responds with H(passphrase + counter) + above server response. Server verifies hmac of server response, timestamp is within valid window, and sent hash matches known secret appended with counter.

Have I thought this one through properly or am I missing something?

Ryan
  • 173
  • 5

3 Answers3

7

What you're suggesting is likely good enough, and very likely far more secure than just about any other lock on your house.

If the only hash function you can find is MD5, go with it, but make sure to HMAC with the passphrase as the key. Again, it's not going to be the weak point of your security. I'm sure I could pick the lock on your front door faster than I could break an MD5 HMAC. Obviously, HMAC-SHA1 would be better, or SHA-256, even. See if you can find a SHA-1 for Arduino.

I don't understand the exact protocol you're proposing. Why the timestamp and a counter? Either alone would work fine, assuming you take more than one second to do the protocol. It doesn't hurt to do both, but let's break it down:

  1. Client sends a request to open.

  2. Server sends a unique string to the client.

  3. Client computes HMAC(passphrase, unique-string) and sends the HMAC back to the server.

  4. Server also computes the HMAC and compares them. If they match, the door opens.

That seems good enough to me, the only thing we're debating is the content of the unique string. A timestamp alone would work if you prevent replays. You could do that by having the Arduino spin until the clock ticks. But there's also nothing wrong with an equivalent of:

static int counter = 0;

...

sprintf(challenge, "%d-%d", time(0), counter++);
send(challenge);

and that would be unique enough.

The risk in this basic protocol would be someone pre-computing an appropriate HMAC. Strictly speaking, the timestamp and the counter helps thwart this, but in practical terms it isn't really going to help. If someone intercepts any given successful challenge and response, they can run a dictionary search on passphrases to find the right HMAC.

But still, it's almost certainly more secure than the locks on the other doors.

Jon

Jon Callas
  • 2,371
  • 15
  • 15
4

Some points:

  • Make sure you authenticate everything you send, not only parts of it. So, append a HMAC(password, everything) to the end of each message (which means both messages, not only the ones sent by the clients). If you do this, the message itself doesn't need to contain the password or any hash of it, though it should contain counter and/or timestamp, and be different for client and server.

  • Don't use MD5. While it is quite fast to compute, it has now a reputation as "broken" (because of quite fast collision attacks). While there is not yet a break which makes HMAC-MD5 attackable, better be save and use a better hash function, like one from the SHA-2 family (SHA-265 should be enough).

  • As said by Ilmari in a comment, a secure block cipher would not necessarily be harder to implement (or take more resources) than a secure hash function. Actually, many hash functions use some kind of block cipher internally in the compression function. You can construct a MAC from a block cipher (for example CMAC), too.

Paŭlo Ebermann
  • 22,946
  • 7
  • 82
  • 119
2

@Ryan You don't need a timestamp to avoid a replay attack. There's a message on the handshake that is generated by the server, so it can be anything random enough. A 32-byte random string is random enough to make a bruteforce unlikely, as the server Arduino have very low computing power to make it viable.

A timestamp is something very predictable, and if an attacker suspects that a timestamp is part of the challenge-response protocol, it would be easier to guess the other parts of the message. A random value don't have this weakness.

So, I think this protocol would suffice:

  1. Client asks for opening
  2. Server sends random string RS1
  3. Client sends HMAC(RS1 + PASSWORD)
  4. Server calculates HMAC(RS1 + PASSWORD) and compares with result

But as Jon said, is way easier to break a lock than to break a hash.

ThoriumBR
  • 130
  • 4