Suppose a desktop client communicates with an internet server program via HTTP requests.

I have a symmetric secret key shared between them used for encrypting/securing communication between them.

I also mention that communication is almost one-way i.e almost always it is the client that sends some data to the server and server returns no data to the client except reporting unexpected errors like decryption failures. In my program the responses of the server aren't even (still) encrypted (although i can implement it relatively easily if really necessary - tell me the reason to do so) because the client makes no important action/decision upon receiving thease error responses (any response other than empty string is regarded as an error and is just ignored (at most printed/logged)).

My app is not very serious/security critical. It is just a little private program (and somewhat experimental/educational and I don't want to go further from a point in its security because I don't have enough reason/priority/time for implementing more details). So please don't be stringent about non-critical details. for example I know that the shared/master key shouldn't be used directly and each time a new session key should be generated somehow, but nonetheless i am using the master key directly for every encryption forever. My intended security is the bare minimum that is absolutely necessary so that ordinary hackers cannot misuse it or read my private data in transit, assuming the client and server environments are out of their reach.

So far i have implemented encryption (AES128(CBC)+HMAC-SHA256), but it seems to me that replay prevention is almost necessary too (and implementing it isn't much work and doesn't need much modifications to my existing codes). So i want to add replay prevention too, but in the most simple way possible for my app and its minimal security requirements.

I thought of a scheme like this:

  • Client stores a counter initially at 0

  • With each request this counter is incremented by one and sent along other data (counter is encrypted too or at least authenticated by MAC)

  • Obviously, server stores the last counter value(plus 1) it received and rejects every later request with a smaller counter value.

  • When client counter resets to zero again, e.g because of a reinstallation, thus it sends a request with an invalid counter to the server, server rejects and responds with an error message to the client and tells in this response the minimum counter value expected.

  • Client then sets the counter to the value reported by the server and sends the request again (Seems to me that the error response/counter value returned by the server doesn't even need to be encrypted/authenticated, because any other counter value will be rejected by the server again).

And, yes I am aware of the problem of counter variable reaching the end of its range (maximum) and reseting to 0. I will take care of it later (seems a simple problem to sovle)

Is this scheme correct in your opinion?

  • 1
    I’ll leave this question as-is due to the fact the scheme is rather minimal, but (for future questions) please be aware that questions asking if a scheme is correct etc. have a good chance to receive off-topic flags since Requests for analyzing ciphertext or reviewing full cryptographic designs are off-topic, as the results are rarely useful to anyone else and/or would be too long for this site. and your Is this scheme correct in your opinion? is asking for a review of a cryptographic design. (I’m merely mentioning this so you don’t stumble into that pitfall somewhere in the future.) – e-sushi Oct 5 '16 at 15:29
  • 1
    'counter is encrypted too or at least authenticated by MAC'; whether or not it's encrypted, it ought to be authenticated by a MAC (or an authenticated encryption scheme); if the counter is only encrypted, there's a possibility that an attacker can change the ciphertext to make the counter sound plausible. – poncho Oct 5 '16 at 16:41
up vote 3 down vote accepted

The main part of the scheme works, but your reset mechanism in the client has a potential weakness:

  • First, the attacker can easily get the information about what is the next expected counter, by simply replaying any old message and inercepting the answer.
  • Then, at some counter $c$, the attacker intercepts the message $m$, and saves it. If your answers are just unencrypted and not signed, he can easily send your client a fake-reply.
  • All subsequent messages are also intercepted, until the client is shut down.

And now the client is restarted, and does the "ask for the correct counter" by sending a message with counter 0. The return value will be something smaller than $c$, because the server never received that value or anything higher. At this point, the attacker could switch the new data for the old data instead. That isn't a replay attack, but the client might think he send something different than what was received at the server.

More complex, the server could actually keep track of the counter, especially if it is always increased by 1. And then replace new information with old ones.


The problem with your idea is, that the counter only changes after receiving a message. But if no message is delivered, the sender might send several messages with that same expected value in the counter. And then the attacker can choose which one he wants to deliver to the server.

A common mechanism to counter replay attacks is to have a challenge-response mechanism: The client sends a hello-message to the server, the server replies with a random challenge, and then you use that number in the response.

  • Good analysis (I marked your answer as accepted), but such an active and weak (consequences) attack is not much of a concern to me. My app's functionality isn't such sensitive. I just wanted to prevent an attacker from causing to repeat the previously done actions (A task that even a passive attacker can do easily). Not anymore important, but also note that the counter is saved in permanent storage at the client side so a shutdown will not cause it to reset (only things such as re-installation can do that). – user40602 Oct 5 '16 at 20:39
  • The things that seem important enough to me (due to their extreme consequences) to prevent are for example: client sends a restart (hardware restart) command to the server. attacker eavesdrops that request and after that he can cause the server to restart any time he wants limitlessly, if there is no replay prevention mechanism in place of cource. But some active attackers intercepting requests and executing some or all of them later aren't important to me. If I wanted to prevent such things, my program would get considerably more complex and more time was needed to complete it. – user40602 Oct 5 '16 at 21:23

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.