12

i am creating Hash values with following code, now what happens is that when i test the hash value on Windows local Xampp server i get hash value which is different for same code that runs on Linux.

  move_uploaded_file($_FILES["file"]["tmp_name"], "upload/" . $newname);
    "Stored in: " . "upload/" . $_FILES["file"]["name"];
    $image = "upload/" . $newname;
    $sign = md5(file_get_contents($image));

Now i dont know why is this happening. For the same code that i just pasted above.

EDIT: Opening question again. The solution i found worked only for Linux which means linux and windows now give me same hash but when an image is uploaded from Mac(IOS) it is still generating different Hash.

noobie-php
  • 6,817
  • 15
  • 54
  • 101
  • 2
    Is it really the same file with the same line endings? Does running `md5sum` on both systems return the same hash? – scai May 23 '14 at 12:43
  • Just test with an arbitrary string, such as `md5('hello');`. Does this match on both systems? – Ohgodwhy May 23 '14 at 12:44
  • Might be an interesting read: http://ubuntuforums.org/showthread.php?t=1941596 – Fluffeh May 23 '14 at 12:44
  • Try comparing the checksums of the file you are uploading and the actual file that has been uploaded and moved to the upload dir by PHP. Are the checksum same? – Laurynas Tretjakovas May 23 '14 at 12:50
  • @scai: its same file tested around 20+ times. at(@)Ohgodwhy: gonna try this,at(@) Laurynas Tretjakovas: i havent calculated checksum yet – noobie-php May 23 '14 at 12:55
  • @Fluffeh: just roughly checked your link, it tells about linux commands regarding permissions i guess, but that dosent tell how to solve it from code point of view – noobie-php May 23 '14 at 13:06
  • If you run an md5 command line tool on each platform, on the file that you've got on disk, what does that show? How does it compare with the hashes you've been generating in PHP? – Jon Skeet May 30 '14 at 06:03
  • Next step: remember `file_get_contents($image)` and log the length of the string. That should at least give a preliminary idea of whether they're *possibly* the same... – Jon Skeet May 30 '14 at 06:04
  • Are you saying the same file uploaded from different client OSes to the same server produce different hashes? Or are you saying the same file uploaded to different server OSes produce different hashes? Because your original question mentions win and linux servers but your edit mentions uploading from (not to) Mac. – FuzzyTree Jun 03 '14 at 04:37
  • @FuzzyTree: I am referring to your 1st explanation i.e `Are you saying the same file uploaded from different client OSes to the same server produce different hashes?` – noobie-php Jun 04 '14 at 12:06

4 Answers4

12

Windows and Linux has different line endings, \r\n and \n. So when the file is read, the content of files is different.

Try uploading Text file with no new line or a Binary file. Also check difference in bytes read. It should be equal to number of new lines in next file.

HoldOffHunger
  • 18,769
  • 10
  • 104
  • 133
Sharad D
  • 329
  • 1
  • 11
  • Thanks alot mate you actually technically guided me on what the problem is , but i still want solution about the problem. – noobie-php Jun 04 '14 at 10:36
  • 1
    Personally I wouldn't recommend this. Since the two files are basically different, it should have different checksum. You can check if file is ascii or binary as given in http://stackoverflow.com/questions/632685/how-to-check-if-file-is-ascii-or-binary-in-php and then convert \r\n to \n http://stackoverflow.com/questions/10209413/how-do-i-convert-line-breaks-to-n. Now check the checksum of converted String. – Sharad D Jun 04 '14 at 10:45
  • The issue for me was that my unit test was using a JSON file which had CRLF line endings, worked on Windows, failed on Ubuntu agent, changing the line endings of the JSON file to CRLF fixed it. – Mohammad Sepahvand May 11 '22 at 08:16
8

Ok i found answer to my question, I still dont know why there are two different hashes been generated for the same code in windows and Linux

move_uploaded_file($_FILES["file"]["tmp_name"], "upload/" . $newname); 
    "Stored in: " . "upload/" . $_FILES["file"]["name"];
    $image = "upload/" . $newname;
    $sign = md5(file_get_contents($image));//This is code block that i was implmenting before solution

What i tried here was i replaced my above code with following code

 move_uploaded_file($_FILES["file"]["tmp_name"], "upload/" . $newname);
        "Stored in: " . "upload/" . $_FILES["file"]["name"];
        $image = "upload/" . $newname;
        $sign = md5_file($image);// Changed here

From this i think Hash values may be same when generated by md5() but if this function accepts file as input then hash values are calculated differently, i dont know if this is a PHP side issue or really OS level issue but if i go on with using md5_file() for generating hash of file i dont get different hash.

noobie-php
  • 6,817
  • 15
  • 54
  • 101
  • My **guess** is that file_get_contents() is behaving differently on the different platforms. Possibly a locale-specific thing? I'm not sure how you could test that hypothesis, too :-/ – burlyearly May 29 '14 at 21:20
  • Your "answer" is now just to hash the filename instead of the content. What's the point of that? I would strongly expect that you really want to hash the content instead. – Jon Skeet May 30 '14 at 06:02
  • 1
    @JonSkeet: Exactly filename is not an issue , issue is actually generating hash. from Filename if you mean `md5_file($image);` then this isnt actually file name that is hashed, its actually file it self. – noobie-php May 30 '14 at 07:32
  • Yes actually answer and question both are given by me so , if some 1 have to look they have to look on both – noobie-php May 30 '14 at 07:54
0

To get the same hash as what's produced in a mac using something like this command:

shasum -a 256 -p {filename} | cut -d' ' -f1"

Replace {filename} with the name of your file to hash on the mac. | cut -d' ' -f1 cuts off the filename from the end of what's returned as were only interested in the hash.

On Windows to get the same hash you need to do this:

Get a stream of your file and call this function I made:

public static string GetSha256Checksum(this Stream stream)
    {
        stream.Rewind();
        using (var sha256 = SHA256Cng.Create())
        {
            return string.Concat(
                sha256.ComputeHash(stream)
                    .Select(item => item.ToString("x2"))
            );
        }
    }

This is what's fundamentally different when creating a hash to be the same as a mac:

string.Concat(sha256.ComputeHash(stream)
              .Select(item => item.ToString("x2"))
Ian
  • 2,898
  • 1
  • 27
  • 29
-1

Might look at the page for fopen() about how to avoid line endings problems but it basically comes down to using 'wb' and 'rb' when writing and reading the file. Here's the link to the fopen page.

Does mean probably can't use file_get_content() as doesn't seem to have option to set read mode.

Dragonaire
  • 313
  • 3
  • 7