diff options
Diffstat (limited to 'testing/web-platform/tests/subresource-integrity')
18 files changed, 704 insertions, 0 deletions
diff --git a/testing/web-platform/tests/subresource-integrity/OWNERS b/testing/web-platform/tests/subresource-integrity/OWNERS new file mode 100644 index 000000000..8f7edaa35 --- /dev/null +++ b/testing/web-platform/tests/subresource-integrity/OWNERS @@ -0,0 +1,6 @@ +@metromoxie +@fmarier +@jonathanKingston +@mikewest +@hillbrad +@mastahyeti diff --git a/testing/web-platform/tests/subresource-integrity/alternate.css b/testing/web-platform/tests/subresource-integrity/alternate.css new file mode 100644 index 000000000..0ea6d22ec --- /dev/null +++ b/testing/web-platform/tests/subresource-integrity/alternate.css @@ -0,0 +1 @@ +.testdiv{ background-color: red } diff --git a/testing/web-platform/tests/subresource-integrity/crossorigin-anon-script.js b/testing/web-platform/tests/subresource-integrity/crossorigin-anon-script.js new file mode 100644 index 000000000..8493585f1 --- /dev/null +++ b/testing/web-platform/tests/subresource-integrity/crossorigin-anon-script.js @@ -0,0 +1 @@ +crossorigin_anon_script=true;
\ No newline at end of file diff --git a/testing/web-platform/tests/subresource-integrity/crossorigin-anon-script.js.headers b/testing/web-platform/tests/subresource-integrity/crossorigin-anon-script.js.headers new file mode 100644 index 000000000..cb762eff8 --- /dev/null +++ b/testing/web-platform/tests/subresource-integrity/crossorigin-anon-script.js.headers @@ -0,0 +1 @@ +Access-Control-Allow-Origin: * diff --git a/testing/web-platform/tests/subresource-integrity/crossorigin-anon-style.css b/testing/web-platform/tests/subresource-integrity/crossorigin-anon-style.css new file mode 100644 index 000000000..3cde4df12 --- /dev/null +++ b/testing/web-platform/tests/subresource-integrity/crossorigin-anon-style.css @@ -0,0 +1 @@ +.testdiv{ background-color: yellow } diff --git a/testing/web-platform/tests/subresource-integrity/crossorigin-anon-style.css.headers b/testing/web-platform/tests/subresource-integrity/crossorigin-anon-style.css.headers new file mode 100644 index 000000000..cb762eff8 --- /dev/null +++ b/testing/web-platform/tests/subresource-integrity/crossorigin-anon-style.css.headers @@ -0,0 +1 @@ +Access-Control-Allow-Origin: * diff --git a/testing/web-platform/tests/subresource-integrity/crossorigin-creds-script.js b/testing/web-platform/tests/subresource-integrity/crossorigin-creds-script.js new file mode 100644 index 000000000..6f39e25b4 --- /dev/null +++ b/testing/web-platform/tests/subresource-integrity/crossorigin-creds-script.js @@ -0,0 +1 @@ +crossorigin_creds_script=true;
\ No newline at end of file diff --git a/testing/web-platform/tests/subresource-integrity/crossorigin-creds-script.js.sub.headers b/testing/web-platform/tests/subresource-integrity/crossorigin-creds-script.js.sub.headers new file mode 100644 index 000000000..d6af1f0de --- /dev/null +++ b/testing/web-platform/tests/subresource-integrity/crossorigin-creds-script.js.sub.headers @@ -0,0 +1,2 @@ +Access-Control-Allow-Origin: {{location[scheme]}}://{{domains[]}}{{GET[acao_port]}} +Access-Control-Allow-Credentials: true diff --git a/testing/web-platform/tests/subresource-integrity/crossorigin-creds-style.css b/testing/web-platform/tests/subresource-integrity/crossorigin-creds-style.css new file mode 100644 index 000000000..3cde4df12 --- /dev/null +++ b/testing/web-platform/tests/subresource-integrity/crossorigin-creds-style.css @@ -0,0 +1 @@ +.testdiv{ background-color: yellow } diff --git a/testing/web-platform/tests/subresource-integrity/crossorigin-creds-style.css.sub.headers b/testing/web-platform/tests/subresource-integrity/crossorigin-creds-style.css.sub.headers new file mode 100644 index 000000000..d6af1f0de --- /dev/null +++ b/testing/web-platform/tests/subresource-integrity/crossorigin-creds-style.css.sub.headers @@ -0,0 +1,2 @@ +Access-Control-Allow-Origin: {{location[scheme]}}://{{domains[]}}{{GET[acao_port]}} +Access-Control-Allow-Credentials: true diff --git a/testing/web-platform/tests/subresource-integrity/crossorigin-ineligible-script.js b/testing/web-platform/tests/subresource-integrity/crossorigin-ineligible-script.js new file mode 100644 index 000000000..dd2f968ef --- /dev/null +++ b/testing/web-platform/tests/subresource-integrity/crossorigin-ineligible-script.js @@ -0,0 +1 @@ +crossorigin_ineligible_script=true;
\ No newline at end of file diff --git a/testing/web-platform/tests/subresource-integrity/crossorigin-ineligible-style.css b/testing/web-platform/tests/subresource-integrity/crossorigin-ineligible-style.css new file mode 100644 index 000000000..3cde4df12 --- /dev/null +++ b/testing/web-platform/tests/subresource-integrity/crossorigin-ineligible-style.css @@ -0,0 +1 @@ +.testdiv{ background-color: yellow } diff --git a/testing/web-platform/tests/subresource-integrity/matching-digest.js b/testing/web-platform/tests/subresource-integrity/matching-digest.js new file mode 100644 index 000000000..ec41325e4 --- /dev/null +++ b/testing/web-platform/tests/subresource-integrity/matching-digest.js @@ -0,0 +1 @@ +matching_digest=true;
\ No newline at end of file diff --git a/testing/web-platform/tests/subresource-integrity/non-matching-digest.js b/testing/web-platform/tests/subresource-integrity/non-matching-digest.js new file mode 100644 index 000000000..1b4943ee0 --- /dev/null +++ b/testing/web-platform/tests/subresource-integrity/non-matching-digest.js @@ -0,0 +1 @@ +non_matching_digest=true;
\ No newline at end of file diff --git a/testing/web-platform/tests/subresource-integrity/style.css b/testing/web-platform/tests/subresource-integrity/style.css new file mode 100644 index 000000000..3cde4df12 --- /dev/null +++ b/testing/web-platform/tests/subresource-integrity/style.css @@ -0,0 +1 @@ +.testdiv{ background-color: yellow } diff --git a/testing/web-platform/tests/subresource-integrity/subresource-integrity.sub.html b/testing/web-platform/tests/subresource-integrity/subresource-integrity.sub.html new file mode 100644 index 000000000..89ae018e4 --- /dev/null +++ b/testing/web-platform/tests/subresource-integrity/subresource-integrity.sub.html @@ -0,0 +1,573 @@ +<!DOCTYPE html> +<meta charset=utf-8> +<title>Subresource Integrity</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> + +<div id="log"></div> + +<div id="container"></div> +<script> + // This horrible hack is needed for the 'use-credentials' tests because, on + // response, if port 80 or 443 is the current port, it will not appear to + // the browser as part of the origin string. Since the origin *string* is + // used for CORS access control, instead of the origin itself, if there + // isn't an exact string match, the check will fail. For example, + // "http://example.com" would not match "http://example.com:80", because + // they are not exact string matches, even though the origins are the same. + // + // Thus, we only want the Access-Control-Allow-Origin header to have + // the port if it's not port 80 or 443, since the user agent will elide the + // ports in those cases. + var main_domain = "{{domains[]}}"; + var www_domain = "{{domains[www]}}"; + var default_port = "{{ports[http][0]}}"; + if (location.protocol === "https:") { + default_port = "{{ports[https][0]}}"; + } + + var port_string = ""; + if (default_port !== "80" && default_port !== "443") + port_string = ":" + default_port; + + www_host_and_port = www_domain + port_string; + + // <script> tests + var xorigin_anon_script = location.protocol + + '//' + www_host_and_port + + '/subresource-integrity/crossorigin-anon-script.js'; + + var xorigin_creds_script = location.protocol + + '//' + www_host_and_port + + '/subresource-integrity/crossorigin-creds-script.js?acao_port=' + + port_string; + + var xorigin_ineligible_script = location.protocol + + '//' + www_host_and_port + + '/subresource-integrity/crossorigin-ineligible-script.js'; + + var SRIScriptTest = function(pass, name, src, integrityValue, crossoriginValue) { + this.pass = pass; + this.name = "Script: " + name; + this.src = src; + this.integrityValue = integrityValue; + this.crossoriginValue = crossoriginValue; + } + + SRIScriptTest.prototype.execute = function() { + var test = async_test(this.name); + var e = document.createElement("script"); + e.src = this.src; + e.setAttribute("integrity", this.integrityValue); + if(this.crossoriginValue) { + e.setAttribute("crossorigin", this.crossoriginValue); + } + if(this.pass) { + e.addEventListener("load", function() {test.done()}); + e.addEventListener("error", function() { + test.step(function(){ assert_unreached("Good load fired error handler.") }) + }); + } else { + e.addEventListener("load", function() { + test.step(function() { assert_unreached("Bad load succeeded.") }) + }); + e.addEventListener("error", function() {test.done()}); + } + document.body.appendChild(e); + }; + + // Note that all of these style URLs have query parameters started, so any + // additional parameters should be appended starting with '&'. + var xorigin_anon_style = location.protocol + + '//' + www_host_and_port + + '/subresource-integrity/crossorigin-anon-style.css?'; + + var xorigin_creds_style = location.protocol + + '//' + www_host_and_port + + '/subresource-integrity/crossorigin-creds-style.css?acao_port=' + + port_string; + + var xorigin_ineligible_style = location.protocol + + '//' + www_host_and_port + + '/subresource-integrity/crossorigin-ineligible-style.css?'; + + // <link> tests + // Style tests must be done synchronously because they rely on the presence + // and absence of global style, which can affect later tests. Thus, instead + // of executing them one at a time, the style tests are implemented as a + // queue that builds up a list of tests, and then executes them one at a + // time. + var SRIStyleTest = function(queue, pass, name, attrs, customCallback, altPassValue) { + this.pass = pass; + this.name = "Style: " + name; + this.customCallback = customCallback || function () {}; + this.attrs = attrs || {}; + this.passValue = altPassValue || "rgb(255, 255, 0)"; + + this.test = async_test(this.name); + + this.queue = queue; + this.queue.push(this); + } + + SRIStyleTest.prototype.execute = function() { + var that = this; + var container = document.getElementById("container"); + while (container.hasChildNodes()) { + container.removeChild(container.firstChild); + } + + var test = this.test; + + var div = document.createElement("div"); + div.className = "testdiv"; + var e = document.createElement("link"); + this.attrs.rel = this.attrs.rel || "stylesheet"; + for (var key in this.attrs) { + if (this.attrs.hasOwnProperty(key)) { + e.setAttribute(key, this.attrs[key]); + } + } + + if(this.pass) { + e.addEventListener("load", function() { + test.step(function() { + var background = window.getComputedStyle(div, null).getPropertyValue("background-color"); + assert_equals(background, that.passValue); + test.done(); + }); + }); + e.addEventListener("error", function() { + test.step(function(){ assert_unreached("Good load fired error handler.") }) + }); + } else { + e.addEventListener("load", function() { + test.step(function() { assert_unreached("Bad load succeeded.") }) + }); + e.addEventListener("error", function() { + test.step(function() { + var background = window.getComputedStyle(div, null).getPropertyValue("background-color"); + assert_not_equals(background, that.passValue); + test.done(); + }); + }); + } + container.appendChild(div); + container.appendChild(e); + this.customCallback(e, container); + }; + + var style_tests = []; + style_tests.execute = function() { + if (this.length > 0) { + this.shift().execute(); + } + } + add_result_callback(function(res) { + if (res.name.startsWith("Style: ")) { + style_tests.execute(); + } + }); + + // Script tests + new SRIScriptTest( + true, + "Same-origin with correct sha256 hash.", + "matching-digest.js", + "sha256-U9WYDtBWkcHx13+9UKk/3Q5eoqDc4YGxYb07EPWzb9E=" + ).execute(); + + new SRIScriptTest( + true, + "Same-origin with correct sha384 hash.", + "matching-digest.js", + "sha384-BDRTPSywZFyxfLEAzaLcL4FfERBgJgXfEkuT0r04LG93Yqn1PWNYPZMomaqEfE3H" + ).execute(); + + new SRIScriptTest( + true, + "Same-origin with correct sha512 hash.", + "matching-digest.js", + "sha512-geByvIIRspbnUnwooKGNNCb39nvg+EW0O9hDScTXeo/9pVZztLSUYU3LNV6H0lZapo8bCJUpyPPLAzE9fDzpxg==" + ).execute(); + + new SRIScriptTest( + true, + "Same-origin with empty integrity.", + "matching-digest.js", + "" + ).execute(); + + new SRIScriptTest( + false, + "Same-origin with incorrect hash.", + "non-matching-digest.js", + "sha256-deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdead" + ).execute(); + + new SRIScriptTest( + true, + "Same-origin with multiple sha256 hashes, including correct.", + "matching-digest.js", + "sha256-U9WYDtBWkcHx13+9UKk/3Q5eoqDc4YGxYb07EPWzb9E= sha256-deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdead" + ).execute(); + + new SRIScriptTest( + true, + "Same-origin with multiple sha256 hashes, including unknown algorithm.", + "matching-digest.js", + "sha256-U9WYDtBWkcHx13+9UKk/3Q5eoqDc4YGxYb07EPWzb9E= foo666-deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdead" + ).execute(); + + new SRIScriptTest( + true, + "Same-origin with sha256 mismatch, sha512 match", + "matching-digest.js", + "sha512-geByvIIRspbnUnwooKGNNCb39nvg+EW0O9hDScTXeo/9pVZztLSUYU3LNV6H0lZapo8bCJUpyPPLAzE9fDzpxg== sha256-deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdead" + ).execute(); + + new SRIScriptTest( + false, + "Same-origin with sha256 match, sha512 mismatch", + "matching-digest.js", + "sha512-deadbeefspbnUnwooKGNNCb39nvg+EW0O9hDScTXeo/9pVZztLSUYU3LNV6H0lZapo8bCJUpyPPLAzE9fDzpxg== sha256-U9WYDtBWkcHx13+9UKk/3Q5eoqDc4YGxYb07EPWzb9E=" + ).execute(); + + new SRIScriptTest( + true, + "<crossorigin='anonymous'> with correct hash, ACAO: *", + xorigin_anon_script, + "sha256-51AjITq701Y0yKSx3/UoIKtIY2UQ9+H8WGyyMuOWOC0=", + "anonymous" + ).execute(); + + new SRIScriptTest( + false, + "<crossorigin='anonymous'> with incorrect hash, ACAO: *", + xorigin_anon_script, + "sha256-deadbeefcSLlbFZCj1OACLxTxVck2TOrBTEdUbwz1yU=", + "anonymous" + ).execute(); + + new SRIScriptTest( + true, + "<crossorigin='use-credentials'> with correct hash, CORS-eligible", + xorigin_creds_script, + "sha256-IaGApVboXPQxVSm2wVFmhMq1Yu37gWklajgMdxKLIvc=", + "use-credentials" + ).execute(); + + new SRIScriptTest( + false, + "<crossorigin='use-credentials'> with incorrect hash CORS-eligible", + xorigin_creds_script, + "sha256-deadbeef2S+pTRZgiw3DWrhC6JLDlt2zRyGpwH7unU8=", + "use-credentials" + ).execute(); + + new SRIScriptTest( + false, + "<crossorigin='anonymous'> with CORS-ineligible resource", + xorigin_ineligible_script, + "sha256-F5fXKTX7SiWjtgybxiBZIo2qhh2WiQnNx372E60XrOo=", + "anonymous" + ).execute(); + + new SRIScriptTest( + false, + "Cross-origin, not CORS request, with correct hash", + xorigin_anon_script, + "sha256-51AjITq701Y0yKSx3/UoIKtIY2UQ9+H8WGyyMuOWOC0=" + ).execute(); + + new SRIScriptTest( + false, + "Cross-origin, not CORS request, with hash mismatch", + xorigin_anon_script, + "sha256-deadbeef01Y0yKSx3/UoIKtIY2UQ9+H8WGyyMuOWOC0=" + ).execute(); + + new SRIScriptTest( + true, + "Cross-origin, empty integrity", + xorigin_anon_script, + "" + ).execute(); + + new SRIScriptTest( + true, + "Same-origin with correct hash, options.", + "matching-digest.js", + "sha256-U9WYDtBWkcHx13+9UKk/3Q5eoqDc4YGxYb07EPWzb9E=?foo=bar?spam=eggs" + ).execute(); + + new SRIScriptTest( + true, + "Same-origin with unknown algorithm only.", + "matching-digest.js", + "foo666-U9WYDtBWkcHx13+9UKk/3Q5eoqDc4YGxYb07EPWzb9E=" + ).execute(); + + // Style tests + new SRIStyleTest( + style_tests, + true, + "Same-origin with correct sha256 hash", + { + href: "style.css?1", + integrity: "sha256-CzHgdJ7wOccM8L89n4bhcJMz3F+SPLT7YZk7gyCWUV4=" + } + ); + + new SRIStyleTest( + style_tests, + true, + "Same-origin with correct sha384 hash", + { + href: "style.css?2", + integrity: "sha384-wDAWxH4tOWBwAwHfBn9B7XuNmFxHTMeigAMwn0iVQ0zq3FtmYMLxihcGnU64CwcX" + } + ); + + new SRIStyleTest( + style_tests, + true, + "Same-origin with correct sha512 hash", + { + href: "style.css?3", + integrity: "sha512-9wXDjd6Wq3H6nPAhI9zOvG7mJkUr03MTxaO+8ztTKnfJif42laL93Be/IF6YYZHHF4esitVYxiwpY2HSZX4l6w==" + } + ); + + new SRIStyleTest( + style_tests, + true, + "Same-origin with empty integrity", + { + href: "style.css?4", + integrity: "" + } + ); + + new SRIStyleTest( + style_tests, + false, + "Same-origin with incorrect hash.", + { + href: "style.css?5", + integrity: "sha256-deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdead" + } + ); + + new SRIStyleTest( + style_tests, + true, + "Same-origin with multiple sha256 hashes, including correct.", + { + href: "style.css?6", + integrity: "sha256-CzHgdJ7wOccM8L89n4bhcJMz3F+SPLT7YZk7gyCWUV4= sha256-deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdead" + } + ); + + new SRIStyleTest( + style_tests, + true, + "Same-origin with multiple sha256 hashes, including unknown algorithm.", + { + href: "style.css?7", + integrity: "sha256-CzHgdJ7wOccM8L89n4bhcJMz3F+SPLT7YZk7gyCWUV4= foo666-deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdead" + } + ); + + new SRIStyleTest( + style_tests, + true, + "Same-origin with sha256 mismatch, sha512 match", + { + href: "style.css?8", + integrity: "sha512-9wXDjd6Wq3H6nPAhI9zOvG7mJkUr03MTxaO+8ztTKnfJif42laL93Be/IF6YYZHHF4esitVYxiwpY2HSZX4l6w== sha256-deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdead" + } + ); + + new SRIStyleTest( + style_tests, + false, + "Same-origin with sha256 match, sha512 mismatch", + { + href: "style.css?9", + integrity: "sha512-deadbeef9wXDjd6Wq3H6nPAhI9zOvG7mJkUr03MTxaO+8ztTKnfJif42laL93Be/IF6YYZHHF4esitVYxiwpY2== sha256-CzHgdJ7wOccM8L89n4bhcJMz3F+SPLT7YZk7gyCWUV4=" + } + ); + + new SRIStyleTest( + style_tests, + true, + "<crossorigin='anonymous'> with correct hash, ACAO: *", + { + href: xorigin_anon_style + '&1', + integrity: "sha256-CzHgdJ7wOccM8L89n4bhcJMz3F+SPLT7YZk7gyCWUV4=", + crossorigin: "anonymous" + } + ); + + new SRIStyleTest( + style_tests, + false, + "<crossorigin='anonymous'> with incorrect hash, ACAO: *", + { + href: xorigin_anon_style + '&2', + integrity: "sha256-deadbeefCzHgdJ7wOccM8L89n4bhcJMz3F+SPLT7YZk=", + crossorigin: "anonymous" + } + ); + + new SRIStyleTest( + style_tests, + true, + "<crossorigin='use-credentials'> with correct hash, CORS-eligible", + { + href: xorigin_creds_style + '&1', + integrity: "sha256-CzHgdJ7wOccM8L89n4bhcJMz3F+SPLT7YZk7gyCWUV4=", + crossorigin: "use-credentials" + } + ); + + new SRIStyleTest( + style_tests, + false, + "<crossorigin='use-credentials'> with incorrect hash CORS-eligible", + { + href: xorigin_creds_style + '&2', + integrity: "sha256-deadbeefCzHgdJ7wOccM8L89n4bhcJMz3F+SPLT7YZk=", + crossorigin: "use-credentials" + } + ); + + new SRIStyleTest( + style_tests, + false, + "<crossorigin='anonymous'> with CORS-ineligible resource", + { + href: xorigin_ineligible_style + '&1', + integrity: "sha256-CzHgdJ7wOccM8L89n4bhcJMz3F+SPLT7YZk7gyCWUV4=", + crossorigin: "anonymous" + } + ); + + new SRIStyleTest( + style_tests, + false, + "Cross-origin, not CORS request, with correct hash", + { + href: xorigin_anon_style + '&3', + integrity: "sha256-CzHgdJ7wOccM8L89n4bhcJMz3F+SPLT7YZk7gyCWUV4=" + } + ); + + new SRIStyleTest( + style_tests, + false, + "Cross-origin, not CORS request, with hash mismatch", + { + href: xorigin_anon_style + '&4', + integrity: "sha256-deadbeefCzHgdJ7wOccM8L89n4bhcJMz3F+SPLT7YZk=" + } + ); + + new SRIStyleTest( + style_tests, + true, + "Cross-origin, empty integrity", + { + href: xorigin_anon_style + '&5', + integrity: "" + } + ); + + new SRIStyleTest( + style_tests, + true, + "Same-origin with correct hash, options.", + { + href: "style.css?10", + integrity: "sha256-CzHgdJ7wOccM8L89n4bhcJMz3F+SPLT7YZk7gyCWUV4=?foo=bar?spam=eggs" + } + ); + + new SRIStyleTest( + style_tests, + true, + "Same-origin with unknown algorithm only.", + { + href: "style.css?11", + integrity: "foo666-CzHgdJ7wOccM8L89n4bhcJMz3F+SPLT7YZk7gyCWUV4=?foo=bar?spam=eggs" + } + ); + + new SRIStyleTest( + style_tests, + true, + "Same-origin with correct sha256 hash, rel='stylesheet license'", + { + href: "style.css?12", + integrity: "sha256-CzHgdJ7wOccM8L89n4bhcJMz3F+SPLT7YZk7gyCWUV4=", + rel: "stylesheet license" + } + ); + + new SRIStyleTest( + style_tests, + true, + "Same-origin with correct sha256 hash, rel='license stylesheet'", + { + href: "style.css?13", + integrity: "sha256-CzHgdJ7wOccM8L89n4bhcJMz3F+SPLT7YZk7gyCWUV4=", + rel: "license stylesheet" + } + ); + + new SRIStyleTest( + style_tests, + true, + "Same-origin with correct sha256 and sha512 hash, rel='alternate stylesheet' enabled", + { + href: "alternate.css?1", + title: "alt", + type: "text/css", + class: "alternate", + disabled: "disabled", + rel: "alternate stylesheet", + integrity: "sha256-phbz83bWhnLig+d2VPKrRrTRyhqoDRo1ruGqZLZ0= sha512-8OYEB7ktnzcb6h+kB9CUIuc8qvKIyLpygRJdQSEEycRy74dUsB+Yu9rSjpOPjRUblle8WWX9Gn7v39LK2Oceig==", + }, + function (link, container) { + var alternate = document.querySelector('link.alternate'); + alternate.disabled = false; + }, + "rgb(255, 0, 0)" + ); + + new SRIStyleTest( + style_tests, + false, + "Same-origin with incorrect sha256 and sha512 hash, rel='alternate stylesheet' enabled", + { + href: "alternate.css?2", + title: "alt", + type: "text/css", + class: "alternate", + disabled: "disabled", + rel: "alternate stylesheet", + integrity: "sha256-fail83bWhnLig+d2VPKrRrTRyhqoDRo1ruGqZLZ0= sha512-failB7ktnzcb6h+kB9CUIuc8qvKIyLpygRJdQSEEycRy74dUsB+Yu9rSjpOPjRUblle8WWX9Gn7v39LK2Oceig==", + }, + function (link, container) { + var alternate = document.querySelector('link.alternate'); + alternate.disabled = false; + } + ); + + style_tests.execute(); + +</script> +<!-- TODO check cache-poisoned resources, transfer-encoding, 3xx redirect + to resource with matching hash, and cross-origin leakage test as in sec5.3. + --> diff --git a/testing/web-platform/tests/subresource-integrity/tools/generate_javascript.py b/testing/web-platform/tests/subresource-integrity/tools/generate_javascript.py new file mode 100644 index 000000000..184a39451 --- /dev/null +++ b/testing/web-platform/tests/subresource-integrity/tools/generate_javascript.py @@ -0,0 +1,52 @@ +from os import path, listdir +from hashlib import sha512, sha256, md5 +from base64 import b64encode +import re + +JS_DIR = path.normpath(path.join(__file__, "..", "..")) + +''' +Yield each file in the javascript directory +''' +def js_files(): + for f in listdir(JS_DIR): + if path.isfile(f) and f.endswith(".js"): + yield f + +''' +URL-safe base64 encode a binary digest and strip any padding. +''' +def format_digest(digest): + return b64encode(digest) + +''' +Generate an encoded sha512 URI. +''' +def sha512_uri(content): + return "sha512-%s" % format_digest(sha512(content).digest()) + +''' +Generate an encoded sha256 URI. +''' +def sha256_uri(content): + return "sha256-%s" % format_digest(sha256(content).digest()) + +''' +Generate an encoded md5 digest URI. +''' +def md5_uri(content): + return "md5-%s" % format_digest(md5(content).digest()) + +def main(): + for file in js_files(): + print "Generating content for %s" % file + base = path.splitext(path.basename(file))[0] + var_name = re.sub(r"[^a-z0-9]", "_", base) + content = "%s=true;" % var_name + with open(file, "w") as f: f.write(content) + print "\tSHA512 integrity: %s" % sha512_uri(content) + print "\tSHA256 integrity: %s" % sha256_uri(content) + print "\tMD5 integrity: %s" % md5_uri(content) + +if __name__ == "__main__": + main() diff --git a/testing/web-platform/tests/subresource-integrity/tools/list_hashes.py b/testing/web-platform/tests/subresource-integrity/tools/list_hashes.py new file mode 100644 index 000000000..5e3830ab6 --- /dev/null +++ b/testing/web-platform/tests/subresource-integrity/tools/list_hashes.py @@ -0,0 +1,57 @@ +from os import path, listdir +from hashlib import sha512, sha384, sha256, md5 +from base64 import b64encode +import re + +DIR = path.normpath(path.join(__file__, "..", "..")) + +''' +Yield each javascript and css file in the directory +''' +def js_and_css_files(): + for f in listdir(DIR): + if path.isfile(f) and (f.endswith(".js") or f.endswith(".css")): + yield f + +''' +URL-safe base64 encode a binary digest and strip any padding. +''' +def format_digest(digest): + return b64encode(digest) + +''' +Generate an encoded sha512 URI. +''' +def sha512_uri(content): + return "sha512-%s" % format_digest(sha512(content).digest()) + +''' +Generate an encoded sha384 URI. +''' +def sha384_uri(content): + return "sha384-%s" % format_digest(sha384(content).digest()) + +''' +Generate an encoded sha256 URI. +''' +def sha256_uri(content): + return "sha256-%s" % format_digest(sha256(content).digest()) + +''' +Generate an encoded md5 digest URI. +''' +def md5_uri(content): + return "md5-%s" % format_digest(md5(content).digest()) + +def main(): + for file in js_and_css_files(): + print "Listing hash values for %s" % file + with open(file, "r") as content_file: + content = content_file.read() + print "\tSHA512 integrity: %s" % sha512_uri(content) + print "\tSHA384 integrity: %s" % sha384_uri(content) + print "\tSHA256 integrity: %s" % sha256_uri(content) + print "\tMD5 integrity: %s" % md5_uri(content) + +if __name__ == "__main__": + main() |