15

I'm planning on storing the passwords as a sha1, so I need a way to validate that it is a sha1 at another point in my website. I was planning on using preg_match, but I do not know how to make regex patterns. Could someone help me out with one?

Thanks

Edit: I am not trying to see if two hashes match.

Leagsaidh Gordon
  • 1,641
  • 5
  • 19
  • 28
  • 1
    Most people store the sha1 hash and then when you need to check a password if it's the same, get the sha1 of the new password and compare it to the stored one, they should be the same. I assumed this is what you are trying to achieve. – animuson Jun 05 '10 at 20:54
  • If you really want to 'match' sha1 hashes, see here: http://stackoverflow.com/questions/468370/a-regex-to-match-a-sha1 – miku Jun 05 '10 at 20:57
  • About all you can do is verify a few really basic points, such as containing 160 bits of information in the format you prefer (e.g., hexadecimal digits). The content is a whole different story -- you'd hope that every possible output can be generated (and, I believe that is the case), which means any value could be valid. – Jerry Coffin Jun 05 '10 at 20:59

3 Answers3

51

Actually, you can use preg_match() to make sure it's a 40 characters hexadecimal string as such:

function is_sha1($str) {
    return (bool) preg_match('/^[0-9a-f]{40}$/i', $str);
}

To explain the pattern:

/        Opening Delimiter
^        Start Of String Anchor
[0-9a-f] Any of the following characters: 0123456789abcdef
{40}     Repeated 40 times
$        End Of String Anchor
/        Closing Delimiter
i        Modifier: Case-Insensitive Search


If you are trying to make sure that the sha1() hash matches the password the user provider, you simply rehash like this:

if($db_hash == sha1($user_provided_pass))
   echo "Password is correct!";
Andrew Moore
  • 93,497
  • 30
  • 163
  • 175
  • 2
    Thank you. You not only gave me the pattern that I needed, but you also explained what each bit meant. – Leagsaidh Gordon Jun 05 '10 at 21:09
  • 7
    Or you could use [`ctype_xdigit`](http://php.net/ctype_xdigit) (to check for hexadecimal digits only) and [`strlen`](http://php.net/strlen) (to check for the string length). – salathe Jun 05 '10 at 21:23
  • No need for insensitive test. – StackSlave Aug 06 '20 at 02:18
  • Also matches all [*160](https://www.php.net/manual/en/function.hash.php#104987) algorithms, and a one in a million chance that the input matches the regular expression without actually being hashed. Use `password_hash()` for passwords, as the hashes are automatically salted. – zanderwar Jun 15 '21 at 01:05
9

ctype_xdigit is much faster. I typically use hashes for lookups and find it very useful.

Kristopher Ives
  • 5,838
  • 7
  • 42
  • 67
0

When comparing two SHA1 hashes, and you know that the first one is one (because it comes out of the database), then just assume that the second is a SHA1 value as well. You are only interested if two hashes match or not. If one of the compared values is not a possible SHA1 value, then it's particulary not the same as the one in the database. And that's all you need to know.

poke
  • 369,085
  • 72
  • 557
  • 602
  • I know this is an old post, but wanted to add my own comment to it. What if your passing a sha1 through a URL as a string think of an MVC for example or passing a password through an AJAX POST/GET you might want to convert the string to a SHA1 or MD5 or whatever prior to making the post get (or put) cause you never know when someones packet sniffing or doing something to catch posted plain text passwords – chris Oct 06 '11 at 04:59
  • (I don’t even remember this question o.O) If you hash the password *before* sending it to the server, you gain nothing. Because as soon as the server already accepts a hashed value, the *hash itself* works as the password. So someone could easily packet-sniff and get the *hash* that is sent and use it in the same way one would normally use a text password. The solution is not to encrypt (or hash) the password before sending, but rather to ensure that the communication is secured itself (e.g. via SSL). – poke Oct 06 '11 at 14:20
  • sorry to dredge up old memories :-) You are right more so with the mention of SSL, but that's only if you assume just the straight hash being sent is the password being used for comparison. Me personally I take the Plain text sha1/md5 it one or the other, then have another completely unique and random salt value that was created and stored with the password hash initially created that I re-hash with. That salt is never seen by anyone other than the server side code. – chris Oct 07 '11 at 04:58