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?