1

If a user tries to change his/her email i would like to generate a 6 digit code to send to his email so that he can then input it in a form so that i can verify he owns that email. Because i don't want to save these 6 digits anywhere i would like to be able create this 6 digits by using 2 strings: 1)User's email (for example test123@gmail.com) 2)a password (for example d%kDh^l1285). Is there a function in php whitch takes as parameters a string (i could concatenate them) or multiple string that produces N digits?

PS: i have already limited the number of requests the user can make.

Gabor Lengyel
  • 14,129
  • 4
  • 32
  • 59
prof chaos
  • 404
  • 3
  • 18
  • Take a look here https://stackoverflow.com/questions/5464906/how-can-i-generate-a-6-digit-unique-number and here https://stackoverflow.com/questions/41972111/how-to-generate-unique-6-digit-code/41972181 – milenmk Aug 22 '21 at 08:13
  • Where is the problem storing a code to the user table? You could create a hash. Extract the first six digits of it (easy with regex) and compare against them. – Markus Zeller Aug 22 '21 at 08:36
  • Why don't you want to use an OTP (One Time Password)? – AbsoluteBeginner Aug 22 '21 at 08:55
  • I understand that it is not a big deal to save the password to the user table but the directive i have is not to store anything anywhere – prof chaos Aug 22 '21 at 09:08

1 Answers1

2

The problem with your approach is replay attacks. Let's say you can generate a code from the email address and a password. The cryptographic tool for this is a message authentication code, you could use hmac in php too, though it would not be 6 digits.

But such a code would not be a one time token, it would not even be timebound, it would be valid forever, for all future correspondence with the same email address, which is not right for this application. The correct way to use hmac for this would be to include a nonce (random value) or a timestamp together with the email address, but that would also have to be stored - and with that, you could simply just store a fully random value as well.

One thing you could actually do is apply hmac to the email address AND the datetime that email was added to your site (I guess you store that already), and only accept a code if the datetime is not too old. This would still not be a one-time token, but would at least be time limited, which mitigates some of the risk.

Also a hmac is not 6 characters, but especially if it is not a one-time token, 6 characters is not enough anyway, and/or you should have other protections in place against brute force - which again will be stateful in some way, ie. something will have to be stored.

In short, while you can get partial solutions to some of the related problems, and you might be able to mitigate many of the risks in a fully stateless solution where you don't store anything additional, it would likely be a lot simpler and more secure to just store a random code. Simplicity is really good for security.

Gabor Lengyel
  • 14,129
  • 4
  • 32
  • 59
  • 1
    I already have limited the number of requests the user can make to 6 per minute. – prof chaos Aug 22 '21 at 09:05
  • If you take the email, concatenated with the timestamp it was created, create a hmac of it with your secret, and take the first six characters of it, that might actually be secure enough for your purposes. – Gabor Lengyel Aug 22 '21 at 09:08
  • You will also want the user to enter their password along with the 6 digit code. But, you reeeeeely want to store that 6 digit code. Otherwise, find a new employer that cares about security. ;) – ptoinson Dec 12 '21 at 16:59