9

If you need to generate a string / token to authenticate future requests (e.g. an API key, an email confirmation URL, etc.), what factors should be considered?

In particular

  • What makes the string "secure" / "very hard to guess"?
  • How is the "security amount" measured / estimated?
  • What are the main standards out there?

A practical example

Let's take these two output strings from NodeJS.

String 1 (through Node crypto)

var crypto = require('crypto');
crypto.randomBytes(48, function (ex, buf) {
  console.log(buf.toString('hex'));
});

String 2 (through Node UUID)

var uuid = require('node-uuid');
console.log(uuid.v4());

Based on the concepts outlined above, which one would be more secure and why?

Also, please feel free to suggest any good introductory material on the topic, as I couldn't easily find articles about this online.

Artjom B.
  • 61,146
  • 24
  • 125
  • 222
Pensierinmusica
  • 6,404
  • 9
  • 40
  • 58
  • I hardly think there's a difference with regards to your particulars and purpose of use. – marekful Aug 12 '15 at 13:20
  • @marekful, thanks! Where I'm trying to get here though is: how can one understand the difference? – Pensierinmusica Aug 12 '15 at 13:22
  • 1
    Check this page on [crypto-strength randomness](http://www.cs.berkeley.edu/~daw/rnd/). – Maciej Lach Aug 12 '15 at 13:26
  • Take a look at this [gist](https://gist.github.com/joepie91/7105003c3b26e65efcea63f3db82dfba) It suggest to use uuid, but not the node-uuid. For token generation you can then use a hash function on this uuid v4 string – Hibbem Feb 20 '19 at 13:12

1 Answers1

7

What makes the string "secure" / "very hard to guess"?

A string or token cannot be cryptographically secure, because it is static.

The notion of a cryptographically secure (pseudo) random number generator (CS(P)RNG) describes that the produced numbers are not predictable. It's a property of the procedure and not of the individual numbers.

How is the "security amount" measured / estimated?

That depends on the randomness sources that are used, because some of them are a black box. You can generate a lot of randomness and see if you find some patterns in there. There are some test suites available, but then you have to think about your application and how fast you need those random numbers. It is possible that requesting a lot of randomness depletes the pool and then produces insufficiently random numbers.

What are the main standards out there?

Use your system's/framework's designated cryptographically secure randomness sources. Node.js' crypto.randomBytes() is one of those if you want to trust the documentation.

A practical example

node-uuid uses crypto.randomBytes() internally, so there is essentially the same randomness strength behind it, but it will fallback to Math.random() if crypto.randomBytes() is not available. Math.random() is not cryptographically secure. If you want to have a cryptographically secure random values in the browser, you will need to query Web Crypto API's getRandomValues().

Community
  • 1
  • 1
Artjom B.
  • 61,146
  • 24
  • 125
  • 222
  • Unfortunately, node-uuid will [silently fallback to an insecure PRNG](https://github.com/broofa/node-uuid/blob/4ff82d52f9c9026fbacfb31eebb92c37efc460b2/uuid.js#L38-L52). – Scott Arciszewski Aug 12 '15 at 13:37
  • Yes, it will fall back to insecure PRNG, but only for browser environments or really old node.js versions. – Artjom B. Aug 12 '15 at 13:41
  • I would, personally, prefer it to error out saying "this cannot be safely used on an insecure platform, please update your software". – Scott Arciszewski Aug 12 '15 at 13:43
  • @ScottArciszewski: But uuid's purpose is *not* security, but uniqueness which is different. You should not use a UUID when you want a secure token. – Neil Slater Aug 12 '15 at 14:06
  • I'd argue: If you want uniqueness, you want a CSPRNG :P -- but yes, UUIDs would make for a terrible security token design. – Scott Arciszewski Aug 12 '15 at 15:28
  • @ScottArciszewski, apart from the fallback to insecure PRNG on some JS engines (browser environments or old node.js versions), why does `node-uuid` make for a terrible security token design? – Pensierinmusica Aug 20 '15 at 16:55
  • @NeilSlater, apart from the fallback to insecure PRNG on some JS engines (browser environments or old node.js versions), is there any other reason why one shouldn't use `node-uuid` to generate secure tokens? – Pensierinmusica Aug 20 '15 at 16:59
  • 1
    @Pensierinmusica: No, that's the main reason. You are vulnerable to, and must always check the implementation. The authors of any implementation of UUID v4 are under no obligation to use a secure RNG, and they may change implementations to be less secure in future, even if they are secure today. It just so happens that secure RNGs and uniqueness concerns of uuid usually overlap. Don't rely on it - it would be your fault and problem if the authors used a less secure RNG after you started to use uuid for secure token. Use a library intended for security, if security is your main concern. – Neil Slater Aug 20 '15 at 17:26
  • @NeilSlater, I see, thanks for the clarification! Btw – within the NodeJS ecosystem – would then `crypto.randomBytes` be the first candidate to generate secure random tokens, or do you have other options in mind that would fit better? – Pensierinmusica Aug 21 '15 at 00:22
  • @Pensierinmusica: Yes. I think take a look at this question: http://stackoverflow.com/questions/8855687/secure-random-token-in-node-js – Neil Slater Aug 21 '15 at 06:29
  • 1
    Take a look at this [gist](https://gist.github.com/joepie91/7105003c3b26e65efcea63f3db82dfba) It suggest to use uuid, but not the node-uuid. For token generation you can then use a hash function on this uuid v4 string – Hibbem Feb 20 '19 at 13:09
  • @Reyske No idea what the author of that gist is trying say without an example. The uuid package has the [same issue](https://github.com/kelektiv/node-uuid/blob/v3.3.2/lib/rng-browser.js#L28) as node-uuid that I identified in my answer. – Artjom B. Feb 21 '19 at 19:13