0

I am trying to encrypt a random token to be stored in the user table when a user uses the forgot password field by entering their username. It will also send out an e-mail with a url to the change user password page. This url will have a query string param called 'key'.

i.e. www.mysite.com/Changepassword?key=xfsdfsdffsdfiughjksdf.

Once the user clicks the link and they are on this page. I have a function that will get a user by ResetToken. If it finds a user then proceed.

I need advice on a few things:

  1. What kind of random token/encryption technique should I use to ensure that no one can go to the Changepassword page and guess a key and be able to change a users password.
  2. How will I handle making this key url friendly?
John Alexiou
  • 28,472
  • 11
  • 77
  • 133
JTunney
  • 914
  • 1
  • 15
  • 46

1 Answers1

1

If you want to be super-secure, using the cryptographically secure random number generator would work. And converting to hex is the easiest way to ensure it's URL-safe:

byte[] bytes = new byte[8];
using (var rng = RandomNumberGenerator.Create())
{
    rng.GetBytes(bytes);
}
string key = string.Join("", bytes.Select(b => b.ToString("X2")));

EDIT Keep in mind that e-mail is potentially insecure, so it's possible (however unlikely) that your message can be intercepted by a malicious third-party before reaching the recipient.

Joe Enos
  • 39,478
  • 11
  • 80
  • 136
  • Awesome!! So will I be able to take this key and store it as a char field in my user table and also send out an email with the key in a url? Will it be url friendly? – JTunney Sep 27 '14 at 16:21
  • The key will be hex characters (2 characters per byte), so if you're doing 8 bytes, you'll have 16 characters. The characters will only be 0123456789ABCDEF, so they'll be URL-safe. If you want to save a little space in your database, you could save the bytes directly as binary(8) in the database, but it's probably just easier to store it as char(16), just so you don't have to think about converting between binary and text again. – Joe Enos Sep 27 '14 at 16:22
  • Sorry to bug you again, but I am trying to store the returned key string into a varbinary(8) field in my db. Entity Framework is telling me that it wants a byte[] array. So I tried User.ResetKey = Encoding.UTF8.GetBytes(key) shouldn't this work? It is erroring on save. – JTunney Sep 27 '14 at 17:16
  • In the code example I have, `bytes` is a byte array, and can be saved to the database as binary(8). `key` is a string that represents the hex codes for 8 bytes, but `key` itself is 16 characters. `Encoding.UTF8.GetBytes(key)` takes the string and converts to bytes, which will give you 16 bytes representing those 16 characters. If you only have the hex string, and want to get the bytes, you'd have to use something like the answer to [this question](http://stackoverflow.com/questions/311165/how-do-you-convert-byte-array-to-hexadecimal-string-and-vice-versa). – Joe Enos Sep 28 '14 at 00:15
  • you should also make sure the token can only be used once and it expires after a reasonable amount of time. – Thomas Waldmann Nov 20 '14 at 01:43