Add Web Crypto API tests and Java tests using test vectors (#35)

* Add test vectors

* Add Java tests using test vectors

* Add Web Crypto API tests.
This commit is contained in:
Thanh Bui
2017-07-27 11:12:16 -07:00
committed by Thai Duong
parent 730842ac8c
commit f755ff0279
31 changed files with 14136 additions and 4 deletions
+26
View File
@@ -11,6 +11,7 @@ java_library(
common_deps = [
":utils",
"@gson//:Gson"
]
test_srcs = glob(["java/com/google/security/wycheproof/testcases/*.java"]) + ["java/com/google/security/wycheproof/WycheproofRunner.java"]
@@ -143,3 +144,28 @@ java_test(
srcs = ["java/com/google/security/wycheproof/ProviderIndependentTest.java"] + test_srcs,
deps = common_deps,
)
# Tests using JSON formated test vectors.
testvectors = [
"//testvectors:aes_gcm",
"//testvectors:aes_gcm_siv",
"//testvectors:dsa",
"//testvectors:ecdsa",
"//testvectors:rsa_signature",
]
java_test(
name = "JsonTest",
size = "small",
srcs = ["java/com/google/security/wycheproof/JsonTest.java"] + test_srcs,
data = testvectors,
deps = common_deps,
)
# Load closure rules
load("@io_bazel_rules_closure//closure:defs.bzl", "closure_js_deps")
closure_js_deps(
name = "E2EDeps",
deps = ["@e2e//:E2E"],
)
+15
View File
@@ -0,0 +1,15 @@
load("@io_bazel_rules_closure//closure:defs.bzl", "closure_js_library")
closure_js_library(
name = "E2E",
visibility = ["//visibility:public"],
srcs = glob(
["src/**/*.js"],
exclude = [
"src/**/*test.js",
"src/**/*tester.js",
"src/**/*testdata.js",
"src/**/testing/*.js",
"src/**/testing.js"],
)
)
+5
View File
@@ -0,0 +1,5 @@
java_library(
name = "Gson",
visibility = ["//visibility:public"],
srcs = glob(["gson/src/main/**/*.java"])
)
+22
View File
@@ -162,6 +162,28 @@ learn more about what a failed test means, you might want to check out [our
documentation](doc/bugs.md) or the comments on top of the corresponding test
function and test class.
- To test [Web Cryptography API](https://www.w3.org/TR/WebCryptoAPI/), you first need
to compile [End-to-end](https://github.com/google/end-to-end) because our tests depend on it:
```
bazel build E2EDeps
```
Since Web Cryptography API works on web browsers, you then need to run a simple web server in your local machine by running, for example:
```
python -m SimpleHTTPServer
```
Now assuming that your source code folder's name is "wycheproof", open the web browsers
that you want to test and point it to:
```
http://localhost:8000/bazel-wycheproof/javascript/webcryptoapi/WebCryptoTest.html
```
We have tested Chrome, Firefox, and Microsoft Edge.
### Hall of Bugs
Here are some of the notable vulnerabilities that are uncovered by
+33
View File
@@ -1,3 +1,36 @@
# for javascript
http_archive(
name = "io_bazel_rules_closure",
sha256 = "e9e2538b1f7f27de73fa2914b7d2cb1ce2ac01d1abe8390cfe51fb2558ef8b27",
strip_prefix = "rules_closure-4c559574447f90751f05155faba4f3344668f666",
urls = [
"http://mirror.bazel.build/github.com/bazelbuild/rules_closure/archive/4c559574447f90751f05155faba4f3344668f666.tar.gz",
"https://github.com/bazelbuild/rules_closure/archive/4c559574447f90751f05155faba4f3344668f666.tar.gz", # 2017-06-21
],
)
load("@io_bazel_rules_closure//closure:defs.bzl", "closure_repositories")
closure_repositories()
# Google End-to-end
new_http_archive(
name = "e2e",
strip_prefix = "end-to-end-a77a8cbd13157139437219a8c87a7e133457c2e7",
sha256 = "1c0d3678a649c75254e035985a209b9e292befdec733af0a4ad3842acef271eb",
url = "https://github.com/google/end-to-end/archive/a77a8cbd13157139437219a8c87a7e133457c2e7.zip",
build_file = "//:E2E.BUILD"
)
# Google GSON
new_http_archive(
name = "gson",
strip_prefix = "gson-gson-parent-2.8.1",
sha256 = "5b64446a14ee5b29ab62f1bc0341631c20073e141b724afc410aa66dff6d7f2e",
url = "https://github.com/google/gson/archive/gson-parent-2.8.1.tar.gz",
build_file = "//:Gson.BUILD"
)
maven_jar(
name = "bouncycastle_1_46",
artifact = "org.bouncycastle:bcprov-jdk15on:1.46",
@@ -0,0 +1,26 @@
/**
* @license
* Copyright 2017 Google Inc. All rights reserved.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.security.wycheproof;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
import org.junit.runners.Suite.SuiteClasses;
/** Provider independent tests using the JSON test vectors */
@RunWith(Suite.class)
@SuiteClasses({JsonSignatureTest.class})
public final class JsonTest {}
@@ -114,6 +114,41 @@ public class AesGcmTest extends TestCase {
"1a0293d8f90219058902139013908190bc490890d3ff12a3",
"64069c2d58690561f27ee199e6b479b6369eec688672bde9",
"9b7abadd6e69c1d9ec925786534f5075"),
// GCM uses GHASH to compute the initial counter J0 if the nonce is not 12 bytes long.
// The counter is incremented modulo 2^32 in counter mode. The following test vectors verify
// the behavior of an implementation for initial counter values J0 close to a 2^32 limit.
// J0:00000000000000000000000000000000
new GcmTestVector(
"00000000000000000000000000000000000000000000000000000000000000000000000000000000",
"00112233445566778899aabbccddeeff",
"7b95b8c356810a84711d68150a1b7750",
"",
"84d4c9c08b4f482861e3a9c6c35bc4d91df927374513bfd49f436bd73f325285daef4ff7e13d46a6",
"213a3cb93855d18e69337eee66aeec07"),
// J0:ffffffffffffffffffffffffffffffff
new GcmTestVector(
"00000000000000000000000000000000000000000000000000000000000000000000000000000000",
"00112233445566778899aabbccddeeff",
"1a552e67cdc4dc1a33b824874ebf0bed",
"",
"948ca37a8e6649e88aeffb1c598f3607007702417ea0e0bc3c60ad5a949886de968cf53ea6462aed",
"99b381bfa2af9751c39d1b6e86d1be6a"),
// J0:000102030405060708090a0bffffffff
new GcmTestVector(
"00000000000000000000000000000000000000000000000000000000000000000000000000000000",
"00112233445566778899aabbccddeeff",
"99821c2dd5daecded07300f577f7aff1",
"",
"127af9b39ecdfc57bb11a2847c7c2d3d8f938f40f877e0c4af37d0fe9af033052bd537c4ae978f60",
"07eb2fe4a958f8434d40684899507c7c"),
// J0:000102030405060708090a0bfffffffe
new GcmTestVector(
"00000000000000000000000000000000000000000000000000000000000000000000000000000000",
"00112233445566778899aabbccddeeff",
"5e4a3900142358d1c774d8d124d8d27d",
"",
"0cf6ae47156b14dce03c8a07a2e172b1127af9b39ecdfc57bb11a2847c7c2d3d8f938f40f877e0c4",
"f145c2dcaf339eede427be934357eac0"),
};
/**
@@ -612,7 +647,6 @@ public class AesGcmTest extends TestCase {
* <p>The test is slow as we have to encrypt 2^32 blocks.
*/
// TODO(quannguyen): Is there a faster way to test it?
/*
@ExcludedTest(
providers = {ProviderType.CONSCRYPT},
comment = "Conscrypt doesn't support streaming, would crash")
@@ -637,5 +671,4 @@ public class AesGcmTest extends TestCase {
System.out.println("testWrappedAroundcounter:" + expected.toString());
}
}
*/
}
@@ -253,7 +253,7 @@ public class DhTest extends TestCase {
BigInteger p = priv.getParams().getP();
BigInteger g = priv.getParams().getG();
int keySize = p.bitLength();
assertEquals("wrong key size", keySize, expectedKeySize);
assertEquals("wrong key size", expectedKeySize, keySize);
// Checks the key size of the private key.
// NIST SP 800-56A requires that x is in the range (1, q-1).
@@ -322,6 +322,7 @@ public class DhTest extends TestCase {
* for each new key.
*/
@SuppressWarnings("InsecureCryptoUsage")
@SlowTest(providers = {ProviderType.BOUNCY_CASTLE, ProviderType.SPONGY_CASTLE})
public void testKeyPairGenerator() throws Exception {
int keySize = 1024;
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("DH");
@@ -0,0 +1,220 @@
/**
* @license
* Copyright 2017 Google Inc. All rights reserved.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.security.wycheproof;
import static java.nio.charset.StandardCharsets.UTF_8;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.google.gson.stream.JsonReader;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.math.BigInteger;
import java.security.KeyFactory;
import java.security.PublicKey;
import java.security.Signature;
import java.security.SignatureException;
import java.security.spec.X509EncodedKeySpec;
import junit.framework.TestCase;
/**
* This test uses test vectors in JSON format to check digital signature schemes.
* There are still a lot of open questions, e.g. the format for the test vectors is not
* yet finalized. Therefore, we are not integrating the tests here into other tests
*/
public class JsonSignatureTest extends TestCase {
static protected String getString(JsonObject object, String name) throws Exception {
return object.get(name).getAsString();
}
/**
* Wycheproof represents BigIntegers as hexadecimal strings, using bigendian order and
* twos complement representation.
*/
static protected BigInteger getBigInteger(JsonObject object, String name) throws Exception {
String hex = getString(object, name);
byte[] bytes = TestUtil.hexToBytes(hex);
return new BigInteger(bytes);
}
/**
* Wycheproof represents byte arrays as hexadeciamal strings.
*/
static protected byte[] getBytes(JsonObject object, String name) throws Exception {
String hex = getString(object, name);
return TestUtil.hexToBytes(hex);
}
/**
* Returns the algorithm name for a digital signature algorithm with a given message digest. The
* algorithm names used in JCA are a bit inconsequential. E.g. a dash is necessary for message
* digests (e.g. "SHA-256") but are not used in the corresponding names for digital signatures
* (e.g. "SHA256WITHECDSA").
*
* <p>See http://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html
*
* @param md the name of the message digest (e.g. "SHA-256")
* @param signatureAlgorithm the name of the signature algorithm (e.g. "ECDSA")
* @return the algorithm name for the signature scheme with the given hash.
*/
protected static String getAlgorithmName(String md, String signatureAlgorithm) {
if (md.equals("SHA-1")) {
md = "SHA1";
} else if (md.equals("SHA-224")) {
md = "SHA224";
} else if (md.equals("SHA-256")) {
md = "SHA256";
} else if (md.equals("SHA-384")) {
md = "SHA384";
} else if (md.equals("SHA-512")) {
md = "SHA512";
}
return md + "WITH" + signatureAlgorithm;
}
/**
* object should contain the key in multiple formats:
* "key" : elements of the public key
* "keyDer": the key in ASN encoding encoded hexadecimal
* "keyPem": the key in Pem format encoded hexadecimal
* The test can use the format that is most convenient.
*/
// This is a false positive, since errorprone cannot track values passed into a method.
@SuppressWarnings("InsecureCryptoUsage")
static protected PublicKey getPublicKey(JsonObject object, String algorithm) throws Exception {
KeyFactory kf;
if (algorithm.equals("ECDSA")) {
kf = KeyFactory.getInstance("EC");
} else {
kf = KeyFactory.getInstance(algorithm);
}
byte[] encoded = TestUtil.hexToBytes(getString(object, "keyDer"));
X509EncodedKeySpec x509keySpec = new X509EncodedKeySpec(encoded);
return kf.generatePublic(x509keySpec);
}
/** Example format for test vectors
* {
* "algorithm": "ECDSA",
* "generatorVersion": "0.0a10",
* "numberOfTests": 217,
* "testGroups": [
* {
* "key": {
* "curve": "secp256r1",
* "type": "ECPublicKey",
* "wx": "0c9c4bc2617c81eb2dcbfda2db2a370a955be86a0d2e95fcb86a99f90cf046573",
* "wy": "0c400363b1b6bcc3595a7d6d3575ccebcbb03f90ba8e58da2bc4824272f4fecff"
* },
* "keyDer": <X509encoded key>
* "keyPem": "-----BEGIN PUBLIC KEY-----\ ... \n-----END PUBLIC KEY-----",
* "sha": "SHA-256",
* "tests": [
* {
* "comment": "random signature",
* "message": "48656c6c6f",
* "result": "valid",
* "sig": "...",
* "tcId": 1
* },
* ...
**/
public void testVectors(JsonObject test, String signatureAlgorithm) throws Exception {
// This test expects that the version in the test vectors and the version here match
// exactly, since the formats have not yet been fixed.
final String expectedVersion = "0.0a10";
String generatorVersion = getString(test, "generatorVersion");
assertEquals(expectedVersion, generatorVersion);
int numTests = test.get("numberOfTests").getAsInt();
int cntTests = 0;
int errors = 0;
for (JsonElement g : test.getAsJsonArray("testGroups")) {
JsonObject group = g.getAsJsonObject();
PublicKey key = getPublicKey(group, signatureAlgorithm);
String md = getString(group, "sha");
String algorithm = getAlgorithmName(md, signatureAlgorithm);
Signature verifier = Signature.getInstance(algorithm);
for (JsonElement t : group.getAsJsonArray("tests")) {
cntTests++;
JsonObject testcase = t.getAsJsonObject();
byte[] message = getBytes(testcase, "message");
byte[] signature = getBytes(testcase, "sig");
int tcid = testcase.get("tcId").getAsInt();
String sig = TestUtil.bytesToHex(signature);
String result = getString(testcase, "result");
verifier.initVerify(key);
verifier.update(message);
boolean verified = false;
try {
verified = verifier.verify(signature);
} catch (SignatureException ex) {
// verify can throw SignatureExceptions if the signature is malformed.
// We don't flag these cases and simply consider the signature as invalid.
verified = false;
} catch (java.lang.ArithmeticException ex) {
// b/33446454 The Sun provider may throw an ArithmeticException instead of
// the expected SignatureException for DSA signatures.
// We should eventually remove this.
verified = false;
} catch (Exception ex) {
// Other exceptions (i.e. unchecked exceptions) are considered as error
// since a third party should never be able to cause such exceptions.
System.out.println(signatureAlgorithm + " signature throws " + ex.toString()
+ " tcId:" + tcid + " sig:" + sig);
verified = false;
errors++;
}
if (!verified && result.equals("valid")) {
System.out.println("Valid " + signatureAlgorithm + " signature not verified."
+ " tcId:" + tcid + " sig:" + sig);
errors++;
} else if (verified && result.equals("invalid")) {
System.out.println("Invalid" + signatureAlgorithm + " signature verified."
+ " tcId:" + tcid + " sig:" + sig);
errors++;
}
}
}
assertEquals(0, errors);
assertEquals(numTests, cntTests);
}
public JsonObject getJsonObjectFromFile(String filename) throws Exception {
FileInputStream is = new FileInputStream(filename);
JsonReader reader = new JsonReader(new InputStreamReader(is, UTF_8));
JsonParser parser = new JsonParser();
JsonElement elem = parser.parse(reader);
return elem.getAsJsonObject();
}
public void testSignatureScheme(String filename, String algorithm) throws Exception {
// TODO(bleichen): This (likely) will not work when published.
String TEST_VECTORS = "third_party/wycheproof/testvectors/";
JsonObject tests = getJsonObjectFromFile(TEST_VECTORS + filename);
testVectors(tests, algorithm);
}
public void testEcdsa() throws Exception {
testSignatureScheme("ecdsa_test.json", "ECDSA");
}
public void testRsaSignatures() throws Exception {
testSignatureScheme("rsa_signature_test.json", "RSA");
}
}
@@ -1430,7 +1430,7 @@ public class RsaKeyTest extends TestCase {
assertEquals(pub.getModulus(), priv.getModulus());
BigInteger e = pub.getPublicExponent();
// Checks that e > 1. [CVE-1999-1444]
assertEquals(e.compareTo(BigInteger.ONE), 1);
assertEquals(1, e.compareTo(BigInteger.ONE));
}
private void checkKeyPair(KeyPair keypair, int keySizeInBits) throws Exception {
+112
View File
@@ -0,0 +1,112 @@
/**
* @license
* Copyright 2017 Google Inc. All rights reserved.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @fileoverview Defines interfaces for big numbers.
* All arithmetic operations are inherits from e2e.BigNum.
*/
goog.provide('wycheproof.BigInteger');
goog.provide('wycheproof.BigPrimeInteger');
goog.require('e2e.BigNum');
goog.require('e2e.BigPrimeNum');
goog.require('goog.crypt');
goog.require('goog.crypt.base64');
goog.require('goog.testing.asserts');
goog.require('wycheproof.TestUtil');
var TestUtil = wycheproof.TestUtil;
/**
* Non-negative arbitrary-precision integers.
* @param {(!Array<Byte>|!Uint8Array)=} optValue
* The value of the BigInteger in big endian.
* @constructor
* @extends {e2e.BigNum}
*/
wycheproof.BigInteger = function(optValue) {
wycheproof.BigInteger.base(this, 'constructor', optValue);
};
goog.inherits(wycheproof.BigInteger, e2e.BigNum);
/**
* A factory method to create a BigInteger from a string that is
* in big-endian, two's complement and hex representation.
* @param {!string} s The string representation of the BigInteger
*
* @return {!BigInteger}
*/
wycheproof.BigInteger.fromHex = function(s) {
assertTrue('Input is not a hex string', TestUtil.isHex(s));
if (s.length % 2 == 1) {
s = '0' + s;
}
var bytes = goog.crypt.hexToByteArray(s);
var bigInt = new wycheproof.BigInteger(bytes);
return bigInt.dropLeadingZeros();
};
/**
* Converts this to a big-endian Base64URL string.
* @param {!number} optValue An optional value that specifies the length in
* bytes of the result. If it is bigger than the original length of this number,
* zeros are added to its beginning.
*
* @return {!string}
*/
wycheproof.BigInteger.prototype.toBase64Url = function(optValue) {
var bytes = this.toByteArray();
if (goog.isDef(optValue) && optValue > bytes.length) {
var addingZeros = new Array(optValue-bytes.length).fill(0);
bytes = addingZeros.concat(bytes);
}
var b64Str = goog.crypt.base64.encodeByteArray(bytes);
return TestUtil.base64ToBase64Url(b64Str);
};
/**
* Converts this to an ArrayBuffer of big-endian bytes
* @param {!number} optValue An optional value that specifies the length in
* bytes of the result. If it is bigger than the original length of this number,
* zeros are added to its beginning.
*
* @return {!ArrayBuffer}
*/
wycheproof.BigInteger.prototype.toArrayBuffer = function(optValue) {
var bytes = this.toByteArray();
if (goog.isDef(optValue) && optValue > bytes.length) {
var addingZeros = new Array(optValue-bytes.length).fill(0);
bytes = addingZeros.concat(bytes);
}
return new Uint8Array(bytes).buffer;
};
/**
* Odd prime big integer that could be use as the modulus in modular arithmetic
* operations in crypto schemes such as ECDSA or ECDH.
* @param {!Array<Byte>|!Uint8Array} modulus The modulus to use.
* @constructor
* @extends {e2e.BigPrimeNum}
*/
wycheproof.BigPrimeInteger = function(modulus) {
wycheproof.BigPrimeInteger.base(this, 'constructor', modulus);
};
goog.inherits(wycheproof.BigPrimeInteger, e2e.BigPrimeNum);
+123
View File
@@ -0,0 +1,123 @@
/**
* @license
* Copyright 2017 Google Inc. All rights reserved.
* Licensed under the Apache License, Version 2.0 (the 'License');
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an 'AS IS' BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* Some utilities for testing Elliptic curve crypto.
*
*/
goog.provide('wycheproof.EcUtil');
goog.require('wycheproof.BigInteger');
goog.require('wycheproof.BigPrimeInteger');
var BigInteger = wycheproof.BigInteger;
var BigPrimeInteger = wycheproof.BigPrimeInteger;
/**
* Parameters of a NIST-recommended curve.
* @param {!number} keySize The bit length of the order n
* @param {!string} hexP The prime modulus p in hex format
* @param {!string} hexN The order n in hex format
* @param {!string} hexB The coefficient b in hex format
* @param {!string} hexGX The x-coordinate of the public curve point
* @param {!string} hexGY The y-coordinate of the public curve point
*/
var NistCurveSpec = function(keySize, hexP, hexN, hexB, hexGX, hexGY) {
this.keySize = keySize;
this.p = new BigPrimeInteger(BigInteger.fromHex(hexP).toByteArray());
this.n = new BigPrimeInteger(BigInteger.fromHex(hexN).toByteArray());
this.b = BigInteger.fromHex(hexB);
this.gx = BigInteger.fromHex(hexGX);
this.gy = BigInteger.fromHex(hexGY);
};
/**
* Returns the NIST's recommended parameters of the given curve.
* @param {!string} name The curve name
*
* @return {NistCurveSpec}
*/
wycheproof.EcUtil.getCurveSpec = function(name) {
switch (name) {
case 'P-256':
return wycheproof.EcUtil.getNistP256Params();
case 'P-384':
return wycheproof.EcUtil.getNistP384Params();
case 'P-521':
return wycheproof.EcUtil.getNistP521Params();
default:
throw 'Curve not implemented:' + name;
}
};
/**
* Returns the NIST's recommended parameters of the secp256r1 curve.
*
* @return {NistCurveSpec}
*/
wycheproof.EcUtil.getNistP256Params = function() {
return new NistCurveSpec(
256,
'ffffffff00000001000000000000000000000000ffffffffffffffffffffffff',
'ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551',
'5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b',
'6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296',
'4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5');
};
/**
* Returns the NIST's recommended parameters of the secp384r1 curve.
*
* @return {NistCurveSpec}
*/
wycheproof.EcUtil.getNistP384Params = function() {
return new NistCurveSpec(
384,
'fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'
+ 'ffeffffffff0000000000000000ffffffff',
'ffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372'
+ 'ddf581a0db248b0a77aecec196accc52973',
'b3312fa7e23ee7e4988e056be3f82d19181d9c6efe8141120314088f5013875a'
+ 'c656398d8a2ed19d2a85c8edd3ec2aef',
'aa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a38'
+ '5502f25dbf55296c3a545e3872760ab7',
'3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c0'
+ '0a60b1ce1d7e819d7a431d7c90ea0e5f');
};
/**
* Returns the NIST's recommended parameters of the secp521r1 curve.
*
* @return {NistCurveSpec}
*/
wycheproof.EcUtil.getNistP521Params = function() {
return new NistCurveSpec(
521,
'1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'
+ 'fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff',
'1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'
+ 'a51868783bf2f966b7fcc0148f709a5d03bb5c9b8899c47aebb6fb71e91386409',
'051953eb9618e1c9a1f929a21a0b68540eea2da725b99b315f3b8b489918ef10'
+ '9e156193951ec7e937b1652c0bd3bb1bf073573df883d2c34f1ef451fd46b503f00',
'c6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d3d'
+ 'baa14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66',
'11839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e6'
+ '62c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650');
};
+140
View File
@@ -0,0 +1,140 @@
/**
* @license
* Copyright 2017 Google Inc. All rights reserved.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* Some utilities for all Javascript tests.
*/
goog.provide('wycheproof.TestUtil');
goog.require('goog.crypt');
goog.require('goog.crypt.base64');
goog.require('goog.json');
/**
* Reads test vectors in JSON format from a file.
* @param {!string} filename
*
* @return {!JSONObject}
*/
wycheproof.TestUtil.readJsonTestVectorsFromFile = function(filename){
var fileContent = goog.loadFileSync_(filename);
assertTrue('Invalid file format (expected JSON)', goog.json.isValid(fileContent));
return goog.json.parse(fileContent);
};
/**
* Analyzes the result from a goog.testing.TestCase execution.
*
* @param {!goog.testing.TestCase.Result} result
*/
wycheproof.TestUtil.checkTestCaseResult = function(result) {
var failMsg = '';
if (result.errors.length > 0) {
for (var i = 0; i < result.errors.length; i++) {
failMsg += result.errors[i].message + '\n';
}
fail(failMsg);
}
};
/**
* Checks whether the given string is in hex format.
* @param {!string} s
*
* @return {!boolean}
*/
wycheproof.TestUtil.isHex = function(s) {
return /(^[0-9A-F]*$)|(^[0-9a-f]*$)/.test(s);
};
/**
* Converts a hex string to a ArrayBuffer.
* @param {!string} s
*
* @return {!ArrayBuffer}
*/
wycheproof.TestUtil.hexToArrayBuffer = function(s) {
var bytes = goog.crypt.hexToByteArray(s);
return new Uint8Array(bytes).buffer;
};
/**
* Converts an ArrayBuffer to hex string
* @param {!ArrayBuffer} ab
*
* @return {!string}
*/
wycheproof.TestUtil.arrayBufferToHex = function(ab) {
return goog.crypt.byteArrayToHex(new Uint8Array(ab));
};
/**
* Converts a Base64URL string to hex format
* @param {!string} s
*
* @return {!string}
*/
wycheproof.TestUtil.base64UrlToHex = function (s) {
var b64str = wycheproof.TestUtil.base64UrlToBase64(s);
return wycheproof.TestUtil.base64ToHex(b64str);
};
/**
* Converts a hex string to Base64 format.
* @param {!string} s
*
* @return {!string}
*/
wycheproof.TestUtil.hexToBase64 = function(s) {
var bytes = goog.crypt.hexToByteArray(s);
return goog.crypt.base64.encodeByteArray(bytes);
};
/**
* Converts a base64 string to hex format.
* @param {!string} s
*
* @return {!string}
*/
wycheproof.TestUtil.base64ToHex = function(s) {
var bytes = goog.crypt.base64.decodeStringToByteArray(s);
return goog.crypt.byteArrayToHex(bytes);
};
/**
* Converts a Base64 string to Base64URL
* @param {!string} s
*
* @return {!string}
*/
wycheproof.TestUtil.base64ToBase64Url = function(s) {
return s.replace(/\+/g, '-')
.replace(/\//g, '_')
.replace(/=/g, '');
};
/**
* Converts a Base64Url string to Base64
* @param {!string} s
*
* @return {!string}
*/
wycheproof.TestUtil.base64UrlToBase64 = function(s) {
return (s + '==='.slice((s.length + 3) % 4))
.replace(/\-/g, '+')
.replace(/_/g, '/');
};
+39
View File
@@ -0,0 +1,39 @@
/**
* @license
* Copyright 2017 Google Inc. All rights reserved.
* Licensed under the Apache License, Version 2.0 (the 'License');
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an 'AS IS' BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @fileoverview Utilities for hash operations
*/
goog.provide('wycheproof.webcryptoapi.HashUtil');
// Hash function names
wycheproof.webcryptoapi.HashUtil.SHA256 = 'SHA-256';
wycheproof.webcryptoapi.HashUtil.SHA384 = 'SHA-384';
wycheproof.webcryptoapi.HashUtil.SHA512 = 'SHA-512';
wycheproof.webcryptoapi.HashUtil.SHA1 = 'SHA-1';
/**
* Calculates a hash of the given message using the given hash algorithm.
* @param {!string} hashAlg The hash algorithm
* @param {!ArrayBuffer} msg The message to be hashed
*
* @return {!Promise}
*/
wycheproof.webcryptoapi.HashUtil.digest = function(hashAlg, msg) {
return window.crypto.subtle.digest(hashAlg, msg);
};
+172
View File
@@ -0,0 +1,172 @@
/**
* @license
* Copyright 2017 Google Inc. All rights reserved.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* Some utilities for testing RSA on Web Crypto APIs
*/
goog.provide('wycheproof.webcryptoapi.RsaUtil');
goog.require('goog.testing.asserts');
goog.require('wycheproof.webcryptoapi.HashUtil');
var HashUtil = wycheproof.webcryptoapi.HashUtil;
// algorithm names
wycheproof.webcryptoapi.RsaUtil.RSASSA_PKCS1 = 'RSASSA-PKCS1-v1_5';
wycheproof.webcryptoapi.RsaUtil.RSA_OAEP = 'RSA-OAEP';
// public exponents
wycheproof.webcryptoapi.RsaUtil.E_65537 = new Uint8Array([0x01, 0x00, 0x01]);
wycheproof.webcryptoapi.RsaUtil.E_3 = new Uint8Array([0x03]);
/**
* Imports a RSA public key.
* @param {!string} e RSA public exponent in base64url format
* @param {!string} n RSA modulus in base64url format
* @param {!string} schemeName The usage scheme.
* Supported values are "RSASSA-PKCS1-v1_5", "RSA-PSS".
* @param {!string} hashAlg The hash algorithm used for the scheme.
* Supported values are "SHA-1", "SHA-256", "SHA-384", and "SHA-512".
* @param {!Array<string>} usages An Array indicating what can be done with the key.
*
* @return {!Promise} A Promise object containing the public key
*/
wycheproof.webcryptoapi.RsaUtil.importPublicKey =
function(e, n, schemeName, hashAlg, usages) {
return window.crypto.subtle.importKey(
'jwk', {
kty: 'RSA',
e: e,
n: n,
ext: true,
}, {
name: schemeName,
hash: {name: hashAlg},
},
false,
usages
);
};
/**
* Verifies a RSA signature using the given public key.
* @param {!CryptoKey} pk The public key object
* @param {!ArrayBuffer} msg
* The message that was signed by the corresponding private key, in
* @param {!ArrayBuffer} sig
* The signature to be verified
* @param {!string} hashAlg The hash algorithm
* @param {!string} schemeName The signature scheme
*
* @return {!Promise} A Promise object containing the verification result.
*/
wycheproof.webcryptoapi.RsaUtil.verify = function(pk, msg, sig, hashAlg, schemeName) {
return window.crypto.subtle.verify(
{
name: schemeName,
hash: hashAlg
},
pk,
sig,
msg
);
};
/**
* Generates a new RSA key pair.
* @param {!string} schemeName The algorithm scheme
* @param {number} keySize The key size in bits
* @param {!ArrayBuffer} e The public exponent
* @param {!string} hashAlg The hash algorithm
* @param {!Array<string>} usages The usages of the key
*
* @return {!Promise} A promise containing the new key pair.
*/
wycheproof.webcryptoapi.RsaUtil.generateKey
= function(schemeName, keySize, e, hashAlg, usages) {
return window.crypto.subtle.generateKey(
{
name: schemeName,
modulusLength: keySize,
publicExponent: e,
hash: {name: hashAlg},
},
true,
usages
);
};
/**
* Decrypts the given ciphertext.
* @param {!string} schemeName The algorithm scheme
* @param {!CryptoKey} sk The private key that will be used for decryption
* @param {!string} ct The ciphertext to be decrypted
*
* @return {!Promise} A promise containing the decrypted text.
*/
wycheproof.webcryptoapi.RsaUtil.decrypt = function(schemeName, sk, ct) {
return window.crypto.subtle.decrypt({name: schemeName}, sk, ct);
};
/**
* A class containing RSA signature test case's parameters
* @param {!number} id
* @param {!string} e RSA public exponent in base64url format
* @param {!string} n RSA modulus in base64url format
* @param {!string} hashAlg The hash algorithm used for the scheme.
* @param {!string} scheme The usage scheme.
* @param {!ArrayBuffer} msg The message to be verified
* @param {!ArrayBuffer} sig The signature to be verified
* @param {!string} result The test result
*/
wycheproof.webcryptoapi.RsaUtil.RsaSignatureTestCase
= function(id, e, n, hashAlg, scheme, msg, sig, result) {
this.id = id;
this.e = e;
this.n = n;
this.hashAlg = hashAlg;
this.scheme = scheme;
this.msg = msg;
this.sig = sig;
this.result = result;
};
/**
* Tests RSA signature verification.
*
* @return {!Promise}
*/
wycheproof.webcryptoapi.RsaUtil.testVerification = function() {
var tc = this;
var promise = new Promise(function(resolve, reject){
RsaUtil.importPublicKey(tc.e, tc.n, tc.scheme, tc.hashAlg, ['verify'])
.then(function(pk){
wycheproof.webcryptoapi.RsaUtil.verify(pk, tc.msg, tc.sig,
tc.hashAlg, tc.scheme).then(function(isValid){
if ((tc.result == 'valid' && !isValid) ||
(tc.result == 'invalid' && isValid)) {
reject('Failed on test case ' + tc.id);
}
resolve();
}).catch(function(err){
// don't expect any exception in signature verification
reject('Unexpected exception on test case ' + tc.id + ": " + err);
});
}).catch(function(err){
reject('Failed to import public key in test case ' + tc.id + ': ' + err);
});
});
return promise;
};
+13
View File
@@ -0,0 +1,13 @@
// This file was autogenerated by depswriter.py.
// Please do not edit.
goog.addDependency('../../../../javascript/BigInteger.js', ['wycheproof.BigInteger', 'wycheproof.BigPrimeInteger'], ['e2e.BigNum', 'e2e.BigPrimeNum', 'goog.crypt', 'goog.crypt.base64', 'goog.testing.asserts', 'wycheproof.TestUtil'], false);
goog.addDependency('../../../../javascript/EcUtil.js', ['wycheproof.EcUtil'], ['wycheproof.BigInteger', 'wycheproof.BigPrimeInteger'], false);
goog.addDependency('../../../../javascript/TestUtil.js', ['wycheproof.TestUtil'], ['goog.crypt', 'goog.crypt.base64', 'goog.json'], false);
goog.addDependency('../../../../javascript/webcryptoapi/HashUtil.js', ['wycheproof.webcryptoapi.HashUtil'], [], false);
goog.addDependency('../../../../javascript/webcryptoapi/RsaUtil.js', ['wycheproof.webcryptoapi.RsaUtil'], ['goog.testing.asserts', 'wycheproof.webcryptoapi.HashUtil'], false);
goog.addDependency('../../../../javascript/webcryptoapi/WebCryptoTest.js', ['wycheproof.webcryptoapi'], ['goog.testing.TestCase', 'goog.userAgent.product'], false);
goog.addDependency('../../../../javascript/webcryptoapi/testcases/AesGcmTest.js', ['wycheproof.webcryptoapi.AES-GCM'], ['goog.testing.TestCase', 'goog.testing.asserts', 'goog.testing.jsunit', 'goog.userAgent.product', 'wycheproof.BigInteger', 'wycheproof.TestUtil'], false);
goog.addDependency('../../../../javascript/webcryptoapi/testcases/EcdhTest.js', ['wycheproof.webcryptoapi.ECDH'], ['goog.testing.TestCase', 'goog.testing.asserts', 'goog.testing.jsunit', 'wycheproof.BigInteger', 'wycheproof.TestUtil', 'wycheproof.webcryptoapi.RsaUtil'], false);
goog.addDependency('../../../../javascript/webcryptoapi/testcases/EcdsaTest.js', ['wycheproof.webcryptoapi.ECDSA'], ['e2e.ecc.Ecdsa', 'goog.testing.TestCase', 'goog.testing.asserts', 'goog.testing.jsunit', 'wycheproof.BigInteger', 'wycheproof.EcUtil', 'wycheproof.TestUtil', 'wycheproof.webcryptoapi.HashUtil'], false);
goog.addDependency('../../../../javascript/webcryptoapi/testcases/RsaOaedTest.js', ['wycheproof.webcryptoapi.RSA-OAED'], ['e2e.random', 'goog.testing.asserts', 'goog.testing.jsunit', 'wycheproof.TestUtil', 'wycheproof.webcryptoapi.RsaUtil'], false);
goog.addDependency('../../../../javascript/webcryptoapi/testcases/RsaSsaPkcs1Test.js', ['wycheproof.webcryptoapi.RSASSA-PKCS1-V1_5'], ['goog.testing.TestCase', 'goog.testing.asserts', 'goog.testing.jsunit', 'wycheproof.BigInteger', 'wycheproof.TestUtil', 'wycheproof.webcryptoapi.HashUtil', 'wycheproof.webcryptoapi.RsaUtil'], false);
@@ -0,0 +1,37 @@
<!-- Copyright 2017 Google Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// -->
<!DOCTYPE html>
<title>Unit Tests of Web Crypto API</title>
<script src="../../external/com_google_javascript_closure_library/closure/goog/base.js"></script>
<script src="../../../bazel-bin/E2EDeps.js"></script>
<!-- This file is generated with depswriter:
https://developers.google.com/closure/library/docs/depswriter
It needs to be updated whenever there are changes. -->
<script src="WebCryptoDeps.js"></script>
<script>
goog.require('wycheproof.webcryptoapi');
goog.require('wycheproof.webcryptoapi.AES-GCM');
goog.require('wycheproof.webcryptoapi.ECDSA');
goog.require('wycheproof.webcryptoapi.ECDH');
goog.require('wycheproof.webcryptoapi.RSA-OAED');
goog.require('wycheproof.webcryptoapi.RSASSA-PKCS1-V1_5');
</script>
<script>
function setUpPage(){
wycheproof.webcryptoapi.setupAllTests();
}
</script>
+92
View File
@@ -0,0 +1,92 @@
/**
* @license
* Copyright 2017 Google Inc. All rights reserved.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @fileoverview Tests for Web Crypto API
*/
goog.provide('wycheproof.webcryptoapi');
goog.require('goog.testing.TestCase');
goog.require('goog.userAgent.product');
const TEST_TIMEOUT = 120*1000;
// A dictionary containing the parameters that are supported by the current browser
var SUPPORTED;
// Parameters that are supported by Microsoft Edge
const EDGE_SUPPORTED = {
'aesgcm-key-size': [128, 192, 256],
'ecdsa-curve': ['P-256', 'P-384', 'P-521'],
'hash': ['SHA-256', 'SHA-384', 'SHA-512']
};
// Parameters that are supported by Chrome
const CHROME_SUPPORTED = {
'aesgcm-key-size': [128, 256],
'ecdsa-curve': ['P-256', 'P-384', 'P-521'],
'hash': ['SHA-1', 'SHA-256', 'SHA-384', 'SHA-512']
};
// Parameters that are supported by Firefox
const FIREFOX_SUPPORTED = {
'aesgcm-key-size': [128, 192, 256],
'ecdsa-curve': ['P-256', 'P-384', 'P-521'],
'hash': ['SHA-1', 'SHA-256', 'SHA-384', 'SHA-512']
};
// Test names
const TEST_AES_GCM_VECTORS = 'testAesGcmVectors';
const TEST_ECDSA_VECTORS = 'testEcdsaVectors';
const TEST_ECDSA_BIAS = 'testEcdsaBiasAll';
const TEST_RSASSAPKCS1_VECTORS = 'testRsaSsaPkcs1Vectors';
const TEST_RSA_ENCRYPT = 'testRsaEncryptionException';
const TEST_ECDH_VECTORS = 'testEcdhVectors';
// Tests to run
var TESTS_ALL = {};
TESTS_ALL[TEST_AES_GCM_VECTORS] = true;
TESTS_ALL[TEST_ECDSA_VECTORS] = true;
TESTS_ALL[TEST_ECDSA_BIAS] = true;
TESTS_ALL[TEST_RSASSAPKCS1_VECTORS] = true;
TESTS_ALL[TEST_RSA_ENCRYPT] = true;
TESTS_ALL[TEST_ECDH_VECTORS] = true;
// Tests to run on Chrome
var TESTS_TO_RUN_CHROME = goog.cloneObject(TESTS_ALL);
// Tests to run on Firefox
var TESTS_TO_RUN_FIREFOX = goog.cloneObject(TESTS_ALL);
// Tests to run on MS Edge.
// MS Edge doesn't support ECDSA and ECDH
var TESTS_TO_RUN_EDGE = goog.cloneObject(TESTS_ALL);
TESTS_TO_RUN_EDGE[TEST_ECDSA_VECTORS] = false;
TESTS_TO_RUN_EDGE[TEST_ECDSA_BIAS] = false;
TESTS_TO_RUN_EDGE[TEST_ECDH_VECTORS] = false;
/**
* Runs all tests.
*/
wycheproof.webcryptoapi.setupAllTests = function() {
var testCase = goog.testing.TestCase.getActiveTestCase();
testCase.promiseTimeout = TEST_TIMEOUT;
if (goog.userAgent.product.CHROME) {
testCase.setTestsToRun(TESTS_TO_RUN_CHROME);
SUPPORTED = CHROME_SUPPORTED;
} else if (goog.userAgent.product.FIREFOX) {
testCase.setTestsToRun(TESTS_TO_RUN_FIREFOX);
SUPPORTED = FIREFOX_SUPPORTED;
} else if (goog.userAgent.product.EDGE) {
testCase.setTestsToRun(TESTS_TO_RUN_EDGE);
SUPPORTED = EDGE_SUPPORTED;
}
};
@@ -0,0 +1,211 @@
/**
* @license
* Copyright 2017 Google Inc. All rights reserved.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* Tests for AES-GCM implementations of Web Crypto API.
*/
goog.provide('wycheproof.webcryptoapi.AES-GCM');
goog.require('goog.testing.TestCase');
goog.require('goog.testing.asserts');
goog.require('goog.testing.jsunit');
goog.require('goog.userAgent.product');
goog.require('wycheproof.BigInteger');
goog.require('wycheproof.TestUtil');
var TestUtil = wycheproof.TestUtil;
var BigInteger = wycheproof.BigInteger;
// Test vector file
var AES_GCM_VECTOR_FILE = '../../testvectors/aes_gcm_test.json';
/**
* A class containing a AES-GCM test case's parameters.
* @param {!number} id Identifier of the test case
* @param {!string} k The key in Base64URL format
* @param {!number} keySize The key's size in bits
* @param {!string} tag The expected tag of the encryption in hex format
* @param {!number} tagSize The tag size in bits
* @param {!ArrayBuffer} iv The initialization vector
* @param {!number} ivSize The iv's size in bits
* @param {!ArrayBuffer} aad The additional authentication data
* @param {!ArrayBuffer} msg The message to be encrypted
* @param {!string} ct The expected ciphertext of the encryption in hex format
* @param {!string} result The expected result of the test
*/
var AesGcmTestCase = function(id, k, keySize, tag, tagSize, iv, ivSize,
aad, msg, ct, result) {
this.id = id;
this.k = k;
this.keySize = keySize;
this.tag = tag;
this.tagSize = tagSize;
this.iv = iv;
this.ivSize = ivSize;
this.aad = aad;
this.msg = msg;
this.ct = ct;
this.result = result;
};
/** AES-GCM wrapper */
var AesGcm = function() {};
/**
* Returns the AES-GCM algorithm name that is accepted by WebCrypto APIs.
* @param {!number} keySize The key's size
*
* @return {!string} The algorithm's name
*/
AesGcm.getAlgName = function(keySize) {
return 'A' + keySize + 'GCM';
};
/**
* Imports a AES-GCM key.
* @param {!string} k The key in Base64URL format
* @param {!number} keySize The key's size in bits
*
* @return {!Promise} A Promise containing the imported key
*/
AesGcm.importKey = function(k, keySize) {
return window.crypto.subtle.importKey(
"jwk",
{
kty: 'oct',
k: k,
alg: AesGcm.getAlgName(keySize),
ext: true,
}, {
name: 'AES-GCM',
},
true,
["encrypt", "decrypt"]
);
};
/**
* Performs AES-GCM encryption.
* @param {!CryptoKey} key The key that is used for encryption
* @param {!ArrayBuffer} aad The additional authentication data
* @param {!ArrayBuffer} msg The message to be encrypted
* @param {!ArrayBuffer} iv The initialization vector
* @param {number} tagSize The tag size in bits
*
* @return {!Promise} A Promise containing the ciphetext
*/
AesGcm.encrypt = function(key, aad, msg, iv, tagSize) {
var alg = {
name: 'AES-GCM',
iv: iv,
tagLength: tagSize
};
if (aad.byteLength > 0) {
alg.additionalData = aad;
}
return window.crypto.subtle.encrypt(alg, key, msg);
};
/**
* Tests AES-GCM encryption.
*
* @return {!Promise}
*/
AesGcm.testEncrypt = function() {
var tc = this;
var promise = new Promise(function(resolve, reject) {
AesGcm.importKey(tc.k, tc.keySize).then(function(key){
AesGcm.encrypt(key, tc.aad, tc.msg, tc.iv, tc.tagSize)
.then(function(ct){
// Fail if the iv is empty and the encryption still succeeds
if (tc.ivSize == 0) {
reject('Failed on test case ' + tc.id + ': 0-length iv should not be accepted');
} else {
var obtainedCt = TestUtil.arrayBufferToHex(ct);
var expectedCt = tc.ct+tc.tag;
if ((tc.result == 'valid' && obtainedCt != expectedCt) ||
(tc.result == 'invalid' && obtainedCt == expectedCt)) {
reject('Failed on test case ' + tc.id);
}
}
resolve();
}).catch(function(err){
// don't expect any exception during encryption
reject('Unexpected exception on test case ' + tc.id + ': ' + err);
});
}).catch(function(err){
reject('Failed to import key in test case ' + tc.id + ': ' + err);
});
});
return promise;
};
/**
* Tests AES-GCM encryption implementation with test vectors from files
*
* @return {!Promise}
*/
function testAesGcmVectors() {
var tv = TestUtil.readJsonTestVectorsFromFile(AES_GCM_VECTOR_FILE);
var testCase = new goog.testing.TestCase();
testCase.promiseTimeout = 2*1000;
for (var i = 0; i < tv['testGroups'].length; i++) {
var tg = tv['testGroups'][i];
var keySizeBit = parseInt(tg['keySize']);
var tagSizeBit = parseInt(tg['tagSize']);
var ivSizeBit = parseInt(tg['ivSize']);
// Only run the tests if the key size is supported
if (SUPPORTED['aesgcm-key-size'].indexOf(keySizeBit) == -1) {
continue;
}
// MS Edge only supports IVs of size 96
if (goog.userAgent.product.EDGE && ivSizeBit != 96) {
continue;
}
for (var j = 0; j < tg['tests'].length; j++){
var tc = tg['tests'][j];
// MS Edge doesn't accept 0-length message
if (goog.userAgent.product.EDGE && tc['msg'].length == 0) {
continue;
}
var k = BigInteger.fromHex(tc['key']).toBase64Url(keySizeBit/8);
var aad = TestUtil.hexToArrayBuffer(tc['aad']);
var msg = TestUtil.hexToArrayBuffer(tc['msg']);
var iv;
if (ivSizeBit == 0) {
iv = new Uint8Array([]).buffer;
} else {
iv = BigInteger.fromHex(tc['iv']).toArrayBuffer(ivSizeBit/8);
}
var ct = tc['ct'];
var tag = tc['tag'];
var result = tc['result'];
var tcId = tc['tcId'];
var test = new AesGcmTestCase(tcId, k, keySizeBit, tag, tagSizeBit,
iv, ivSizeBit, aad, msg, ct, result);
testCase.addNewTest('Test ' + tcId, AesGcm.testEncrypt, test);
}
}
return testCase.runTestsReturningPromise().then(TestUtil.checkTestCaseResult);
}
@@ -0,0 +1,183 @@
/**
* @license
* Copyright 2017 Google Inc. All rights reserved.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* Tests for ECDH implementations of Web Crypto API.
*/
goog.provide('wycheproof.webcryptoapi.ECDH');
goog.require('goog.testing.TestCase');
goog.require('goog.testing.asserts');
goog.require('goog.testing.jsunit');
goog.require('wycheproof.BigInteger');
goog.require('wycheproof.TestUtil');
goog.require('wycheproof.webcryptoapi.RsaUtil');
var TestUtil = wycheproof.TestUtil;
var RsaUtil = wycheproof.webcryptoapi.RsaUtil;
var BigInteger = wycheproof.BigInteger;
// Test vector files
var ECDH_VECTOR_FILE = '../../testvectors/ecdh_webcrypto_test.json';
/** ECDH wrapper */
var Ecdh = function() {};
/**
* Generates an ECDH key pair using the given curve name.
* @param {!string} curveName The curve name
*
* @return {!Promise}
*/
Ecdh.generateKey = function(curveName) {
return window.crypto.subtle.generateKey(
{
name: 'ECDH',
namedCurve: curveName,
},
true,
['deriveKey', 'deriveBits']
);
};
/**
* Imports a ECDH key from the given key data.
* @param {!string} curveName The curve name
* @param {!JSONObject} keyData The key data in JWK format
* @param {!Array<string>} usages The usages of the key
*
* @return {!Promise}
*/
Ecdh.importKey = function(curveName, keyData, usages) {
return window.crypto.subtle.importKey(
"jwk",
keyData,
{
name: 'ECDH',
namedCurve: curveName,
},
true,
usages
);
};
/**
* Exports the given ECDSA key as a JSON object.
* @param {!CryptoKey} key The ECDH key to be exported
*
* @return {!Promise}
*/
Ecdh.exportKey = function(key) {
return window.crypto.subtle.exportKey("jwk", key);
};
/**
* Derives bits from a public key and a private key.
* @param {!CryptoKey} pubKey The public key
* @param {!CryptoKey} privKey The private key
* @param {number} bitLen The number of bits to be derived
*
* @return {!Promise}
*/
Ecdh.deriveBits = function(pubKey, privKey, bitLen) {
return window.crypto.subtle.deriveBits(
{
name: 'ECDH',
public: pubKey,
},
privKey,
bitLen
);
};
/**
* Tests ECDH key derivation. The test case's parameters are passed
* to 'this' variable of the function.
*
* @return {!Promise}
*/
Ecdh.testKeyDerivation = function() {
tc = this;
var sk, pk;
var promise = new Promise(function(resolve, reject){
Ecdh.importKey(tc.curveName, tc.privKeyData, ['deriveBits']).then(function(key){
sk = key;
Ecdh.importKey(tc.curveName, tc.pubKeyData, []).then(function(key){
pk = key;
Ecdh.deriveBits(pk, sk, tc.sharedKeyLen).then(function(sharedKey){
if (tc.result == 'invalid') {
reject('Failed on test case ' + tc.id);
}
var hexSharedKey = TestUtil.arrayBufferToHex(sharedKey);
if (hexSharedKey != tc.sharedKey) {
reject('Failed on test case ' + tc.id);
}
resolve();
}).catch(function(err) {
// don't expect any exception in signature verification
reject('Unexpected exception on test case ' + tc.id + ": " + err);
});
}).catch(function(err) {
reject('Failed to import public key: ' + err);
});
}).catch(function(err) {
reject('Failed to import private key: ' + err);
});
});
return promise;
};
/**
* Parameters of a ECDH key derivation test.
* @param {!number} id Test case's id
* @param {!string} curveName The name of the elliptic curve
* @param {!JSONObject} privKeyData The private key's data in JWK format
* @param {!JSONObject} pubKeyData The public key's data in JWK format
* @param {!string} sharedKey The expected shared key
* @param {!string} result The expected result of the test case
*/
var EcdhTestCase = function(id, curveName, privKeyData, pubKeyData, sharedKey, result) {
this.id = id;
this.curveName = curveName;
this.privKeyData = privKeyData;
this.pubKeyData = pubKeyData;
this.sharedKey = sharedKey;
this.sharedKeyLen = sharedKey.length/2*8;
this.result = result;
};
/**
* Tests ECDH key derivation with a number of test vectors.
*
* @return {!Promise}
*/
function testEcdhVectors() {
var tv = TestUtil.readJsonTestVectorsFromFile(ECDH_VECTOR_FILE);
var testCase = new goog.testing.TestCase();
for (var i = 0; i < tv['testGroups'].length; i++) {
tg = tv['testGroups'][i];
for (var j = 0; j < tg['tests'].length; j++) {
tc = tg['tests'][j];
var test = new EcdhTestCase(tc['tcId'], tc['curve'], tc['private'], tc['public'],
tc['shared'], tc['result']);
testCase.addNewTest(tc['tcId'], Ecdh.testKeyDerivation, test);
}
}
return testCase.runTestsReturningPromise().then(TestUtil.checkTestCaseResult);
}
@@ -0,0 +1,378 @@
/**
* @license
* Copyright 2017 Google Inc. All rights reserved.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* Tests for ECDSA implementations of Web Crypto API.
*/
goog.provide('wycheproof.webcryptoapi.ECDSA');
goog.require('e2e.ecc.Ecdsa');
goog.require('goog.testing.TestCase');
goog.require('goog.testing.asserts');
goog.require('goog.testing.jsunit');
goog.require('wycheproof.BigInteger');
goog.require('wycheproof.EcUtil');
goog.require('wycheproof.TestUtil');
goog.require('wycheproof.webcryptoapi.HashUtil');
var TestUtil = wycheproof.TestUtil;
var EcUtil = wycheproof.EcUtil;
var BigInteger = wycheproof.BigInteger;
var HashUtil = wycheproof.webcryptoapi.HashUtil;
// Test vector files
var ECDSA_VECTOR_FILE = '../../testvectors/ecdsa_webcrypto_test.json';
/** ECDSA wrapper */
var Ecdsa = function() {};
/**
* Verifies the given signature using the given ECDSA public key.
* @param {!CryptoKey} pk The ECDSA public key
* @param {!string} hashAlg The hash algorithm
* @param {!ArrayBuffer} msg The message to be verified
* @param {!ArrayBuffer} sig The signature to be verified
*
* @return {!Promise}
*/
Ecdsa.verify = function(pk, hashAlg, msg, sig) {
return crypto.subtle.verify(
{
name: 'ECDSA',
hash: {name: hashAlg}
},
pk,
sig,
msg
);
};
/**
* Signs a message using the given ECDSA private key and hash algorithm.
* @param {!CryptoKey} sk The ECDSA private key
* @param {!ArrayBuffer} msg The message to be signed
* @param {!string} hashAlg The hash algorithm
*
* @return {!Promise}
*/
Ecdsa.sign = function(sk, msg, hashAlg) {
return crypto.subtle.sign(
{
name: 'ECDSA',
hash: {name: hashAlg},
},
sk,
msg
);
};
/**
* Imports a ECDSA public key.
* @param {!JSONObject} keyData The key data in JWK format
* @param {!string} hashAlg The hash algorithm
* @param {!Array<string>} usages The usages of the key
*
* @return {!Promise}
*/
Ecdsa.importPublicKey = function(keyData, hashAlg, usages) {
return crypto.subtle.importKey(
'jwk',
keyData,
{
name: 'ECDSA',
namedCurve: keyData['crv'],
hash: {name: hashAlg}
},
true,
usages
);
};
/**
* Exports the given ECDSA key as a JSON object.
* @param {!CryptoKey} key The ECDSA key to be exported
*
* @return {!Promise}
*/
Ecdsa.exportKey = function(key) {
return crypto.subtle.exportKey('jwk', key);
};
/**
* Generates an ECDSA key pair using the given hash algorithm and curve name.
* @param {!string} hashAlg The hash algorithm
* @param {!string} curveName The curve name
*
* @return {!Promise}
*/
Ecdsa.generateKey = function(hashAlg, curveName) {
return crypto.subtle.generateKey(
{
name: 'ECDSA',
namedCurve: curveName,
},
true,
['sign', 'verify']
);
};
/**
* Tests ECDSA signature verification. The test case's parameters are passed
* to 'this' variable of the function.
*
* @return {!Promise}
*/
Ecdsa.testVerify = function() {
tc = this;
var promise = new Promise((resolve, reject) => {
Ecdsa.importPublicKey(tc.keyData, tc.hashAlg, ['verify']).then(function(pk){
Ecdsa.verify(pk, tc.hashAlg, tc.msg, tc.sig).then(function(isValid){
if ((tc.result == 'valid' && !isValid) ||
(tc.result == 'invalid' && isValid)) {
reject('Failed in test case ' + tc.id);
}
resolve();
}).catch(function(err){
// don't expect any exception in signature verification
reject('Unexpected exception on test case ' + tc.id + ": " + err);
});
}).catch(function(err){
reject('Failed to import key in test case ' + tc.id + ': ' + err);
});
});
return promise;
};
/**
* Parameters of a ECDSA signature verification test.
* @param {!number} id Test case's id
* @param {!JSONObject} keyData The key data in JWK format
* @param {!string} hashAlg The hash algorithm
* @param {!ArrayBuffer} msg The message that was signed
* @param {!ArrayBuffer} sig The signature to be verified
* @param {!string} result The expected result of the test case
*/
var EcdsaVerifyTestCase = function(id, keyData, hashAlg, msg, sig, result) {
this.id = id;
this.keyData = keyData;
this.msg = msg;
this.sig = sig;
this.result = result;
this.hashAlg = hashAlg;
};
/**
* Tests ECDSA signature implementation with a number of test vectors.
*
* @return {!Promise}
*/
function testEcdsaVectors() {
var tv = TestUtil.readJsonTestVectorsFromFile(ECDSA_VECTOR_FILE);
var testCase = new goog.testing.TestCase();
for (var i = 0; i < tv['testGroups'].length; i++) {
var tg = tv['testGroups'][i];
var keyData = tg['jwk'];
var curveName = keyData['crv'];
var hashAlg = tg['sha'];
if (SUPPORTED['ecdsa-curve'].indexOf(curveName) == -1
|| SUPPORTED['hash'].indexOf(hashAlg) == -1) {
continue;
}
for (var j = 0; j < tg['tests'].length; j++) {
var tc = tg['tests'][j];
var tcId = tc['tcId'];
var result = tc['result'];
var msg = TestUtil.hexToArrayBuffer(tc['message']);
var sig = TestUtil.hexToArrayBuffer(tc['sig']);
var test = new EcdsaVerifyTestCase(
tcId, keyData, hashAlg, msg, sig, result);
testCase.addNewTest('Test ' + tcId, Ecdsa.testVerify, test);
}
}
return testCase.runTestsReturningPromise().then(TestUtil.checkTestCaseResult);
}
/**
* Extracts 'r' and 's' values from the given signature. The function assumes
* that the given signature is the concatenation of 'r' and 's'.
* @param {!ArrayBuffer} sig The signature
*
* @return {!Array<wycheproof.BigInteger>}
*/
Ecdsa.extractSig = function(sig) {
var bytes = new Uint8Array(sig);
var byteLen = bytes.length;
var rBytes = bytes.subarray(0, byteLen/2);
var r = new BigInteger(rBytes);
var sBytes = bytes.subarray(byteLen/2, byteLen);
var s = new BigInteger(sBytes);
return [r, s];
};
/**
* Extracts the random nonce that was used to calculate the given signature.
* @param {!wycheproof.BigInteger} h The digest of the message
* @param {!wycheproof.BigInteger} r The 'r' value of the signature
* @param {!wycheproof.BigInteger} s The 's' value of the signature
* @param {!wycheproof.BigInteger} d The private component of the ECDSA key
* @param {!NistCurveSpec} curveSpec The specifications of the used curve
*
* @return {!wycheproof.BigInteger}
*/
Ecdsa.extractNonce = function(h, r, s, d, curveSpec) {
var n = curveSpec.n;
var k = d.multiply(r).add(h).multiply(n.modInverse(s)).mod(n);
return k;
};
/**
* Checks whether the given nonce was actually used during the signing process
* of the given signature.
* @param {!ArrayBuffer} msg The message that was signed
* @param {!wycheproof.BigInteger} r The 'r' value of the signature
* @param {!wycheproof.BigInteger} s The 's' value of the signature
* @param {!wycheproof.BigInteger} d The private component of the ECDSA key
* @param {!wycheproof.BigInteger} k The nonce that needs to be checked
* @param {!string} curveName The curve name
*/
Ecdsa.checkNonceCorrectness = function(msg, r, s, d, k, curveName) {
var e2eCurveMap = {
'P-256': 'P_256',
'P-384': 'P_384',
'P-521': 'P_521',
};
var e2eCurveName = e2eCurveMap[curveName];
var key = new e2e.ecc.Ecdsa(e2eCurveName,
{privKey: d.toByteArray()});
var msgBytes = new Uint8Array(msg);
var calSig = key.signForTestingOnly(msgBytes, k);
var calR = new BigInteger(calSig['r']);
var calS = new BigInteger(calSig['s']);
assertTrue('Nonce calculation was incorrect',
r.isEqual(calR) && s.isEqual(calS));
};
/**
* Tests whether there is bias in the nonce generation during
* ECDSA signing process. The test case's parameters are passed
* to 'this' variable of the function. The test is based on the fact that
* if we throw a fair coin nTests times then the probability that
* either heads or tails appears less than minCount is less than 2^{-32}.
* Therefore the test below is not expected to fail unless the generation
* of the one time keys is indeed biased.
*
* NOTE: This test only works correctly if the length of the output of the
* hash function is equal to the bit length of the curve order.
*
* @return {!Promise}
*/
Ecdsa.testBias = function() {
var tc = this;
var nDone = 0;
var countLsb = 0;
var countMsb = 0;
var promise = new Promise(function(resolve, reject){
for (var i = 0; i < tc.nTests; i++) {
Ecdsa.generateKey(tc.hashAlg, tc.curveName).then(function(key){
Ecdsa.exportKey(key.privateKey).then(function(keyData){
Ecdsa.sign(key.privateKey, tc.msg, tc.hashAlg).then(function(sig){
HashUtil.digest(tc.hashAlg, tc.msg).then(function(digest){
var curveSpec = EcUtil.getCurveSpec(tc.curveName);
var h = new BigInteger(new Uint8Array(digest));
// private key value
var d = BigInteger.fromHex(TestUtil.base64UrlToHex(keyData['d']));
var r, s;
[r, s] = Ecdsa.extractSig(sig);
var k = Ecdsa.extractNonce(h, r, s, d, curveSpec);
// Uncomment this line to check correctness of nonce calculation
// Ecdsa.checkNonceCorrectness(tc.msg, r, s, d, k, tc.curveName);
var halfN = curveSpec.n.shiftRight(1);
if (k.isBitSet(0)) countLsb += 1;
if (k.compare(halfN) == 1) countMsb += 1;
nDone += 1;
if (nDone == tc.nTests) {
if (countLsb < tc.minCount || countLsb > tc.nTests-tc.minCount) {
reject("Bias detected in the LSB of k" +
", hash: " + tc.hashAlg + ", curve: " + tc.curveName +
", countLSB: " + countLsb + ", countMSB: " + countMsb);
}
if (countMsb < tc.minCount || countMsb > tc.nTests-tc.minCount) {
reject("Bias detected in the MSB of k" +
", hash: " + tc.hashAlg + ", curve: " + tc.curveName +
", countLSB: " + countLsb + ", countMSB: " + countMsb);
}
resolve();
}
});
}).catch(function(err){
reject('Failed to sign: ' + err);
});
}).catch(function(err){
reject('Failed to export private key: ' + err);
});
}).catch(function(err){
reject('Failed to generate key: ' + err);
});
}
});
return promise;
};
/**
* Parameters of a ECDSA bias test.
* @param {!string} hashAlg The hash algorithm
* @param {!string} curveName The curve name
* @param {!ArrayBuffer} msg The message that was signed
* @param {!number} nTests The number of key to be generated
* @param {!number} minCount
* The expected number of times that a bit of the nonce should be 1 or 0
*/
var EcdsaBiasTestCase = function(hashAlg, curveName, msg, nTests, minCount) {
this.msg = msg;
this.hashAlg = hashAlg;
this.curveName = curveName;
this.nTests = nTests;
this.minCount = minCount;
};
/**
* Tests whether there is bias in the nonce generation during
* ECDSA signing process. It considers three curves: secp256r1, secp384r1,
* and secp521r1.
*
* @return {!Promise}
*/
function testEcdsaBiasAll() {
var testCase = new goog.testing.TestCase();
testCase.promiseTimeout = 120*1000;
var msg = TestUtil.hexToArrayBuffer('48656c6c6f'); // msg = 'Hello'
var nTests = 1024;
var minCount = 410;
var biasTest256 = new EcdsaBiasTestCase('SHA-256', 'P-256', msg, nTests, minCount);
testCase.addNewTest('bias256', Ecdsa.testBias, biasTest256);
var biasTest384 = new EcdsaBiasTestCase('SHA-384', 'P-384', msg, nTests, minCount);
testCase.addNewTest('bias384', Ecdsa.testBias, biasTest384);
var biasTest521 = new EcdsaBiasTestCase('SHA-512', 'P-521', msg, nTests, minCount);
testCase.addNewTest('bias521', Ecdsa.testBias, biasTest521);
return testCase.runTestsReturningPromise()
.then(wycheproof.TestUtil.checkTestCaseResult);
}
@@ -0,0 +1,106 @@
/**
* @license
* Copyright 2017 Google Inc. All rights reserved.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* Tests for RSA-OAEP encryption implementations of Web Crypto API.
*/
goog.provide('wycheproof.webcryptoapi.RSA-OAED');
goog.require('e2e.random');
goog.require('goog.testing.asserts');
goog.require('goog.testing.jsunit');
goog.require('wycheproof.TestUtil');
goog.require('wycheproof.webcryptoapi.RsaUtil');
var RsaUtil = wycheproof.webcryptoapi.RsaUtil;
var TestUtil = wycheproof.TestUtil;
/**
* Tries decrypting random messages with a given algorithm. Counts the number of distinct error
* messages and expects this number to be 1.
*
* <p><b>References:</b>
*
* <ul>
* <li>Bleichenbacher, "Chosen ciphertext attacks against protocols based on the RSA encryption
* standard PKCS# 1" Crypto 98
* <li>Manger, "A chosen ciphertext attack on RSA optimal asymmetric encryption padding (OAEP)
* as standardized in PKCS# 1 v2.0", Crypto 2001 This paper shows that OAEP is susceptible
* to a chosen ciphertext attack if error messages distinguish between different failure
* condidtions.
* <li>Bardou, Focardi, Kawamoto, Simionato, Steel, Tsay "Efficient Padding Oracle Attacks on
* Cryptographic Hardware", Crypto 2012 The paper shows that small differences on what
* information an attacker recieves can make a big difference on the number of chosen
* message necessary for an attack.
* <li>Smart, "Errors matter: Breaking RSA-based PIN encryption with thirty ciphertext validity
* queries" RSA conference, 2010 This paper shows that padding oracle attacks can be
* successful with even a small number of queries.
* </ul>
*
* <p><b>Some recent bugs:</b> CVE-2012-5081: Java JSSE provider leaked information through
* exceptions and timing. Both the PKCS #1 padding and the OAEP padding were broken:
* http://www-brs.ub.ruhr-uni-bochum.de/netahtml/HSS/Diss/MeyerChristopher/diss.pdf
*
* <p><b>What this test does not (yet) cover:</b>
*
* <ul>
* <li> A previous version of one of the provider leaked the block type. (when was this fixed?)
* <li> Some attacks require a large number of ciphertexts to be detected if random ciphertexts
* are used. Such problems require specifically crafted ciphertexts to run in a unit test.
* E.g. "Attacking RSA-based Sessions in SSL/TLS" by V. Klima, O. Pokorny, and T. Rosa:
* https://eprint.iacr.org/2003/052/
* <li> Timing leakages because of differences in parsing the padding (e.g. CVE-2015-7827) Such
* differences are too small to be reliably detectable in unit tests.
* </ul>
*
* @return {!Promise}
*/
function testRsaEncryptionException() {
var promise = new Promise(function(resolve, reject){
var scheme = RsaUtil.RSA_OAEP;
var keySize = 1024;
var e = RsaUtil.E_65537;
var hashAlg = 'SHA-256';
var usages = ['encrypt', 'decrypt'];
var ctLen = keySize/8;
var nTest = 1000;
var nDone = 0;
var exceptions = new Set();
RsaUtil.generateKey(scheme, keySize, e, hashAlg, usages).then(function(key) {
for (var i = 0; i < nTest; i++) {
var ct = new Uint8Array(e2e.random.getRandomBytes(ctLen)).buffer;
RsaUtil.decrypt(scheme, key.privateKey, ct).then(function(pt){
reject('RSA-OAEP decryption should not succeed on random bytes');
}).catch(function(err){
exceptions.add(err.name + ': ' + err.message);
nDone += 1;
if (nDone == nTest) {
if (exceptions.size > 1) {
var msg = 'Exceptions leak information about the padding for ' + scheme + '\n';
exceptions.forEach(function(e) {
msg += e;
});
reject(msg);
}
resolve();
}
});
}
}).catch(function(err){
reject('Failed to generate key: ' + err);
});
});
return promise;
}
@@ -0,0 +1,71 @@
/**
* @license
* Copyright 2017 Google Inc. All rights reserved.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* Tests for RSASSA-PKCS1-v1_5 signature implementations of Web Crypto APIs.
*/
goog.provide('wycheproof.webcryptoapi.RSASSA-PKCS1-V1_5');
goog.require('goog.testing.TestCase');
goog.require('goog.testing.asserts');
goog.require('goog.testing.jsunit');
goog.require('wycheproof.BigInteger');
goog.require('wycheproof.TestUtil');
goog.require('wycheproof.webcryptoapi.HashUtil');
goog.require('wycheproof.webcryptoapi.RsaUtil');
var TestUtil = wycheproof.TestUtil;
var RsaUtil = wycheproof.webcryptoapi.RsaUtil;
var HashUtil = wycheproof.webcryptoapi.HashUtil;
var BigInteger = wycheproof.BigInteger;
// Test vector file
var RSASSA_PKCS1_SIGNATURE_VECTOR_FILE
= '../../testvectors/rsa_signature_test.json';
/**
* Tests RSASSA-PKCS1-v1_5 signature implementation with a number of vectors.
*
* @return {!Promise}
*/
function testRsaSsaPkcs1Vectors() {
var tv = TestUtil.readJsonTestVectorsFromFile(
RSASSA_PKCS1_SIGNATURE_VECTOR_FILE);
var testCase = new goog.testing.TestCase();
for (var i = 0; i < tv['testGroups'].length; i++) {
var tg = tv['testGroups'][i];
var e = BigInteger.fromHex(tg['e']).toBase64Url();
var n = BigInteger.fromHex(tg['n']).toBase64Url();
var hashAlg = tg['sha'];
if (SUPPORTED['hash'].indexOf(hashAlg) == -1) {
continue;
}
for (var j = 0; j < tg['tests'].length; j++) {
var tc = tg['tests'][j];
var msg = BigInteger.fromHex(tc['message']).toArrayBuffer();
var sig = TestUtil.hexToArrayBuffer(tc['sig']);
var result = tc['result'];
var tcId = tc['tcId'];
// Creates new Test Case object
var test = new RsaUtil.RsaSignatureTestCase(tcId, e, n, hashAlg,
RsaUtil.RSASSA_PKCS1, msg, sig, result);
testCase.addNewTest('Test case ' + tcId, RsaUtil.testVerification, test);
}
}
return testCase.runTestsReturningPromise().then(TestUtil.checkTestCaseResult);
}
+43
View File
@@ -0,0 +1,43 @@
package(default_visibility = ["//visibility:public"])
licenses(["notice"]) # Apache 2.0
filegroup(
name = "all",
srcs = glob(["**"]),
)
filegroup(
name = "aes_gcm_siv",
srcs = ["aes_gcm_siv_test.json"],
)
filegroup(
name = "aes_gcm",
srcs = ["aes_gcm_test.json"],
)
filegroup(
name = "dsa",
srcs = ["dsa_test.json"],
)
filegroup(
name = "ecdsa",
srcs = ["ecdsa_test.json"],
)
filegroup(
name = "rsa_signature",
srcs = ["rsa_signature_test.json"],
)
filegroup(
name = "ecdsa_webcrypto",
srcs = ["ecdsa_webcrypto_test.json"],
)
filegroup(
name = "ecdh_webcrypto",
srcs = ["ecdh_webcrypto_test.json"],
)
File diff suppressed because it is too large Load Diff
+669
View File
@@ -0,0 +1,669 @@
{
"algorithm": "AES-GCM",
"generatorVersion": "0.0a8",
"numberOfTests": 50,
"testGroups": [
{
"ivSize": 96,
"keySize": 128,
"tagSize": 128,
"tests": [
{
"aad": "",
"comment": "",
"ct": "26073cc1d851beff176384dc9896d5ff",
"iv": "028318abc1824029138141a2",
"key": "5b9604fe14eadba931b0ccf34843dab9",
"msg": "001d0c231287c1182784554ca3a21908",
"result": "valid",
"tag": "0a3ea7a5487cb5f7d70fb6c58d038554",
"tcId": 1
},
{
"aad": "00112233445566778899aabbccddeeff",
"comment": "",
"ct": "49d8b9783e911913d87094d1f63cc765",
"iv": "921d2507fa8007b7bd067d34",
"key": "5b9604fe14eadba931b0ccf34843dab9",
"msg": "001d0c231287c1182784554ca3a21908",
"result": "valid",
"tag": "1e348ba07cca2cf04c618cb4d43a5b92",
"tcId": 2
},
{
"aad": "aac39231129872a2",
"comment": "",
"ct": "eea945f3d0f98cc0fbab472a0cf24e87",
"iv": "0432bc49ac34412081288127",
"key": "aa023d0478dcb2b2312498293d9a9129",
"msg": "2035af313d1346ab00154fea78322105",
"result": "valid",
"tag": "4bb9b4812519dadf9e1232016d068133",
"tcId": 3
},
{
"aad": "",
"comment": "",
"ct": "ff",
"iv": "327182bee515d2b15f949477",
"key": "dc25a94c28b9d18a6468f41428fae84d",
"msg": "6f",
"result": "valid",
"tag": "62870f416e1fb63486127df9555ebcdb",
"tcId": 4
},
{
"aad": "",
"comment": "",
"ct": "4bd185849ab0f4d0",
"iv": "0cfe85626ce523b3204ca873",
"key": "bd6ffed2d59c492aec86368e02f6baeb",
"msg": "3c3b3a363f3a504e",
"result": "valid",
"tag": "742f379ab07b2c8c0c0eff4ce9327218",
"tcId": 5
},
{
"aad": "",
"comment": "",
"ct": "11afae2b91b71126e31d868e3482f907",
"iv": "5fe1b8445d7a2bce3ffd01c5",
"key": "6b21264d4ffdaa70021f6ea94f3f7729",
"msg": "6538395b746031796f5b60303261684e",
"result": "valid",
"tag": "b5133f5ce864f55641c121fb48c77e8c",
"tcId": 6
},
{
"aad": "",
"comment": "",
"ct": "ca741e2b8f4bfb75f3a897869664982be5e1feb1c3588621",
"iv": "1e0055ab643fe8d851f27501",
"key": "3f89802f2f430d027d9d27ab10095a1e",
"msg": "78446a4e313d634d524834637040456b793c6e4d4166544c",
"result": "valid",
"tag": "ab9a540db92381a4768ea81f08230100",
"tcId": 7
},
{
"aad": "15",
"comment": "",
"ct": "fa2ac3a4d15e01d64b642c4dc75f95e0",
"iv": "2071ec1a1d0ff802349fc01b",
"key": "f08afe018379b19417388302c3508983",
"msg": "566464646d4639476d5e4673653e3838",
"result": "valid",
"tag": "d95cea01fafb2c8c21cebfcbc412f87a",
"tcId": 8
},
{
"aad": "0b2bc21ab1fbff11e376e1a65ca2a1",
"comment": "",
"ct": "1e3373677b4615745a57ce43c0874702",
"iv": "460b321e66c90ae86f878da7",
"key": "7c7337a75c47230f579ff763e544b63b",
"msg": "4c565d4051404f4f35633a63455d7676",
"result": "valid",
"tag": "6c0314734528fe2863f2dc16f313e5ff",
"tcId": 9
},
{
"aad": "2eb61446950c83695522fdeb92220645",
"comment": "",
"ct": "107150b5349540a6b953c033d3ed0eec",
"iv": "787c817bf07a25ec613f4fbb",
"key": "9bd978c97f84c67e967a6dc71a9dd29a",
"msg": "4d36343f6e38716e476476394764635b",
"result": "valid",
"tag": "87ec1d4fee69de2efe606138b99a1c56",
"tcId": 10
},
{
"aad": "62a76634d40bb93ce8bd140e418bf88f002e1b88396511f5ddd9b099abe7b722",
"comment": "",
"ct": "8e0b9ca71471c5d509167fb138d65834",
"iv": "da22d5718083aee0b1ecf18c",
"key": "a3b604ee4889e9986b1d760779acb0da",
"msg": "453b3b34344076413d3b5b46373f725c",
"result": "valid",
"tag": "7cc68eb3039691eeea5b211c9f39244a",
"tcId": 11
},
{
"aad": "",
"comment": "special case",
"ct": "f62d84d649e56bc8cfedc5d74a51e2f7",
"iv": "000000000000000000000000",
"key": "00112233445566778899aabbccddeeff",
"msg": "ebd4a3e10cf6d41c50aeae007563b072",
"result": "valid",
"tag": "ffffffffffffffffffffffffffffffff",
"tcId": 12
},
{
"aad": "",
"comment": "special case",
"ct": "431f31e6840931fd95f94bf88296ff69",
"iv": "ffffffffffffffffffffffff",
"key": "00112233445566778899aabbccddeeff",
"msg": "d593c4d8224f1b100c35e4f6c4006543",
"result": "valid",
"tag": "00000000000000000000000000000000",
"tcId": 13
},
{
"aad": "",
"comment": "special case",
"ct": "d8eba6a5a03403851abc27f6e15d84c0",
"iv": "00112233445566778899aabb",
"key": "00112233445566778899aabbccddeeff",
"msg": "7fd49ba712d0d28f02ef54ed18db43f8",
"result": "valid",
"tag": "00000000000000000000000000000000",
"tcId": 14
}
],
"type": "AES-GCM"
},
{
"ivSize": 64,
"keySize": 128,
"tagSize": 128,
"tests": [
{
"aad": "aac39231129872a2",
"comment": "",
"ct": "64c36bb3b732034e3a7d04efc5197785",
"iv": "0432bc49ac344120",
"key": "aa023d0478dcb2b2312498293d9a9129",
"msg": "2035af313d1346ab00154fea78322105",
"result": "valid",
"tag": "b7d0dd70b00d65b97cfd080ff4b819d1",
"tcId": 15
},
{
"aad": "",
"comment": "unusual IV size",
"ct": "553763110458769a08e3c5d9",
"iv": "22117438f0762c77",
"key": "b215270c3e1055888599f1e5f6188e57",
"msg": "7675613a6c356e663d483264",
"result": "valid",
"tag": "14fed4270ed847fec690988c729672d1",
"tcId": 16
}
],
"type": "AES-GCM"
},
{
"ivSize": 128,
"keySize": 128,
"tagSize": 128,
"tests": [
{
"aad": "1a0293d8f90219058902139013908190bc490890d3ff12a3",
"comment": "",
"ct": "64069c2d58690561f27ee199e6b479b6369eec688672bde9",
"iv": "3254202d854734812398127a3d134421",
"key": "2034a82547276c83dd3212a813572bce",
"msg": "02efd2e5782312827ed5d230189a2a342b277ce048462193",
"result": "valid",
"tag": "9b7abadd6e69c1d9ec925786534f5075",
"tcId": 17
},
{
"aad": "",
"comment": "J0:000102030405060708090a0b0c0d0e0f",
"ct": "00078d109d92143fcd5df56721b884fac64ac7762cc09eea2a3c68e92a17bdb575f87bda18be564e",
"iv": "f95fde4a751913202aeeee32a0b55753",
"key": "00112233445566778899aabbccddeeff",
"msg": "00000000000000000000000000000000000000000000000000000000000000000000000000000000",
"result": "valid",
"tag": "152a65045fe674f97627427af5be22da",
"tcId": 18
},
{
"aad": "",
"comment": "J0:00000000000000000000000000000000",
"ct": "84d4c9c08b4f482861e3a9c6c35bc4d91df927374513bfd49f436bd73f325285daef4ff7e13d46a6",
"iv": "7b95b8c356810a84711d68150a1b7750",
"key": "00112233445566778899aabbccddeeff",
"msg": "00000000000000000000000000000000000000000000000000000000000000000000000000000000",
"result": "valid",
"tag": "213a3cb93855d18e69337eee66aeec07",
"tcId": 19
},
{
"aad": "",
"comment": "J0:ffffffffffffffffffffffffffffffff",
"ct": "948ca37a8e6649e88aeffb1c598f3607007702417ea0e0bc3c60ad5a949886de968cf53ea6462aed",
"iv": "1a552e67cdc4dc1a33b824874ebf0bed",
"key": "00112233445566778899aabbccddeeff",
"msg": "00000000000000000000000000000000000000000000000000000000000000000000000000000000",
"result": "valid",
"tag": "99b381bfa2af9751c39d1b6e86d1be6a",
"tcId": 20
},
{
"aad": "",
"comment": "J0:000102030405060708090a0bffffffff",
"ct": "127af9b39ecdfc57bb11a2847c7c2d3d8f938f40f877e0c4af37d0fe9af033052bd537c4ae978f60",
"iv": "99821c2dd5daecded07300f577f7aff1",
"key": "00112233445566778899aabbccddeeff",
"msg": "00000000000000000000000000000000000000000000000000000000000000000000000000000000",
"result": "valid",
"tag": "07eb2fe4a958f8434d40684899507c7c",
"tcId": 21
},
{
"aad": "",
"comment": "J0:000102030405060708090a0bfffffffe",
"ct": "0cf6ae47156b14dce03c8a07a2e172b1127af9b39ecdfc57bb11a2847c7c2d3d8f938f40f877e0c4",
"iv": "5e4a3900142358d1c774d8d124d8d27d",
"key": "00112233445566778899aabbccddeeff",
"msg": "00000000000000000000000000000000000000000000000000000000000000000000000000000000",
"result": "valid",
"tag": "f145c2dcaf339eede427be934357eac0",
"tcId": 22
},
{
"aad": "",
"comment": "special case",
"ct": "1cd5a06214235ceb044d4bad7b047312",
"iv": "ffffffffffffffffffffffffffffffff",
"key": "00112233445566778899aabbccddeeff",
"msg": "4d82639c39d3f3490ee903dd0be7afcf",
"result": "valid",
"tag": "ffffffffffffffffffffffffffffffff",
"tcId": 23
},
{
"aad": "",
"comment": "unusual IV size",
"ct": "d6db136eb9bd4cdaf0bd1913",
"iv": "44b926c2a249611e14475b6cfe4d7dae",
"key": "c79117e417d6d45e37a52441cbfaa47b",
"msg": "623734365060575b423b303a",
"result": "valid",
"tag": "54132cb206112184c889e1f15b83fe1f",
"tcId": 24
}
],
"type": "AES-GCM"
},
{
"ivSize": 96,
"keySize": 256,
"tagSize": 128,
"tests": [
{
"aad": "00000000ffffffff",
"comment": "",
"ct": "e27abdd2d2a53d2f136b",
"iv": "00112233445566778899aabb",
"key": "92ace3e348cd821092cd921aa3546374299ab46209691bc28b8752d17f123c20",
"msg": "00010203040506070809",
"result": "valid",
"tag": "9a4a2579529301bcfb71c78d4060f52c",
"tcId": 25
},
{
"aad": "aabbccddeeff",
"comment": "",
"ct": "",
"iv": "00112233445566778899aabb",
"key": "29d3a44f8723dc640239100c365423a312934ac80239212ac3df3421a2098123",
"msg": "",
"result": "valid",
"tag": "2a7d77fa526b8250cb296078926b5020",
"tcId": 26
},
{
"aad": "",
"comment": "",
"ct": "11",
"iv": "61de8c2f27065bb3f1235d55",
"key": "a68e06009f0c9630fed700e67d4960378cc1c86ae6cc79a6ac6a9042bf83039a",
"msg": "7a",
"result": "valid",
"tag": "05402b6d9671f281c34848fed708da8b",
"tcId": 27
},
{
"aad": "",
"comment": "",
"ct": "aecefdde647dbfd9",
"iv": "27f3c472caf75d6102ef5f0d",
"key": "fe65ab5e97e2adff16bb5cf71f31d09754ce2a246aeaedc5647afb54dce7b68d",
"msg": "493d425c4b3f6d51",
"result": "valid",
"tag": "02af89a1eadcb29077a26203314a7dc3",
"tcId": 28
},
{
"aad": "",
"comment": "",
"ct": "3ddf2af410318b26750139bf4ec13460",
"iv": "6f5485754cd243aecd2c9e43",
"key": "9c6edc8b05d7bceb455a6b915f16f117e244ff788a8c20c25fd6e0a49566d781",
"msg": "5031613a625a7348753b323c4f3f7835",
"result": "valid",
"tag": "4e4bc7648e7fb0976c4cb9c2fb3ca540",
"tcId": 29
},
{
"aad": "",
"comment": "",
"ct": "28bbe0d13c0f43422df882a2dc9e011b4d4fd5bc9e73c515",
"iv": "3d3f629413e65f8b6e55ec8e",
"key": "c786bc3074dad0f11efecfd24dd9f9df9fec79161d1ffd5acb18fc69fe3f3e0f",
"msg": "635569643f32513f655a6e5c423547744259725e454b616d",
"result": "valid",
"tag": "bbf623568c0bd3b94b5201af8711a8d2",
"tcId": 30
},
{
"aad": "45",
"comment": "",
"ct": "69c3ee7e6d4bae0d747164980d6b9b0c",
"iv": "c0dfc8a34a8c946504f882c5",
"key": "44a85d703964debdf04efe8748c7953da193ecd7ce4453673d86b96c5a1b3154",
"msg": "5a416a725a6d69746269316f6c747566",
"result": "valid",
"tag": "5221ece0acc54017981f0cdad17839b2",
"tcId": 31
},
{
"aad": "e19b62570639e9329109d81795f82f",
"comment": "",
"ct": "54d25cd9f65a56ee17a4cb88fbc7489d",
"iv": "6f6a2fc05f916819550e1ec0",
"key": "afc8d84a39c7b984670d42712c1e6b86aa8bf9458e20054da9aa4de627aadb69",
"msg": "45353c45306243584277445f317a355a",
"result": "valid",
"tag": "8e535d739362959710ec3ddb486e8bc2",
"tcId": 32
},
{
"aad": "d0468a40ded0439cdf41cfa5662181d8",
"comment": "",
"ct": "ec23144c64749090e581928d86681f3e",
"iv": "b74599e72c0309e162658615",
"key": "62f210a5cdfaa9c341c5c25ca1510fbbe611d433091d064eb62dbbcfbc95f15b",
"msg": "5a6551343a4b45685c49795b5a557449",
"result": "valid",
"tag": "ce0594dabb2b4db89460e085bc44e684",
"tcId": 33
},
{
"aad": "6387afe729e73233e3860de9c1a6617b37bab1eedaba9fcb53618e7eac3d8009",
"comment": "",
"ct": "fcfc653448912e1d9f5413dc92c7678b",
"iv": "74852c78eb5a479ec8620ae4",
"key": "34135b6afae2248312d68c1e28db5a4cbbfd3ccc5b4aab357353bd2541d45c59",
"msg": "34356b523f4a6d5c3237325043353e50",
"result": "valid",
"tag": "1b3acf71c1fdcfa8d61d585d10004f6d",
"tcId": 34
}
],
"type": "AES-GCM"
},
{
"ivSize": 96,
"keySize": 192,
"tagSize": 128,
"tests": [
{
"aad": "",
"comment": "",
"ct": "7a",
"iv": "e6bfc54c87a8e2a9b539eedb",
"key": "6c7a0c4c8515ed6c7d4eca4916bb0c8362d282afeacbe3f9",
"msg": "3c",
"result": "valid",
"tag": "106daeade85585d997e65bc4564fe125",
"tcId": 35
},
{
"aad": "",
"comment": "",
"ct": "16f812c2be4121b6",
"iv": "6d7baec9ed558f82aa1128cd",
"key": "35a0d16c02ec630e360e9d7243a82c76ac36668c0b59413e",
"msg": "5c513c3a74763674",
"result": "valid",
"tag": "f35ba677c07a76aea8e70a81918d35cf",
"tcId": 36
},
{
"aad": "",
"comment": "",
"ct": "21c250e0f28c494c944bd1345d6daa51",
"iv": "cffd1a7e8d52cf3c0c4bbb8e",
"key": "ddeb7f10bbd1b82c115165e6c1547d224e3449933ea3bfe9",
"msg": "526a3b4e7472324a5b3a5b553b4b443f",
"result": "valid",
"tag": "bbaea6623cf22328efcd21bf3656987e",
"tcId": 37
},
{
"aad": "",
"comment": "",
"ct": "034c477eee703e11b0f354d5912c16fd512c69cccbc22211",
"iv": "56f2119df4070d2e767861e8",
"key": "b567dc2ed4684ccfb582d80ff9b15ef520a325f0b8201cdc",
"msg": "306c3e337a60677956536e346472534679707a6552624e3f",
"result": "valid",
"tag": "d8ecc0925d544d9e2906504e4f006bea",
"tcId": 38
}
],
"type": "AES-GCM"
},
{
"ivSize": 120,
"keySize": 128,
"tagSize": 128,
"tests": [
{
"aad": "",
"comment": "unusual IV size",
"ct": "fde7899c326af98d67b07890",
"iv": "ca2a23ea38e82a4304021e0984800c",
"key": "a9ded7b2cbce3621d310006444ce80a3",
"msg": "665470423738756779357345",
"result": "valid",
"tag": "a545ed6b98a8b49c6588232e3d876de7",
"tcId": 39
}
],
"type": "AES-GCM"
},
{
"ivSize": 160,
"keySize": 128,
"tagSize": 128,
"tests": [
{
"aad": "",
"comment": "unusual IV size",
"ct": "35a123fa123571aa0d242a66",
"iv": "9ce715dd2a59b4a6bf7451c7a144b97f3e62c0a0",
"key": "1e7cc3c9116b0a2d25154e1f4ae97796",
"msg": "6c74623b3346665333613c3d",
"result": "valid",
"tag": "831a00839d8c008c9d1cb0f9a8d17255",
"tcId": 40
}
],
"type": "AES-GCM"
},
{
"ivSize": 64,
"keySize": 256,
"tagSize": 128,
"tests": [
{
"aad": "",
"comment": "unusual IV size",
"ct": "99add354679e324c3277506c",
"iv": "bd3b080f33229c69",
"key": "b22f6e946ab41994781b4bfff1e3f44e3daaf4d9ad788bbfa39a8caa2bc112cf",
"msg": "3b353b365e37784a5833354c",
"result": "valid",
"tag": "174fd057b60654548d833f9d6d9626e8",
"tcId": 41
}
],
"type": "AES-GCM"
},
{
"ivSize": 120,
"keySize": 256,
"tagSize": 128,
"tests": [
{
"aad": "",
"comment": "unusual IV size",
"ct": "992b01084e37fbe3a6cfd456",
"iv": "479e398a4805a347a5c4c16ddfe621",
"key": "0d20b8ef8b05c48f691a5dd9b49b6c0637aee0567257b6c3ce35a5823c337294",
"msg": "527979696037335d553a4767",
"result": "valid",
"tag": "1cd717548e768aa0f9932311d443bf0e",
"tcId": 42
}
],
"type": "AES-GCM"
},
{
"ivSize": 128,
"keySize": 256,
"tagSize": 128,
"tests": [
{
"aad": "",
"comment": "unusual IV size",
"ct": "fa93631a76a63d8096bb11f3",
"iv": "ad581e8f55a8d283f0dfebae9d0c6484",
"key": "cc4a246cb3e166c194e59f465db9adf92a8974cd472744c062728ccbae687aac",
"msg": "6b4d3e67695a79544b725046",
"result": "valid",
"tag": "fb1c7f1c3d5c0155ae18eb9bc13f7758",
"tcId": 43
}
],
"type": "AES-GCM"
},
{
"ivSize": 160,
"keySize": 256,
"tagSize": 128,
"tests": [
{
"aad": "",
"comment": "unusual IV size",
"ct": "b35920ed04f6a7dcf8d075a9",
"iv": "3293e555aa1cb29f839d571e811b8e84807a0031",
"key": "3a95937dd23f0997fae31a26821d99e8e338016c05ad30718f41fa04aced12f8",
"msg": "5578554a61324e4c3142483a",
"result": "valid",
"tag": "fa0c75f97432e5ef97445ccf99a90231",
"tcId": 44
}
],
"type": "AES-GCM"
},
{
"ivSize": 0,
"keySize": 128,
"tagSize": 128,
"tests": [
{
"aad": "",
"comment": "0 size IV is not valid",
"ct": "",
"iv": "",
"key": "b1e11d771f1ea274a3386d3879738d64",
"msg": "",
"result": "invalid",
"tag": "ec5c4805da277942d7ad6ea2d212d909",
"tcId": 45
},
{
"aad": "",
"comment": "0 size IV is not valid",
"ct": "8766b19d2e07b51ddfe8c85ea440ee2e",
"iv": "",
"key": "fb6c0503a1cd5219a2d5daa2e32a1520",
"msg": "446e39493339594b7247494d41344739",
"result": "invalid",
"tag": "5154e473735b026452a57060f3be5f66",
"tcId": 46
}
],
"type": "AES-GCM"
},
{
"ivSize": 0,
"keySize": 192,
"tagSize": 128,
"tests": [
{
"aad": "",
"comment": "0 size IV is not valid",
"ct": "",
"iv": "",
"key": "0955fa25af91994f0407ff1e2f3b09af4074c13fbba6aa0b",
"msg": "",
"result": "invalid",
"tag": "bec27fcd432323a3162cbcfc4a4ae53b",
"tcId": 47
},
{
"aad": "",
"comment": "0 size IV is not valid",
"ct": "a284cb5110f73225954d0a74fc24b024",
"iv": "",
"key": "0750d0d5d4df4985fcc726177e6b325e90c7e9c5f4922e43",
"msg": "793b50665c4c79647534646231496748",
"result": "invalid",
"tag": "8fe5ddb632fa6d72af5fe114c95bcaa3",
"tcId": 48
}
],
"type": "AES-GCM"
},
{
"ivSize": 0,
"keySize": 256,
"tagSize": 128,
"tests": [
{
"aad": "",
"comment": "0 size IV is not valid",
"ct": "",
"iv": "",
"key": "57163950d52c957068dc2ae7184911402887458e65ae212e54369eac864376a8",
"msg": "",
"result": "invalid",
"tag": "6397e0239baa358c90bc5a8bb69d3330",
"tcId": 49
},
{
"aad": "",
"comment": "0 size IV is not valid",
"ct": "77bbd2bc21a7cb2f1b62510a659db421",
"iv": "",
"key": "c242c762169e049fa7952d14123f61add08f9cd3cdb0784d7241f073244f0580",
"msg": "3669513131313f386240783b573b666f",
"result": "invalid",
"tag": "b2015bf3387d68cd2e9785d0b8bc46c8",
"tcId": 50
}
],
"type": "AES-GCM"
}
]
}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff