问题
I am generating a nonce to validate the wizard steps to secure it one after another.
I know how to create the nonce in nodejs and store the same in database to make sure it can be used once.
But I was wondering, whether there is an idea to generate and validate a nonce as above like to be used only once and if possible, can be used within a time limit (expiry) without storing the same in the database but simply returning it to the client in one wizard step and validate the same on the next step.
I normally use the below method to generate the nonce, normalize it and store it in a mongodb with a time to expire so that mongodb will delete it after a particular time if its not been used.
var crypto = require('crypto');
crypto.randomBytes(32, function (err, bytes) {
if (err) {
next(err);
} else {
next(null, normalize(bytes));
}
});
Please suggest if any good/optimized way of generating the nonce than this and a possibility to take care of the one time usage and expiry without a database call.
回答1:
It's always better practise to have a database to store and validate the nonce
. To restrict with time, either you can use a mongodb with expiry or you can generate the timestamp, then generate a hmac
with timestamp, nonce & private key. Then send the nonce, timestamp & hmac to the client. This way you can secure the timestamp as well you can restrict the nonce with particular time if your database is not supporting the document expiry as mongodb. Hope it explains.
回答2:
It is possible to have a time expired nonce without a database call, using something like a hash map on the server to store and retrieve the nonce and check the time. If there is a session id or static user id, that would help. However, this idea of having the server generate, hold, fetch, and maintain a nonce seems difficult in comparison to a tested solution such as MongoDB. There is another wrinkle that would happen in the case of multiple servers for a service, where traffic would have to be kept consistent for sessions start to finish. Using a database for a single source of truth on nonces fixes that.
If the reason for keeping the nonce on the node server is for speed / lag, it could be worth the extra testing and code. In that case the timeout for the nonces would need to be scanned with regularity for expired ones, to maintain fast searching.
回答3:
You don't need databases.
If you use a cryptographic random number with 128 bits, you have 2^(128)
possibilities of numbers. Considering an even, equally distributed random number generator, and that you call such function once per second, the probability of repetition would be almost zero.
You may use something like this in node (conversion here to base64
)
const crypto = require('crypto');
var nonce = crypto.randomBytes(16).toString('base64');
128 bits are 16 bytes.
Mathematical demonstration
The probability mass function of the binomial distribution, which is the one applicable, is
This functions returns the probability of getting exactly k successes within n trials, with p being the probability of success for each trial.
In our case p=1/(2^128)
.
The cumulative function is
where k
on the sum is the "floor" under k, i.e. the greatest integer less than or equal to k. This cumulative function gives, the probability of having the number of successes between 0 and k.
But we need the probability of at least one successful trial, since we don't want to have repetitions. And considering that
thus
which means for k=1
that
in our case, if we call our nonce once per second during 100 years, we get n=1*60*60*24*365.25*100=3155760000
Therefore
p=1/(2^128);
n=3155760000;
Applying the formula
Conclusion
If you use 128 bits nonce and you call the nonce once per second during 100 years, the probability of repeating said nonce during that period of 100 years is almost zero, which means almost impossible. That means that you don't need databases.
来源:https://stackoverflow.com/questions/40068193/how-to-use-a-generated-nonce-in-nodejs-and-do-validation-without-a-database-call