Bug 1191936 - Add more test vectors and a test for deterministic signatures r=rbarnes
authorTim Taubert <tim@timtaubert.de>
Fri, 22 Jan 2016 15:37:35 +0100
changeset 318136 92e279613f0e
parent 318135 29a076e8bc0d
child 318137 86ea08134f37
push id5913
push userjlund@mozilla.com
push dateMon, 25 Apr 2016 16:57:49 +0000
treeherdermozilla-beta@dcaf0a6fa115 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersrbarnes
bugs1191936
milestone47.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1191936 - Add more test vectors and a test for deterministic signatures r=rbarnes
dom/crypto/test/test-vectors.js
dom/crypto/test/test_WebCrypto_RSA_PSS.html
--- a/dom/crypto/test/test-vectors.js
+++ b/dom/crypto/test/test-vectors.js
@@ -413,17 +413,17 @@ tv = {
     result: util.hex2abv(
       "354fe67b4a126d5d35fe36c777791a3f7ba13def484e2d3908aff722fad468fb" +
       "21696de95d0be911c2d3174f8afcc201035f7b6d8e69402de5451618c21a535f" +
       "a9d7bfc5b8dd9fc243f8cf927db31322d6e881eaa91a996170e657a05a266426" +
       "d98c88003f8477c1227094a0d9fa1e8c4024309ce1ecccb5210035d47ac72e8a"
     ),
   },
 
-  // RSA-PSS test vectors, pss-vect.txt, Example 1: A 1024-bit RSA Key Pair
+  // [pss-vect.txt] Example 1.1 from
   // <ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip>
   rsapss: {
     pkcs8: util.hex2abv(
       "30820275020100300d06092a864886f70d01010105000482025f3082025b0201" +
       "0002818100a56e4a0e701017589a5187dc7ea841d156f2ec0e36ad52a44dfeb1" +
       "e61f7ad991d8c51056ffedb162b4c0f283a12a88a394dff526ab7291cbb307ce" +
       "abfce0b1dfd5cd9508096d5b2b8b6df5d671ef6377c0921cb23c270a70e2598e" +
       "6ff89d19f105acc2d3f0cb35f29280e1386b6f64c4ef22e1e1f20d0ce8cffb22" +
@@ -461,19 +461,17 @@ tv = {
       "be02546f130fd2e33b936d2676e08aed1b73318b750a0167d0"
     ),
     sig: util.hex2abv(
       "9074308fb598e9701b2294388e52f971faac2b60a5145af185df5287b5ed2887" +
       "e57ce7fd44dc8634e407c8e0e4360bc226f3ec227f9d9e54638e8d31f5051215" +
       "df6ebb9c2f9579aa77598a38f914b5b9c1bd83c4e2f9f382a0d0aa3542ffee65" +
       "984a601bc69eb28deb27dca12c82c2d4c3f66cd500f1ff2b994d8a4e30cbb33c"
     ),
-    salt: util.hex2abv(
-      "dee959c7e06411361420ff80185ed57f3e6776af"
-    ),
+    saltLength: 20,
     jwk_priv: {
       kty: "RSA",
       n: "pW5KDnAQF1iaUYfcfqhB0Vby7A42rVKkTf6x5h962ZHYxRBW_-2xYrTA8oOhK" +
          "oijlN_1JqtykcuzB86r_OCx39XNlQgJbVsri2311nHvY3fAkhyyPCcKcOJZjm" +
          "_4nRnxBazC0_DLNfKSgOE4a29kxO8i4eHyDQzoz_siSb2aITc",
       e: "AQAB",
       d: "M6UEKpCyfU9UUcqbu9C0R3GhAa-IQ0Cu-YhfKku-kuiUpySsPFaMj5eFOtB8A" +
          "mbIxqPKCSnx6PESMYhEKfxNmuVf7olqEM5wfD7X5zTkRyejlXRQGlMmgxCcKr" +
@@ -493,16 +491,114 @@ tv = {
       kty: "RSA",
       n: "pW5KDnAQF1iaUYfcfqhB0Vby7A42rVKkTf6x5h962ZHYxRBW_-2xYrTA8oOhK" +
          "oijlN_1JqtykcuzB86r_OCx39XNlQgJbVsri2311nHvY3fAkhyyPCcKcOJZjm" +
          "_4nRnxBazC0_DLNfKSgOE4a29kxO8i4eHyDQzoz_siSb2aITc",
       e: "AQAB",
     },
   },
 
+  // [pss-vect.txt] Example 1.4 from
+  // <ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip>
+  rsapss2: {
+    spki: util.hex2abv(
+      "30819f300d06092a864886f70d010101050003818d0030818902818100a56e4a" +
+      "0e701017589a5187dc7ea841d156f2ec0e36ad52a44dfeb1e61f7ad991d8c510" +
+      "56ffedb162b4c0f283a12a88a394dff526ab7291cbb307ceabfce0b1dfd5cd95" +
+      "08096d5b2b8b6df5d671ef6377c0921cb23c270a70e2598e6ff89d19f105acc2" +
+      "d3f0cb35f29280e1386b6f64c4ef22e1e1f20d0ce8cffb2249bd9a2137020301" +
+      "0001"
+    ),
+    data: util.hex2abv(
+      "bc656747fa9eafb3f0"
+    ),
+    sig: util.hex2abv(
+      "4609793b23e9d09362dc21bb47da0b4f3a7622649a47d464019b9aeafe53359c" +
+      "178c91cd58ba6bcb78be0346a7bc637f4b873d4bab38ee661f199634c547a1ad" +
+      "8442e03da015b136e543f7ab07c0c13e4225b8de8cce25d4f6eb8400f81f7e18" +
+      "33b7ee6e334d370964ca79fdb872b4d75223b5eeb08101591fb532d155a6de87"
+    ),
+    saltLength: 20
+  },
+
+  // [SigVerPSS_186-3.rsp] from
+  // <http://csrc.nist.gov/groups/STM/cavp/documents/dss/186-2rsatestvectors.zip>
+  rsapss3: {
+    spki: util.hex2abv(
+      "30819d300d06092a864886f70d010101050003818b0030818702818100be499b" +
+      "5e7f06c83fa0293e31465c8eb6b58af920bae52a7b5b9bfeb7aa72db1264112e" +
+      "b3fd431d31a2a7e50941566929494a0e891ed5613918b4b51b0d1fb97783b26a" +
+      "cf7d0f384cfb35f4d2824f5dd380623a26bf180b63961c619dcdb20cae406f22" +
+      "f6e276c80a37259490cfeb72c1a71a84f1846d330877ba3e3101ec9c7b020111"
+    ),
+    data: util.hex2abv(
+      "c7f5270fca725f9bd19f519a8d7cca3cc5c079024029f3bae510f9b02140fe23" +
+      "8908e4f6c18f07a89c687c8684669b1f1db2baf9251a3c829faccb493084e16e" +
+      "c9e28d58868074a5d6221667dd6e528d16fe2c9f3db4cfaf6c4dce8c8439af38" +
+      "ceaaaa9ce2ecae7bc8f4a5a55e3bf96df9cd575c4f9cb327951b8cdfe4087168"
+    ),
+    sig: util.hex2abv(
+      "11e169f2fd40b07641b9768a2ab19965fb6c27f10fcf0323fcc6d12eb4f1c06b" +
+      "330ddaa1ea504407afa29de9ebe0374fe9d1e7d0ffbd5fc1cf3a3446e4145415" +
+      "d2ab24f789b3464c5c43a256bbc1d692cf7f04801dac5bb401a4a03ab7d5728a" +
+      "860c19e1a4dc797ca542c8203cec2e601eb0c51f567f2eda022b0b9ebddeeefa"
+    ),
+    saltLength: 10
+  },
+
+  // [SigVerPSS_186-3.rsp] from
+  // <http://csrc.nist.gov/groups/STM/cavp/documents/dss/186-2rsatestvectors.zip>
+  rsapss4: {
+    spki: util.hex2abv(
+      "30819d300d06092a864886f70d010101050003818b0030818702818100be499b" +
+      "5e7f06c83fa0293e31465c8eb6b58af920bae52a7b5b9bfeb7aa72db1264112e" +
+      "b3fd431d31a2a7e50941566929494a0e891ed5613918b4b51b0d1fb97783b26a" +
+      "cf7d0f384cfb35f4d2824f5dd380623a26bf180b63961c619dcdb20cae406f22" +
+      "f6e276c80a37259490cfeb72c1a71a84f1846d330877ba3e3101ec9c7b020111"
+    ),
+    data: util.hex2abv(
+      "c7f5270fca725f9bd19f519a8d7cca3cc5c079024029f3bae510f9b02140fe23" +
+      "8908e4f6c18f07a89c687c8684669b1f1db2baf9251a3c829faccb493084e16e" +
+      "c9e28d58868074a5d6221667dd6e528d16fe2c9f3db4cfaf6c4dce8c8439af38" +
+      "ceaaaa9ce2ecae7bc8f4a5a55e3bf96df9cd575c4f9cb327951b8cdfe4087168"
+    ),
+    sig: util.hex2abv(
+      "b281ad934b2775c0cba5fb10aa574d2ed85c7f99b942b78e49702480069362ed" +
+      "394baded55e56cfcbe7b0b8d2217a05a60e1acd725cb09060dfac585bc2132b9" +
+      "9b41cdbd530c69d17cdbc84bc6b9830fc7dc8e1b2412cfe06dcf8c1a0cc3453f" +
+      "93f25ebf10cb0c90334fac573f449138616e1a194c67f44efac34cc07a526267"
+    ),
+    saltLength: 10
+  },
+
+  // [SigVerPSS_186-3.rsp] from
+  // <http://csrc.nist.gov/groups/STM/cavp/documents/dss/186-2rsatestvectors.zip>
+  rsapss5: {
+    spki: util.hex2abv(
+      "30819d300d06092a864886f70d010101050003818b0030818702818100be499b" +
+      "5e7f06c83fa0293e31465c8eb6b58af920bae52a7b5b9bfeb7aa72db1264112e" +
+      "b3fd431d31a2a7e50941566929494a0e891ed5613918b4b51b0d1fb97783b26a" +
+      "cf7d0f384cfb35f4d2824f5dd380623a26bf180b63961c619dcdb20cae406f22" +
+      "f6e276c80a37259490cfeb72c1a71a84f1846d330877ba3e3101ec9c7b020111"
+    ),
+    data: util.hex2abv(
+      "c7f5270fca725f9bd19f519a8d7cca3cc5c079024029f3bae510f9b02140fe23" +
+      "8908e4f6c18f07a89c687c8684669b1f1db2baf9251a3c829faccb493084e16e" +
+      "c9e28d58868074a5d6221667dd6e528d16fe2c9f3db4cfaf6c4dce8c8439af38" +
+      "ceaaaa9ce2ecae7bc8f4a5a55e3bf96df9cd575c4f9cb327951b8cdfe4087168"
+    ),
+    sig: util.hex2abv(
+      "8ffc38f9b820ef6b080fd2ec7de5626c658d79056f3edf610a295b7b0546f73e" +
+      "01ffdf4d0070ebf79c33fd86c2d608be9438b3d420d09535b97cd3d846ecaf8f" +
+      "6551cdf93197e9f8fb048044473ab41a801e9f7fc983c62b324361dade9f71a6" +
+      "5952bd35c59faaa4d6ff462f68a6c4ec0b428aa47336f2178aeb276136563b7d"
+    ),
+    saltLength: 10
+  },
+
   key_wrap_known_answer: {
     key:          util.hex2abv("0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a"),
     wrapping_key: util.hex2abv("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b"),
     wrapping_iv:  util.hex2abv("0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c"),
     wrapped_key:  util.hex2abv("9ed0283a9a2b7e4292ebc5135e6342cc" +
                                "8a7f65802a1f6fd41bd3251c4da0c138")
   },
 
--- a/dom/crypto/test/test_WebCrypto_RSA_PSS.html
+++ b/dom/crypto/test/test_WebCrypto_RSA_PSS.html
@@ -75,61 +75,113 @@ TestArray.addTest(
 );
 
 // -----------------------------------------------------------------------------
 TestArray.addTest(
   "RSA-PSS verify known signature (SHA-1, 1024-bit)",
   function () {
     var that = this;
     var alg = {name: "RSA-PSS", hash: "SHA-1"};
+    var vec = tv.rsapss;
 
     function doVerify(x) {
-      var alg = {name: "RSA-PSS", saltLength: tv.rsapss.salt.byteLength};
-      return crypto.subtle.verify(alg, x, tv.rsapss.sig, tv.rsapss.data);
+      var alg = {name: "RSA-PSS", saltLength: vec.saltLength};
+      return crypto.subtle.verify(alg, x, vec.sig, vec.data);
     }
 
-    crypto.subtle.importKey("spki", tv.rsapss.spki, alg, false, ["verify"])
+    crypto.subtle.importKey("spki", vec.spki, alg, false, ["verify"])
       .then(doVerify, error(that))
       .then(complete(that, x => x), error(that));
   }
 );
 
 // -----------------------------------------------------------------------------
 TestArray.addTest(
+  "Test invalid RSA-PSS signatures",
+  function () {
+    var that = this;
+    var alg = {name: "RSA-PSS", hash: "SHA-1"};
+    var vec = tv.rsapss;
+
+    function doVerify(x) {
+      var alg = {name: "RSA-PSS", saltLength: vec.saltLength};
+      var clone1 = new Uint8Array(vec.data);
+      var clone2 = new Uint8Array(vec.data);
+      clone1[clone1.byteLength - 1] ^= 1;
+      clone2[0] ^= 1;
+
+      return Promise.all([
+        crypto.subtle.verify(alg, x, vec.sig, clone1),
+        crypto.subtle.verify(alg, x, vec.sig, clone2),
+        crypto.subtle.verify(alg, x, vec.sig, vec.data.slice(1)),
+        crypto.subtle.verify(alg, x, vec.sig, vec.data.slice(0, vec.data.byteLength - 1)),
+      ]);
+    }
+
+    crypto.subtle.importKey("spki", vec.spki, alg, false, ["verify"])
+      .then(doVerify, error(that))
+      .then(results => results.every(x => !x))
+      .then(complete(that, x => x), error(that));
+  }
+);
+
+// -----------------------------------------------------------------------------
+TestArray.addTest(
   "RSA-PSS verify known signature (SHA-1, 1024-bit, JWK)",
   function () {
     var that = this;
     var alg = {name: "RSA-PSS", hash: "SHA-1"};
 
     function doVerify(x) {
-      var alg = {name: "RSA-PSS", saltLength: tv.rsapss.salt.byteLength};
+      var alg = {name: "RSA-PSS", saltLength: tv.rsapss.saltLength};
       return crypto.subtle.verify(alg, x, tv.rsapss.sig, tv.rsapss.data);
     }
 
     crypto.subtle.importKey("jwk", tv.rsapss.jwk_pub, alg, false, ["verify"])
       .then(doVerify, error(that))
       .then(complete(that, x => x), error(that));
   }
 );
 
 // -----------------------------------------------------------------------------
 TestArray.addTest(
+  "RSA-PSS verify known signatures (SHA-1 to SHA-512, 1024-bit)",
+  function () {
+    var that = this;
+
+    function verifyCase(hash, tv) {
+      var alg = {name: "RSA-PSS", hash, saltLength: tv.saltLength};
+      return crypto.subtle.importKey("spki", tv.spki, alg, false, ["verify"])
+        .then(x => crypto.subtle.verify(alg, x, tv.sig, tv.data));
+    }
+
+    Promise.all([
+      verifyCase("SHA-1", tv.rsapss2),
+      verifyCase("SHA-256", tv.rsapss3),
+      verifyCase("SHA-384", tv.rsapss4),
+      verifyCase("SHA-512", tv.rsapss5),
+    ]).then(complete(that, x => x.every(y => y)), error(that));
+  }
+);
+
+// -----------------------------------------------------------------------------
+TestArray.addTest(
   "RSA-PSS import SPKI/PKCS#8 keys and sign/verify (SHA-1, 1024-bit)",
   function () {
     var that = this;
     var alg = {name: "RSA-PSS", hash: "SHA-1"};
 
     var privKey, pubKey;
     function setKeys([pub, priv]) { pubKey = pub; privKey = priv; }
     function doSign() {
-      var alg = {name: "RSA-PSS", saltLength: tv.rsapss.salt.byteLength};
+      var alg = {name: "RSA-PSS", saltLength: tv.rsapss.saltLength};
       return crypto.subtle.sign(alg, privKey, tv.rsapss.data);
     }
     function doVerify(x) {
-      var alg = {name: "RSA-PSS", saltLength: tv.rsapss.salt.byteLength};
+      var alg = {name: "RSA-PSS", saltLength: tv.rsapss.saltLength};
       return crypto.subtle.verify(alg, pubKey, x, tv.rsapss.data);
     }
 
     var spki =
       crypto.subtle.importKey("spki", tv.rsapss.spki, alg, false, ["verify"]);
     var pkcs8 =
       crypto.subtle.importKey("pkcs8", tv.rsapss.pkcs8, alg, false, ["sign"]);
 
@@ -146,21 +198,21 @@ TestArray.addTest(
   "RSA-PSS import JWK keys and sign/verify (SHA-1, 1024-bit)",
   function () {
     var that = this;
     var alg = {name: "RSA-PSS", hash: "SHA-1"};
 
     var privKey, pubKey;
     function setKeys([pub, priv]) { pubKey = pub; privKey = priv; }
     function doSign() {
-      var alg = {name: "RSA-PSS", saltLength: tv.rsapss.salt.byteLength};
+      var alg = {name: "RSA-PSS", saltLength: tv.rsapss.saltLength};
       return crypto.subtle.sign(alg, privKey, tv.rsapss.data);
     }
     function doVerify(x) {
-      var alg = {name: "RSA-PSS", saltLength: tv.rsapss.salt.byteLength};
+      var alg = {name: "RSA-PSS", saltLength: tv.rsapss.saltLength};
       return crypto.subtle.verify(alg, pubKey, x, tv.rsapss.data);
     }
 
     var spki =
       crypto.subtle.importKey("jwk", tv.rsapss.jwk_pub, alg, false, ["verify"]);
     var pkcs8 =
       crypto.subtle.importKey("jwk", tv.rsapss.jwk_priv, alg, false, ["sign"]);
 
@@ -266,16 +318,60 @@ TestArray.addTest(
                  x.dp == jwk.dp &&
                  x.dq == jwk.dq &&
                  x.qi == jwk.qi;
           }),
         error(that)
       );
   }
 );
+
+// -----------------------------------------------------------------------------
+TestArray.addTest(
+  "Deterministic RSA-PSS signatures with saltLength=0 (SHA-256, 2048-bit)",
+  function () {
+    var that = this;
+    var alg = {
+      name: "RSA-PSS",
+      hash: "SHA-256",
+      modulusLength: 2048,
+      publicExponent: new Uint8Array([0x01, 0x00, 0x01])
+    };
+
+    var privKey, pubKey;
+    var data = crypto.getRandomValues(new Uint8Array(128));
+    function setKey(x) { pubKey = x.publicKey; privKey = x.privateKey; }
+
+    function doSignTwice() {
+      var alg = {name: "RSA-PSS", saltLength: 0};
+      return Promise.all([
+        crypto.subtle.sign(alg, privKey, data),
+        crypto.subtle.sign(alg, privKey, data)
+      ]);
+    }
+
+    function doVerify(x) {
+      var alg = {name: "RSA-PSS", saltLength: 0};
+      return crypto.subtle.verify(alg, pubKey, x, data);
+    }
+
+    crypto.subtle.generateKey(alg, false, ["sign", "verify"])
+      .then(setKey, error(that))
+      .then(doSignTwice, error(that))
+      .then(([sig1, sig2]) => {
+        if (!util.memcmp(sig1, sig2)) {
+          throw new Error("sig1 must be equal to sig2");
+        }
+
+        return sig1;
+      }, error(that))
+      .then(doVerify, error(that))
+      .then(complete(that, x => x), error(that))
+  }
+);
 /*]]>*/</script>
 </head>
 
 <body>
 
 <div id="content">
 	<div id="head">
 		<b>Web</b>Crypto<br>