|  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #64211 sha256 hashes "#", "&", and "+" incorrectly.
Submitted: 2013-02-14 11:05 UTC Modified: 2013-02-15 13:56 UTC
From: pwormer at science dot ru dot nl Assigned:
Status: Not a bug Package: hash related
PHP Version: 5.4.11 OS: windows/linux
Private report: No CVE-ID: None
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If this is not your bug, you can add a comment by following this link.
If this is your bug, but you forgot your password, you can retrieve your password here.
Bug Type:
From: pwormer at science dot ru dot nl
New email:
PHP Version: OS:


 [2013-02-14 11:05 UTC] pwormer at science dot ru dot nl
The JavaScript functions at:


give the same hash for any password  of any length consisting of ASCII 32 through 128.  Almost always the hash is the same as obtained from PHP:  hash("sha256", $pswd).

Exceptions (bugs?) are passwords containing one or more of the three characters:
"#" (number sign), "&" (ampersand), or "+" (plus sign).

Tested with XAMPP (PHP 5.4.7), FireFox and Chrome and Linux server.

Test script:

This URL calls SHA256.php which contains the following four lines

$pswd = $_GET["pswd"];
echo hash("sha256", $pswd);

Expected result:
I expect JavaScript and PHP to give same Sha-256 hashes

Actual result:
Hash of # (single character):

JS:  334359b90efed75da5f0ada1d5e6b256f4a6bd0aee7eb39c0f90182a021ffc8b
PHP: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855


Add a Patch

Pull Requests

Add a Pull Request


AllCommentsChangesGit/SVN commitsRelated reports
 [2013-02-14 21:37 UTC]
-Status: Open +Status: Not a bug
 [2013-02-14 21:37 UTC]
Can't reproduce on 32 or 64 bit Linux:
$ php53 -r 'echo hash("sha256", "#") . "\n";'
$ php54 -r 'echo hash("sha256", "#") . "\n";'

Is it coincidence that "" (an empty string) gives the hash you are expecting for 

$ php53 -r 'echo hash("sha256", "") . "\n";'
$ php54 -r 'echo hash("sha256", "") . "\n";'
 [2013-02-14 21:38 UTC]
 [2013-02-15 10:29 UTC] pwormer at science dot ru dot nl
Two more examples:

1. Password "a b" (no quotes, pswd contains three characters, middle one ASCII 32):
JS-hashed password :  c8687a08aa5d6ed2044328fa6a697ab8e96dc34291e8c2034ae8c38e6fcc6d65
PHP-hashed password:  c8687a08aa5d6ed2044328fa6a697ab8e96dc34291e8c2034ae8c38e6fcc6d65

2. Password "a#b" (no quotes, pswd contains three characters, middle one ASCII 35):
JS-hashed password : 8187fc8f7f007036dffc199544b33167632c7739733785bbdec0fbb9a2c43ca1
PHP-hashed password: ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb

My problem is the difference in hash between JavaScript and PHP that occurs if and only if the pswd contains anywhere #, & or +. By looking at PHP alone this problem cannot be solved.
 [2013-02-15 10:40 UTC] pwormer at science dot ru dot nl
I call PHP from JS through"GET", "SHA256.php?pswd="+pswd). Maybe the problem lies in XMLHttp?
 [2013-02-15 11:00 UTC]
That'S your problem. You have to escape the URL parameters.
 pswd = "a#b";
 url = "SHA256.php?pswd="+pswd

will create the URL "SHA256.php?pswd=a#b" the browser will then cut of the "#b" from the URL before sending it to the server.

$ php -r 'echo hash("sha256", "a");'

Which is what you get. You should escape the data ... 

Additional comment: Don't transfer the password as part of the URL. URLs are stored in browser history etc. and might leak therefore. Always use POST data for that. (but still mind proper escaping)
 [2013-02-15 13:56 UTC] pwormer at science dot ru dot nl
Thank you, forgetting to encode was indeed my problem. What threw me off was that almost all special characters (slash, period, at-sign, angular brackets, etc) worked OK without encoding. 

Your point about GET versus POST is well taken. I used GET so far because I'm in an exploration phase. In my definite code I will either use POST or don't hash  on the client, I have to think more about it.
PHP Copyright © 2001-2023 The PHP Group
All rights reserved.
Last updated: Wed Feb 01 10:03:45 2023 UTC