Function to create hash in SRI pattern

Asked

Viewed 578 times

2

I was looking at a new specification W3C SRI (Subresource Integrity) which roughly means Integrity of the Sub-resource that promises to bring more security to resources hosted on third-party servers (or in the own) already in use by Bootstrapcdn, Cloudflare, Github and jQuery although it is still new and does not have a wide implementation by browsers.

Basically the new specification adds the tag script two new attributes:

  • Integrity: containing the hash cryptographic file
  • crossorigin: by default "Anonymous"

The (simplistic) documentation describes the use of OpenSSL via command line to create the hash:

Command line instruction to generate hash

openssl dgst -sha384 -binary FILENAME.js | openssl base64 -A

My question is: how to use the functions openssl of PHP to get the same result (generate the hash of a file)?

References:

2 answers

3


You have the hash_file() in PHP, that the variation of hash() for archives, which is similar to dead md5_file().

$algoritmo = 'SHA512';
$arquivo = 'arquivo.js';

$hash = hash_file($algoritmo, $arquivo, true);

$integrity = strtolower($algoritmo) . '-' . base64_encode( $hash );

So just use:

<script src="' . $arquivo . '" integrity="' . $integrity . '" crossorigin="anonymous">

Obviously I should calculate this beforehand, because to perform this on each page visited is a waste, to spend time to calculate the same hash at all times...

I don’t see much point in using this for the same domain, because if someone has access or can change the content the javascript will quite possibly be able to change the hash HTML, thus making the new Javascript valid.

If you use CDN (or another server) to distribute javascript, or if you will allow others to enter your javascript, it makes a great sense to use this feature, because in this situation if someone changes your file your clients will have the file HASH.


The use of this feature would prevent/minimize the attack on the "Armored Site", which modified the image, showing another result, this occurred in 2012, see here, all "Armored Site" customers had their pages showing the altered content, a "Hacked Armored Site" logo, due to there being no kind of verification.

  • It is worth mentioning the correction: the specification SRI requires the decriminator of the algorithm used to be lowercase and the value in base64 be a binário.

  • As for use: the scripts and its attributes are mounted on PHP and curly with OPcache to be used on other pages without waste of resources... regarding unauthorized access or good hack, this specification does not mitigate the damage arising from this.

  • I corrected to force the minuscule letter. About the "invasions" what I meant is that it reduces the damage range. Imagine that you use the Jquery of Googleapis. If Google "is hacked" (or MITM) and changes the Jquery library, your website may display malicious javascript instead. With the use of this feature the hash of both files will be different, the malicious file will have a different hash than the original file, thus preventing visitors to your site from using malicious JS, so we can say that in case of invasions on THIRD PARTY SERVERS it reduces the damage.

  • Wouldn’t it have been easier to change SHA512 for sha512 rather than the use of strtolower()? Add a third argument to the function hash_file() ({boolean} true) for her to return a binary. Would you know what function (openssl_digest(), hash() or hash_file()) has less processing cost? Grateful

  • The way your example is making a mistake

  • I made the correction, I did not understand this detail. O hash() is for texts, you use the file_get_contents should be slower than the hash_file, that must do the same task in C, much faster than PHP. I do not know, I personally avoid using it, but I believe it should be as fast as. I used the strtolower because it avoids human error, if it depends on someone typing in minuscule or capital case the chance of failure would be higher, someone could fall here and not notice that it has to be minuscule, using the strtolower either way will be minuscule.

Show 1 more comment

0

When searching in the community about SRI did not get results so I leave my own answer.

In a practical way I arrived at the result in two ways PHP:

<?php

   $file = file_get_contents('./main.js');

   echo "sha512-".base64_encode(openssl_digest($file, 'sha512', true));

   //output: sha512-4nAOca/W9ZDO2dwcudh/hbnatmbvezf5ZTti0+VZFDG+V65tDx8OeKIpZfG7NYvOjqytEveULALcb7ZbPAuF/Q==


   $hash = hash('sha512', $file, true);

   echo "sha512-".base64_encode($hash);

   //output: sha512-4nAOca/W9ZDO2dwcudh/hbnatmbvezf5ZTti0+VZFDG+V65tDx8OeKIpZfG7NYvOjqytEveULALcb7ZbPAuF/Q==

Both return the same result, fit here to test performance.

Reference:

In this article of the website Tenzer.dk the author indicates to have observed the source code of the site SRI Hash Generator and adapted the logic to other languages between them:

  • Shell
  • Python
  • Node.js
  • Go
  • Ruby
  • PHP

And how the specification deals with using a checksum worth going through this reference here from the community.

That’s it.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.