0

I'm having some difficulties doing this the right way (as much as it can go).
Some time ago, I've asked a question here, asking for help on how to implement sending an access link through email.

First of, I know this is terribly insecure from the beginning, but we have our reasons so let's leave that aside.

The Idea

The idea basically is sending an email with a long-living link that gives access to a very specific area of our app.
Example link: ourwebsite.com/users/ACCESS-KEY

The Attack I Want To Avoid

A user guessing another access key using his own.

What I Was Suggested

In my former question, I was suggested using a random string as the access key which'll be saved in my database.
I've been doing a bit of research, and I'm worried my PRNG won't be random enough, especially since I'm generating a bunch of access keys at a time.
I've been traumatized by C# lessons in school where my "random" function would change output every 1000 or so iterations.

I'm thinking about using Random.org to have a truly random seed, but that seems a bit of an overkill.

My Thoughts

I have 4 options which I want to check with you guys before I succumb to Random.org -

  1. Just using the PRNG, checking beforehand how it behaves (Node.js's PRNG), maybe implementing a sleep(500) between generations. If the result are similar but not identical, hash it with SHA-2.
  2. Taking the user ID and hashing it thoroughly with PBKDF2 (does it matter?), save it in DB and just send that.
  3. Using an implemented PRNG such as Mersenee Twister, as suggested in this stackoverflow question.
  4. Other stuff which I know nothing about such as a cipher which only I know how to decrypt, or JWTs like I'm using for my regular users.

What do you think?
Thanks for any assist! I appreciate taking the time to read this.

3
  • 1
    It's very important to use the function the right way, like your C# example. If you generate a new Random()-class everytime, you might get the same Value for a couple of times. If you use the same class for each number, you'll always get a new random number. Therefore it si really important to read the documentation carefully!
    – Tokk
    Commented Jan 22, 2016 at 13:56
  • 1
    What's wrong with just using a Node.js secure random number generator? That seems much simpler to me. Commented Jan 22, 2016 at 18:30
  • I don't honestly know. Is there something wrong with it? I need to make sure that: 1. Generated strings will not collide, 2. Generated strings will not resemble each other.
    – Neta
    Commented Jan 22, 2016 at 18:38

3 Answers 3

1

ok you just need to hash user specific data (but nothing critical) and combine the user data with unique hard to guess numbers such as a couple of random ints and the date of creation (down to the second if you can)

... hash this altogether and you have a very hard to guess string. the date wont be the same unless everyone creates it within the same second. making this more complex. oh and dont forget to use your own salt also.

well using a random number generator for something like this is not a good idea (unless combining, but you dont want too large of a random number when hashing), while the odds are very very very low, it is possible to generate the same key for another user, using my suggestions you remove that chance.

using a salt of your own making gives it that personal password feel that no one on the outside world should find out, if they find it out you have more things to worry about.

the random ints gives it that small bit of random to stop educated guesses.

the user data makes the string unique and the date adds an extra layer so someone cannot guess someone elses string without knowing the date of creation. keeping your algorithm and the order in which you piece it together is just as important.

your points:

Just using the PRNG, checking beforehand how it behaves (Node.js's PRNG), maybe implementing a sleep(500) between generations. If the result are similar but not identical, hash it with SHA-2. -- I have already mentioned this its not needed but down to choice really.

Taking the user ID and hashing it thoroughly with PBKDF2 (does it matter?) -- yes and no, the hashing function does not matter (just not md5) as long as your hashing is a hash and not an encryption (if you can decrypt the string its an encryption, DO NOT DO THIS THIS IS DANGEROUS)

Other stuff which I know nothing about such as a cipher which only I know how to decrypt, or JWTs like I'm using for my regular users -- dont decrypt

3
  • Thanks! That's a good idea. I'll be honest with you though, security in this area isn't so critical. The main purpose I had writing this question is learning a bit more about cryptography and information security. If you want to take a crack at the suggestions I made and explain a bit of the advantages/disadvantages, that'll be awesome and teach me a lot. Thanks again for reading!
    – Neta
    Commented Jan 22, 2016 at 13:03
  • Thanks for updating your answer. So to conclude, I'll hash together the user's ID, the moment of creation, a random salt which I'll save with the user and a secret random string I'll save in my config file.
    – Neta
    Commented Jan 22, 2016 at 16:20
  • yup! sounds good, dont forget a few randomly generated numbers thrown in!
    – TheHidden
    Commented Jan 22, 2016 at 17:19
3

All you'll need in this case is GUID's for the key. Most implementations are random, and they're always going to be unique.

Of course you could AES encrypt it, but that doesn't really add any additional security over and above using standard GUID's.

1
  • This is definitely the way to go. Works out of the box with (typically) a one liner of code. MS implementation uses 60 bits (of 128) for the timestamp.
    – TTT
    Commented Jan 22, 2016 at 18:57
2

Use a cryptographically secure pseudo random number generator (CSPRNG).

Do not use classes such as math.random or similar, as they are usually seeded with the number of seconds since midnight and are often not considered to be unpredictable enough if seeded with something else.

Examples in different languages are:

  • C# - RNGCryptoServiceProvider
  • Client-side JavaScript - Window.crypto
  • NodeJS - secure-random
  • Linux - /dev/urandom
3
  • I'm already using SHA-256 with a 64 bit secret, a 128 bit salt, the time and date down to milliseconds and the user's ID. Should I switch to CSPRNG?
    – Neta
    Commented Jan 25, 2016 at 13:04
  • I'd use a CSPRNG for the salt, certainly. Commented Jan 25, 2016 at 14:14
  • Done, I'll update the algorithm today. Thanks a lot!
    – Neta
    Commented Jan 25, 2016 at 14:15

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .