Anti-replay attack based on timestamp and nonce

Previously, timestamps were always used to prevent replay attacks, but this does not guarantee that each request is a one-time. Today I saw an article introduced by nonce (Number used once) to ensure that one is effective, I feel that the combination of the two can achieve a very good effect.


First of all, we must clarify one thing. The replay attack is a secondary request. The hacker obtains the requested HTTP message by capturing the packet, and then the hacker writes a similar HTTP request and sends it to the server. That is to say, the server processes two requests, first processes the normal HTTP request, and then processes the falsified HTTP request sent by the hacker.

Timestamp based solution

For each HTTP request, you need to add the timestamp parameter, and then digitally sign the timestamp along with other parameters. Because a normal HTTP request, the arrival of the server from the outgoing will generally not exceed 60s, so after the server receives the HTTP request, first determine whether the timestamp parameter is compared with the current time, whether it exceeds 60s, if it is exceeded, it is considered illegal. request.




/ / The server can read the token from the database through uid

Under normal circumstances, the hacker takes up more than 60s from the packet replay request, so the stime parameter in the request has expired. If the hacker modifies the stime parameter to the current timestamp, the digital signature corresponding to the sign parameter will be invalidated because the hacker does not know the token value and there is no way to generate a new digital signature.

However, the vulnerability in this way is also obvious. If the replay attack is performed after 60s, there is no way, so this method cannot guarantee that the request is valid only once.

Nonce based solution

Nonce means only one valid random string, which requires different parameters for each request, so this parameter is generally related to the timestamp. For convenience, we use the hexadecimal timestamp of the timestamp for actual use. You can add the client's ip address, mac address and other information to do a hash, as a nonce parameter. We store the nonce parameters for each request in a "collection" that can be stored in the database or cache in json format. Each time an HTTP request is processed, it is first determined whether the nonce parameter of the request is in the "set", and if it exists, it is considered an illegal request.

among them:




/ / The server can read the token from the database through uid

The nonce parameter is already stored in the "collection" on the server when it is first requested, and the resending request is recognized and rejected. The nonce parameter can't be tampered with as part of the digital signature, because the hacker doesn't know the token, so it can't generate a new sign.

There is also a big problem in this way, that is, the "collection" of storing nonce parameters will become larger and larger, and it will take longer and longer to verify whether the nonce exists in the "collection". We can't make the nonce "collection" infinite, so we need to clean up the "collection" regularly, but once the "collection" is cleaned up, we can't verify the cleaned nonce parameter. That is to say, if the "collection" is cleaned once every day, the url we grabbed, although the replay attack could not be performed at that time, we can still perform a replay attack every other day. And within 24 hours of storage, all the requested "nonce" parameters are also a small overhead.

Based on timestamp and nonce scheme

So if we use the timestamp and nonce parameters at the same time? Nonce can solve the problem of timestamp parameter 60s in one time, and timestamp can solve the problem that the "collection" of nonce parameters is getting bigger and bigger.

We add the nonce parameter based on the timestamp scheme, because the timstamp parameter considers an illegal request for requests over 60s, so we only need to store the "set" of the nons parameter of 60s.

among them:




/ / The server can read the token from the database through uid

If the HTTP request is replayed within 60 s, since the nonce parameter has been recorded in the server's nonce parameter "set" at the time of the first request, it is judged to be an illegal request. After more than 60s, the stime parameter will be invalid. At this time, because the hacker does not know the value of the token, the signature cannot be regenerated.

In summary, we believe that a normal HTTP request will not be sent more than 60s. The replay attack within 60s can be guaranteed by the nonce parameter. The replay attack of more than 60s can be guaranteed by the stime parameter.

Because the nonce parameter only works within 60s, you only need to save the nonce parameter within 60s.

We don't have to clean up the set of nonce parameters every 60s. We only need to judge the last modification time of the nonce set when the new nonce arrives. If it exceeds 60s, we will clear the set and store the new nonce parameter set. In fact, the collection of nonce parameters can be stored for a longer time, but at least 60s.

Verification process:






















/ / Determine whether the stime parameter is valid

if$now $stime > 60){

die("Request timed out");


/ / Determine whether the nonce parameter already exists in the "collection"

if( in_array($nonce,$nonceArray) ){

die("Request is only valid once");


/ / Verify the digital signature

if $sign != md5($uid.$token.$stime.$nonce) ){

die("Digital signature verification failed");


/ / Determine whether you need to clean up the nonce collection

if$now $nonceArray->lastModifyTime > 60 ){

$nonceArray = null;


/ / Record the nonce parameter of this request


/ / Start processing legitimate requests