There are few ways that how you can achieve this. I hope your objective is accept requests only from known clients?
A PSK in its simplest form is a key that is exchanged between two parties out-of-band with the sender using the shared key as is in the messages as the credential. For this reason, HTTPS generally is a must for PSKs. Without help
from transport security, it is easier for a malicious user to get the PSK and use it in a malicious request, just like a legitimate request.
Time Stamp to prevent replay attacks
Suppose we design our security mechanism to transmit the credentials not in plain text but encrypted using the PSK.
The encrypted credential is sent in the message, typically in the HTTP request header. A malicious user cannot decrypt
the header and extract the credentials but can replay the earlier request as is. Worse, a malicious user can frame a new
request and use only the header value containing the valid credentials from the previous successful request.
A timestamp can be added to the message and encrypted along with the rest of the message content. The service can
retrieve the timestamp after decrypting the message and fail the request if the timestamp is too old for the threshold
that is already agreed on. This cuts down on the window of opportunity to replay a request.
Downside is , both server and client need to in sync with time.
An alternative to a timestamp is a counter such as the nonce counter that we saw with digest authentication. With
a counter, we don’t need to be concerned about the skew between the clocks. However, clients must implement a
counter to ensure the count sent in a request is greater than the count in the previous request at least by one, and the
server must keep a record of the last received counter. Of course, the message has to be signed so that a malicious user
does not increment the counter and replay the rest of the request.
Prevent Identifier Misuse
In its simplest form, a PSK is both the user identifier and the credential. For this reason, PSKs must be unique. Given a
key, an application must be able to identify the corresponding user without any ambiguity. The basic premise that we
are working on is the avoidance of HTTPS. For this reason, the PSK cannot be transmitted as is.We need to have two keys: one acting as the identity of the user and the other acting as the credential.
However, these keys are not mathematically linked. Also, the same key used to sign on the sender’s end is used to
validate the signature on the receiver’s end; hence, this is just a symmetric shared key. But similar to public key
cryptography, only the private key must be guarded.
Prevent MIM attacks (for non HTTPS communication)
With no HTTPS, a man-in-the-middle (MITM) attack is one of the most significant threats. The primary mechanism
to ensure data integrity of messages is a Hash-Based Message Authentication Code (HMAC). HMAC is just a piece
of data created through a cryptographic hashing algorithm and a shared secret key. In this section, I show you how
to create an HMAC using the SHA256 algorithm.
However, if the message needs to be encrypted for confidentiality, you can easily add that functionality
using the same private key we use for HMAC or you can introduce a new key specifically for encryption.
The Request should contain following params
- The public key, which is the key associated with the user.
- The counter
- The timestamp
In addition to the parameters, the request includes a signature that ensures that none of the parameters are
tampered with. It is possible to create the signature based not only on the three parameters but also on the entire body
of the request if the objective is to make sure nothing in the request gets modified.
To make sure no one tampers with the parameters, we can include an HMAC-SHA256 of all three values plus the
request URI and HTTP method. Listing 9-1 shows an HTTP request secured by the PSK mechanism. Figure 9-2 shows
the PSK design.