1

I'm looking for a standard solution to the following problem. I've been unable to find how something like this is normally accomplished. Even a key word that points me in the right direction would be helpful at this point.

Imagine two devices connected to the same WiFi network:

  • Device 1 - standard network host (smart phone, tablet, or computer)
  • Device 2 - network host that can turn on a powerful motor (or any actuation of a dangerous real-world object).

A simple protocol exists (for example, built on top of a TCP socket), in which Device 1 sends commands to Device 2:

  • Packet A: "MOTOR_ON"
  • Packet B: "MOTOR_OFF"

Imagine both devices are aware of a super secret password that can be used for signing or encryption.

How is it possible to authenticate that a "MOTOR_ON" packet received by Device 2 comes from Device 1? The point is to be 100% sure that no unauthorized device can turn on the motor.

As far as I can tell (maybe I'm wrong), any authentication scheme (even TLS?) I've found so far could be defeated if an attacker simply listens on the network, notices that some packet turns on the motor, and spoofs that packet exactly (down to the MAC address). I've considered adding a value that increments with every message to the encryption, so the spoofing the "same" message doesn't work. But that seems brittle, what happens if a packet are dropped, etc.

I feel like I'm missing something obvious here.

Thank you.

2
  • 1
    A challenge-response protocol might work for this. The attack you're worried about is called a replay attack.
    – Aman Grewal
    Jan 31 at 18:35
  • If it's better placed in security, please migrate it there! Thank you. The responses so far have been helpful.
    – safety_motorhead_19
    Jan 31 at 20:05

2 Answers 2

4

With regard to:

As far as I can tell (maybe I'm wrong), any authentication scheme (even TLS?) I've found so far could be defeated if an attacker simply listens on the network, notices that some packet turns on the motor, and spoofs that packet exactly (down to the MAC address).

This type of attack is known as a replay attack.

So, you need a protocol that enables the server (device 2) to authenticate the client (device 1), then allows the client to send a message to the server (e.g. 'motor_on', 'motor_off'), and also prevents replay attacks. If the protocol also provides secrecy and integrity (messages cannot be observed or modified by other nodes on the network), these would be nice properties to have as well.

Enter TLS. Or, more specifically, mTLS. With mTLS (mutual TLS), a secure tunnel is created between the client and the server. As part of that process, the client and the server authenticate one another, using certificates. Once the secure tunnel is established, the client can then send a command to the server (e.g. 'motor_on', 'motor_off'). TLS prevents replay attacks - if a rogue host tried to emulate a client by sending the exact same packets to the server that the actual client sent previously, it wouldn't work. TLS also provides secrecy and integrity as well.

Best of all, you don't need to re-invent the wheel. TLS is a standard, mature protocol. Libraries for implementing TLS exist for many devices and development platforms, which you can use to incorporate TLS on the client and the server in your application.

5
  • 1
    Just wanted to ask: why is mTLS necessary here? Per OP's requirement, only the server (Device 2) needs to authenticate the client (Device 1).
    – sandyp
    Feb 2 at 2:10
  • 1
    @sandyp With regular TLS, the client authenticates the server (using the server's certificate). But, the server does not authenticate the client, as needed in this case. mTLS is 'mutual TLS'. Both the client and the server have certificates; and the client and server authenticate one another using these certificates.
    – mti2935
    Feb 2 at 10:59
  • 1
    Actually, TLS with any kind of client authentication will work all right. TLS has already have anti-replay protection. If you are using HTTP over TLS to talk to your bank website (with any kind of client authentication) and issue a transfer of 1000€, TLS protects against a replay attack. The attacker cannot replay the complete TLS exhcnange because the server inludes a unique/difference nonce (server random) for each connection attempt.
    – ysdx
    Feb 4 at 23:06
  • 1
    @ysdx Yes, I completely agree with what you wrote (+1). I suggested mTLS so that client authentication can simply be handled by TLS, instead of by the application. But, either would work.
    – mti2935
    Feb 4 at 23:28
  • You just need to disable 0-RTT feature from TLS 1.3 or make sure it is correctly handled by the application layer (see rfc-editor.org/rfc/rfc8470.html): 0-RTT / early data can be replayed.
    – ysdx
    Feb 5 at 7:30
3

A simple, practical solution to the question's problem is TLS-PSK (Pre Shared Key) and some predefined ciphersuite, e.g. TLS_PSK_WITH_AES_128_CBC_SHA defined in RFC 4279. TLS-PSK has protection against replay (if the random number generator in Device 2 is not broken).

The pre-shared key should be derived from the "super secret password", preferably with a purposely slow password-based Key Derivation Function (KDF) such as Argon2 (which needs not be implemented in Device 2, if the procedure to load the key into Device 2 does the key derivation).

That purposely slow KDF step is to make brute-force password search harder. If the password has enough entropy (128-bit, that is 22 characters randomly picked among an alphabet of 57), it's not necessary to use Argon2 and we can use a fast KDF, or even SHA-256 truncated to the desired key size (128 bits at least).


Instead of a "super secret password" on both sides, it's also possible to do with a public key in Device 2 and the corresponding private key in Device 1, using TLS ciphersuites with asymetric cryptography (e.g. ECDHE-ECDSA-CHACHA20-POLY1305). The advantage is that extracting the data in Device 2 does not leak the credentials that would allow to command Device 2. The disadvantage is that there is more code and processing in Device 2, which might be an issue if it is heavily constrained by power or cost.


It's also possible to do without TLS, and implement a challenge/response protocol with a Message Authentication Code over the bare link (TCP will do):

  1. Device 2 generates a fixed-size nonce. That can be a large enough (e.g. 160-bit) random number generated by a random number generator that's not broken (which is much harder than it seems), or a robust counter (e.g. 80-bit) that never wraparounds and can't be reset by adversaries (e.g. by cutting power when the counter is updated in permanent memory, a classic attack). It's possible to combine the two techniques for a more robust nonce.
  2. Device 1 receives nonce
  3. Device 1 forms (command, HMAC-SHA-256(pre-shared-key, salt = (command ∥ nonce)))
  4. Device 2 receives (command, authenticator) allegedly produced as above, and honors the command only if HMAC-SHA-256(pre-shared-key, salt = (command ∥ nonce)) = authenticator; and (regardless of the outcome of this test) makes sure another execution of 1 above will occur for the next command.

That later solution uses less resources in Device 2, however it does not give confidentiality (passive eavesdropping is enough to see the commands issued).

Note: the pre-shared-key can be derived as in the first solution; or it can even be the password itself if it has at least 128-bit entropy.


If there are multiple instances of Device 2, it's important that the pre-shared-key is different for each instance.

  • It prevents attacks where Device 1 is abused to command the wrong instance.
  • That's necessary against replay in a challenge/response protocol with nonce generated by a counter and if it's initialization value and width makes it possible that there is overlap of counter values across instances.
  • That removes the risk of extraction of pre-shared-key from one instance to attack the others.

The standard way to get unique pre-shared-key is entering a unique ID in the input of the KDF that generates an instance's pre-shared-key (on top of the "super secret password"). Device 1 can keep a single "super secret password" and generate pre-shared-key for the approriate instance, knowing it's ID, by running the KDF. That is sometime called key diversification.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .