mirror of
https://github.com/LadybirdBrowser/ladybird
synced 2026-04-27 02:05:07 +02:00
LibWeb: Import KMAC WPT tests
This commit is contained in:
committed by
Jelle Raaijmakers
parent
915fc4602b
commit
6cc575b8a9
Notes:
github-actions[bot]
2026-03-19 09:48:04 +00:00
Author: https://github.com/mikiubo Commit: https://github.com/LadybirdBrowser/ladybird/commit/6cc575b8a9c Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/8445 Reviewed-by: https://github.com/gmta ✅
@@ -0,0 +1,17 @@
|
||||
<!doctype html>
|
||||
<meta charset=utf-8>
|
||||
<title>WebCryptoAPI: generateKey() for Failures</title>
|
||||
<meta name="timeout" content="long">
|
||||
<script>
|
||||
self.GLOBAL = {
|
||||
isWindow: function() { return true; },
|
||||
isWorker: function() { return false; },
|
||||
isShadowRealm: function() { return false; },
|
||||
};
|
||||
</script>
|
||||
<script src="../../resources/testharness.js"></script>
|
||||
<script src="../../resources/testharnessreport.js"></script>
|
||||
<script src="../util/helpers.js"></script>
|
||||
<script src="failures.js"></script>
|
||||
<div id=log></div>
|
||||
<script src="../../WebCryptoAPI/generateKey/failures_kmac.tentative.https.any.js"></script>
|
||||
@@ -0,0 +1,5 @@
|
||||
// META: title=WebCryptoAPI: generateKey() for Failures
|
||||
// META: timeout=long
|
||||
// META: script=../util/helpers.js
|
||||
// META: script=failures.js
|
||||
run_test(["KMAC128", "KMAC256"]);
|
||||
@@ -0,0 +1,18 @@
|
||||
<!doctype html>
|
||||
<meta charset=utf-8>
|
||||
<title>WebCryptoAPI: generateKey() Successful Calls</title>
|
||||
<meta name="timeout" content="long">
|
||||
<script>
|
||||
self.GLOBAL = {
|
||||
isWindow: function() { return true; },
|
||||
isWorker: function() { return false; },
|
||||
isShadowRealm: function() { return false; },
|
||||
};
|
||||
</script>
|
||||
<script src="../../resources/testharness.js"></script>
|
||||
<script src="../../resources/testharnessreport.js"></script>
|
||||
<script src="../util/helpers.js"></script>
|
||||
<script src="../../common/subset-tests.js"></script>
|
||||
<script src="successes.js"></script>
|
||||
<div id=log></div>
|
||||
<script src="../../WebCryptoAPI/generateKey/successes_kmac.tentative.https.any.js"></script>
|
||||
@@ -0,0 +1,6 @@
|
||||
// META: title=WebCryptoAPI: generateKey() Successful Calls
|
||||
// META: timeout=long
|
||||
// META: script=../util/helpers.js
|
||||
// META: script=/common/subset-tests.js
|
||||
// META: script=successes.js
|
||||
run_test(["KMAC128", "KMAC256"]);
|
||||
@@ -0,0 +1,17 @@
|
||||
<!doctype html>
|
||||
<meta charset=utf-8>
|
||||
<title>WebCryptoAPI: importKey() for symmetric keys</title>
|
||||
<meta name="timeout" content="long">
|
||||
<script>
|
||||
self.GLOBAL = {
|
||||
isWindow: function() { return true; },
|
||||
isWorker: function() { return false; },
|
||||
isShadowRealm: function() { return false; },
|
||||
};
|
||||
</script>
|
||||
<script src="../../resources/testharness.js"></script>
|
||||
<script src="../../resources/testharnessreport.js"></script>
|
||||
<script src="../util/helpers.js"></script>
|
||||
<script src="symmetric_importKey.js"></script>
|
||||
<div id=log></div>
|
||||
<script src="../../WebCryptoAPI/import_export/KMAC_importKey.tentative.https.any.js"></script>
|
||||
@@ -0,0 +1,7 @@
|
||||
// META: title=WebCryptoAPI: importKey() for symmetric keys
|
||||
// META: timeout=long
|
||||
// META: script=../util/helpers.js
|
||||
// META: script=symmetric_importKey.js
|
||||
|
||||
runTests("KMAC128");
|
||||
runTests("KMAC256");
|
||||
@@ -0,0 +1,615 @@
|
||||
function run_test() {
|
||||
setup({explicit_done: true});
|
||||
|
||||
var subtle = self.crypto.subtle; // Change to test prefixed implementations
|
||||
|
||||
// When are all these tests really done? When all the promises they use have resolved.
|
||||
var all_promises = [];
|
||||
|
||||
// Source file kmac_vectors.js provides the getTestVectors method
|
||||
// for the algorithm that drives these tests.
|
||||
var testVectors = getTestVectors();
|
||||
|
||||
// Test verification first, because signing tests rely on that working
|
||||
testVectors.forEach(function(vector) {
|
||||
var promise = importVectorKeys(vector, ["verify", "sign"])
|
||||
.then(function(vector) {
|
||||
promise_test(function(test) {
|
||||
var algorithmParams = {name: vector.algorithm, length: vector.length};
|
||||
if (vector.customization !== undefined) {
|
||||
algorithmParams.customization = vector.customization;
|
||||
}
|
||||
var operation = subtle.verify(algorithmParams, vector.key, vector.signature, vector.plaintext)
|
||||
.then(function(is_verified) {
|
||||
assert_true(is_verified, "Signature verified");
|
||||
}, function(err) {
|
||||
assert_unreached("Verification should not throw error " + vector.name + ": '" + err.message + "'");
|
||||
});
|
||||
|
||||
return operation;
|
||||
}, vector.name + " verification");
|
||||
|
||||
}, function(err) {
|
||||
// We need a failed test if the importVectorKey operation fails, so
|
||||
// we know we never tested verification.
|
||||
promise_test(function(test) {
|
||||
assert_unreached("importVectorKeys failed for " + vector.name + ". Message: ''" + err.message + "''");
|
||||
}, "importVectorKeys step: " + vector.name + " verification");
|
||||
});
|
||||
|
||||
all_promises.push(promise);
|
||||
});
|
||||
|
||||
// Test verification with an altered buffer during call
|
||||
testVectors.forEach(function(vector) {
|
||||
var promise = importVectorKeys(vector, ["verify", "sign"])
|
||||
.then(function(vector) {
|
||||
promise_test(function(test) {
|
||||
var signature = copyBuffer(vector.signature);
|
||||
signature[0] = 255 - signature[0];
|
||||
var algorithmParams = {
|
||||
length: vector.length,
|
||||
get name() {
|
||||
signature[0] = vector.signature[0];
|
||||
return vector.algorithm;
|
||||
}
|
||||
};
|
||||
if (vector.customization !== undefined) {
|
||||
algorithmParams.customization = vector.customization;
|
||||
}
|
||||
var operation = subtle.verify(algorithmParams, vector.key, signature, vector.plaintext)
|
||||
.then(function(is_verified) {
|
||||
assert_true(is_verified, "Signature is not verified");
|
||||
}, function(err) {
|
||||
assert_unreached("Verification should not throw error " + vector.name + ": '" + err.message + "'");
|
||||
});
|
||||
|
||||
return operation;
|
||||
}, vector.name + " verification with altered signature during call");
|
||||
}, function(err) {
|
||||
promise_test(function(test) {
|
||||
assert_unreached("importVectorKeys failed for " + vector.name + ". Message: ''" + err.message + "''");
|
||||
}, "importVectorKeys step: " + vector.name + " verification with altered signature during call");
|
||||
});
|
||||
|
||||
all_promises.push(promise);
|
||||
});
|
||||
|
||||
// Test verification with an altered buffer after call
|
||||
testVectors.forEach(function(vector) {
|
||||
var promise = importVectorKeys(vector, ["verify", "sign"])
|
||||
.then(function(vector) {
|
||||
promise_test(function(test) {
|
||||
var signature = copyBuffer(vector.signature);
|
||||
var algorithmParams = {name: vector.algorithm, length: vector.length};
|
||||
if (vector.customization !== undefined) {
|
||||
algorithmParams.customization = vector.customization;
|
||||
}
|
||||
var operation = subtle.verify(algorithmParams, vector.key, signature, vector.plaintext)
|
||||
.then(function(is_verified) {
|
||||
assert_true(is_verified, "Signature is not verified");
|
||||
}, function(err) {
|
||||
assert_unreached("Verification should not throw error " + vector.name + ": '" + err.message + "'");
|
||||
});
|
||||
|
||||
signature[0] = 255 - signature[0];
|
||||
return operation;
|
||||
}, vector.name + " verification with altered signature after call");
|
||||
}, function(err) {
|
||||
promise_test(function(test) {
|
||||
assert_unreached("importVectorKeys failed for " + vector.name + ". Message: ''" + err.message + "''");
|
||||
}, "importVectorKeys step: " + vector.name + " verification with altered signature after call");
|
||||
});
|
||||
|
||||
all_promises.push(promise);
|
||||
});
|
||||
|
||||
// Test verification with a transferred buffer during call
|
||||
testVectors.forEach(function(vector) {
|
||||
var promise = importVectorKeys(vector, ["verify", "sign"])
|
||||
.then(function(vector) {
|
||||
promise_test(function(test) {
|
||||
var signature = copyBuffer(vector.signature);
|
||||
var algorithmParams = {
|
||||
get name() {
|
||||
signature.buffer.transfer();
|
||||
return vector.algorithm;
|
||||
},
|
||||
length: vector.length
|
||||
};
|
||||
if (vector.customization !== undefined) {
|
||||
algorithmParams.customization = vector.customization;
|
||||
}
|
||||
var operation = subtle.verify(algorithmParams, vector.key, signature, vector.plaintext)
|
||||
.then(function(is_verified) {
|
||||
assert_false(is_verified, "Signature is NOT verified");
|
||||
}, function(err) {
|
||||
assert_unreached("Verification should not throw error " + vector.name + ": '" + err.message + "'");
|
||||
});
|
||||
|
||||
return operation;
|
||||
}, vector.name + " verification with transferred signature during call");
|
||||
}, function(err) {
|
||||
promise_test(function(test) {
|
||||
assert_unreached("importVectorKeys failed for " + vector.name + ". Message: ''" + err.message + "''");
|
||||
}, "importVectorKeys step: " + vector.name + " verification with transferred signature during call");
|
||||
});
|
||||
|
||||
all_promises.push(promise);
|
||||
});
|
||||
|
||||
// Test verification with a transferred buffer after call
|
||||
testVectors.forEach(function(vector) {
|
||||
var promise = importVectorKeys(vector, ["verify", "sign"])
|
||||
.then(function(vector) {
|
||||
promise_test(function(test) {
|
||||
var signature = copyBuffer(vector.signature);
|
||||
var algorithmParams = {name: vector.algorithm, length: vector.length};
|
||||
if (vector.customization !== undefined) {
|
||||
algorithmParams.customization = vector.customization;
|
||||
}
|
||||
var operation = subtle.verify(algorithmParams, vector.key, signature, vector.plaintext)
|
||||
.then(function(is_verified) {
|
||||
assert_true(is_verified, "Signature is not verified");
|
||||
}, function(err) {
|
||||
assert_unreached("Verification should not throw error " + vector.name + ": '" + err.message + "'");
|
||||
});
|
||||
|
||||
signature.buffer.transfer();
|
||||
return operation;
|
||||
}, vector.name + " verification with transferred signature after call");
|
||||
}, function(err) {
|
||||
promise_test(function(test) {
|
||||
assert_unreached("importVectorKeys failed for " + vector.name + ". Message: ''" + err.message + "''");
|
||||
}, "importVectorKeys step: " + vector.name + " verification with transferred signature after call");
|
||||
});
|
||||
|
||||
all_promises.push(promise);
|
||||
});
|
||||
|
||||
// Check for successful verification even if plaintext is altered during call.
|
||||
testVectors.forEach(function(vector) {
|
||||
var promise = importVectorKeys(vector, ["verify", "sign"])
|
||||
.then(function(vector) {
|
||||
promise_test(function(test) {
|
||||
var plaintext = copyBuffer(vector.plaintext);
|
||||
plaintext[0] = 255 - plaintext[0];
|
||||
var algorithmParams = {
|
||||
length: vector.length,
|
||||
get name() {
|
||||
plaintext[0] = vector.plaintext[0];
|
||||
return vector.algorithm;
|
||||
}
|
||||
};
|
||||
if (vector.customization !== undefined) {
|
||||
algorithmParams.customization = vector.customization;
|
||||
}
|
||||
var operation = subtle.verify(algorithmParams, vector.key, vector.signature, plaintext)
|
||||
.then(function(is_verified) {
|
||||
assert_true(is_verified, "Signature verified");
|
||||
}, function(err) {
|
||||
assert_unreached("Verification should not throw error " + vector.name + ": '" + err.message + "'");
|
||||
});
|
||||
|
||||
return operation;
|
||||
}, vector.name + " with altered plaintext during call");
|
||||
}, function(err) {
|
||||
promise_test(function(test) {
|
||||
assert_unreached("importVectorKeys failed for " + vector.name + ". Message: ''" + err.message + "''");
|
||||
}, "importVectorKeys step: " + vector.name + " with altered plaintext during call");
|
||||
});
|
||||
|
||||
all_promises.push(promise);
|
||||
});
|
||||
|
||||
// Check for successful verification even if plaintext is altered after call.
|
||||
testVectors.forEach(function(vector) {
|
||||
var promise = importVectorKeys(vector, ["verify", "sign"])
|
||||
.then(function(vector) {
|
||||
promise_test(function(test) {
|
||||
var plaintext = copyBuffer(vector.plaintext);
|
||||
var algorithmParams = {name: vector.algorithm, length: vector.length};
|
||||
if (vector.customization !== undefined) {
|
||||
algorithmParams.customization = vector.customization;
|
||||
}
|
||||
var operation = subtle.verify(algorithmParams, vector.key, vector.signature, plaintext)
|
||||
.then(function(is_verified) {
|
||||
assert_true(is_verified, "Signature verified");
|
||||
}, function(err) {
|
||||
assert_unreached("Verification should not throw error " + vector.name + ": '" + err.message + "'");
|
||||
});
|
||||
|
||||
plaintext[0] = 255 - plaintext[0];
|
||||
return operation;
|
||||
}, vector.name + " with altered plaintext after call");
|
||||
}, function(err) {
|
||||
promise_test(function(test) {
|
||||
assert_unreached("importVectorKeys failed for " + vector.name + ". Message: ''" + err.message + "''");
|
||||
}, "importVectorKeys step: " + vector.name + " with altered plaintext after call");
|
||||
});
|
||||
|
||||
all_promises.push(promise);
|
||||
});
|
||||
|
||||
// Check for failed verification if plaintext is transferred during call.
|
||||
testVectors.forEach(function(vector) {
|
||||
var promise = importVectorKeys(vector, ["verify", "sign"])
|
||||
.then(function(vector) {
|
||||
promise_test(function(test) {
|
||||
var plaintext = copyBuffer(vector.plaintext);
|
||||
var algorithmParams = {
|
||||
get name() {
|
||||
plaintext.buffer.transfer();
|
||||
return vector.algorithm;
|
||||
},
|
||||
length: vector.length
|
||||
};
|
||||
if (vector.customization !== undefined) {
|
||||
algorithmParams.customization = vector.customization;
|
||||
}
|
||||
var operation = subtle.verify(algorithmParams, vector.key, vector.signature, plaintext)
|
||||
.then(function(is_verified) {
|
||||
assert_false(is_verified, "Signature is NOT verified");
|
||||
}, function(err) {
|
||||
assert_unreached("Verification should not throw error " + vector.name + ": '" + err.message + "'");
|
||||
});
|
||||
|
||||
return operation;
|
||||
}, vector.name + " with transferred plaintext during call");
|
||||
}, function(err) {
|
||||
promise_test(function(test) {
|
||||
assert_unreached("importVectorKeys failed for " + vector.name + ". Message: ''" + err.message + "''");
|
||||
}, "importVectorKeys step: " + vector.name + " with transferred plaintext during call");
|
||||
});
|
||||
|
||||
all_promises.push(promise);
|
||||
});
|
||||
|
||||
// Check for successful verification even if plaintext is transferred after call.
|
||||
testVectors.forEach(function(vector) {
|
||||
var promise = importVectorKeys(vector, ["verify", "sign"])
|
||||
.then(function(vector) {
|
||||
promise_test(function(test) {
|
||||
var plaintext = copyBuffer(vector.plaintext);
|
||||
var algorithmParams = {name: vector.algorithm, length: vector.length};
|
||||
if (vector.customization !== undefined) {
|
||||
algorithmParams.customization = vector.customization;
|
||||
}
|
||||
var operation = subtle.verify(algorithmParams, vector.key, vector.signature, plaintext)
|
||||
.then(function(is_verified) {
|
||||
assert_true(is_verified, "Signature verified");
|
||||
}, function(err) {
|
||||
assert_unreached("Verification should not throw error " + vector.name + ": '" + err.message + "'");
|
||||
});
|
||||
|
||||
plaintext.buffer.transfer();
|
||||
return operation;
|
||||
}, vector.name + " with transferred plaintext after call");
|
||||
}, function(err) {
|
||||
promise_test(function(test) {
|
||||
assert_unreached("importVectorKeys failed for " + vector.name + ". Message: ''" + err.message + "''");
|
||||
}, "importVectorKeys step: " + vector.name + " with transferred plaintext after call");
|
||||
});
|
||||
|
||||
all_promises.push(promise);
|
||||
});
|
||||
|
||||
// Check for failures due to no "verify" usage.
|
||||
testVectors.forEach(function(originalVector) {
|
||||
var vector = Object.assign({}, originalVector);
|
||||
|
||||
var promise = importVectorKeys(vector, ["sign"])
|
||||
.then(function(vector) {
|
||||
promise_test(function(test) {
|
||||
var algorithmParams = {name: vector.algorithm, length: vector.length};
|
||||
if (vector.customization !== undefined) {
|
||||
algorithmParams.customization = vector.customization;
|
||||
}
|
||||
return subtle.verify(algorithmParams, vector.key, vector.signature, vector.plaintext)
|
||||
.then(function(plaintext) {
|
||||
assert_unreached("Should have thrown error for no verify usage in " + vector.name + ": '" + err.message + "'");
|
||||
}, function(err) {
|
||||
assert_equals(err.name, "InvalidAccessError", "Should throw InvalidAccessError instead of '" + err.message + "'");
|
||||
});
|
||||
}, vector.name + " no verify usage");
|
||||
}, function(err) {
|
||||
promise_test(function(test) {
|
||||
assert_unreached("importVectorKeys failed for " + vector.name + ". Message: ''" + err.message + "''");
|
||||
}, "importVectorKeys step: " + vector.name + " no verify usage");
|
||||
});
|
||||
|
||||
all_promises.push(promise);
|
||||
});
|
||||
|
||||
// Check for successful signing and verification.
|
||||
testVectors.forEach(function(vector) {
|
||||
var promise = importVectorKeys(vector, ["verify", "sign"])
|
||||
.then(function(vectors) {
|
||||
promise_test(function(test) {
|
||||
var algorithmParams = {name: vector.algorithm, length: vector.length};
|
||||
if (vector.customization !== undefined) {
|
||||
algorithmParams.customization = vector.customization;
|
||||
}
|
||||
return subtle.sign(algorithmParams, vector.key, vector.plaintext)
|
||||
.then(function(signature) {
|
||||
assert_true(equalBuffers(signature, vector.signature), "Signing did not give the expected output");
|
||||
// Can we get the verify the new signature?
|
||||
return subtle.verify(algorithmParams, vector.key, signature, vector.plaintext)
|
||||
.then(function(is_verified) {
|
||||
assert_true(is_verified, "Round trip verifies");
|
||||
return signature;
|
||||
}, function(err) {
|
||||
assert_unreached("verify error for test " + vector.name + ": '" + err.message + "'");
|
||||
});
|
||||
});
|
||||
}, vector.name + " round trip");
|
||||
|
||||
}, function(err) {
|
||||
// We need a failed test if the importVectorKey operation fails, so
|
||||
// we know we never tested signing or verifying
|
||||
promise_test(function(test) {
|
||||
assert_unreached("importVectorKeys failed for " + vector.name + ". Message: ''" + err.message + "''");
|
||||
}, "importVectorKeys step: " + vector.name + " round trip");
|
||||
});
|
||||
|
||||
all_promises.push(promise);
|
||||
});
|
||||
|
||||
// Test signing with the wrong algorithm
|
||||
testVectors.forEach(function(vector) {
|
||||
// Want to get the key for the wrong algorithm
|
||||
var promise = subtle.generateKey({name: "ECDSA", namedCurve: "P-256", hash: "SHA-256"}, false, ["sign", "verify"])
|
||||
.then(function(wrongKey) {
|
||||
return importVectorKeys(vector, ["verify", "sign"])
|
||||
.then(function(vectors) {
|
||||
promise_test(function(test) {
|
||||
var algorithmParams = {name: vector.algorithm, length: vector.length};
|
||||
if (vector.customization !== undefined) {
|
||||
algorithmParams.customization = vector.customization;
|
||||
}
|
||||
var operation = subtle.sign(algorithmParams, wrongKey.privateKey, vector.plaintext)
|
||||
.then(function(signature) {
|
||||
assert_unreached("Signing should not have succeeded for " + vector.name);
|
||||
}, function(err) {
|
||||
assert_equals(err.name, "InvalidAccessError", "Should have thrown InvalidAccessError instead of '" + err.message + "'");
|
||||
});
|
||||
|
||||
return operation;
|
||||
}, vector.name + " signing with wrong algorithm name");
|
||||
|
||||
}, function(err) {
|
||||
// We need a failed test if the importVectorKey operation fails, so
|
||||
// we know we never tested verification.
|
||||
promise_test(function(test) {
|
||||
assert_unreached("importVectorKeys failed for " + vector.name + ". Message: ''" + err.message + "''");
|
||||
}, "importVectorKeys step: " + vector.name + " signing with wrong algorithm name");
|
||||
});
|
||||
}, function(err) {
|
||||
promise_test(function(test) {
|
||||
assert_unreached("Generate wrong key for test " + vector.name + " failed: '" + err.message + "'");
|
||||
}, "generate wrong key step: " + vector.name + " signing with wrong algorithm name");
|
||||
});
|
||||
|
||||
all_promises.push(promise);
|
||||
});
|
||||
|
||||
// Test verification with the wrong algorithm
|
||||
testVectors.forEach(function(vector) {
|
||||
// Want to get the key for the wrong algorithm
|
||||
var promise = subtle.generateKey({name: "ECDSA", namedCurve: "P-256", hash: "SHA-256"}, false, ["sign", "verify"])
|
||||
.then(function(wrongKey) {
|
||||
return importVectorKeys(vector, ["verify", "sign"])
|
||||
.then(function(vector) {
|
||||
promise_test(function(test) {
|
||||
var algorithmParams = {name: vector.algorithm, length: vector.length};
|
||||
if (vector.customization !== undefined) {
|
||||
algorithmParams.customization = vector.customization;
|
||||
}
|
||||
var operation = subtle.verify(algorithmParams, wrongKey.publicKey, vector.signature, vector.plaintext)
|
||||
.then(function(signature) {
|
||||
assert_unreached("Verifying should not have succeeded for " + vector.name);
|
||||
}, function(err) {
|
||||
assert_equals(err.name, "InvalidAccessError", "Should have thrown InvalidAccessError instead of '" + err.message + "'");
|
||||
});
|
||||
|
||||
return operation;
|
||||
}, vector.name + " verifying with wrong algorithm name");
|
||||
|
||||
}, function(err) {
|
||||
// We need a failed test if the importVectorKey operation fails, so
|
||||
// we know we never tested verification.
|
||||
promise_test(function(test) {
|
||||
assert_unreached("importVectorKeys failed for " + vector.name + ". Message: ''" + err.message + "''");
|
||||
}, "importVectorKeys step: " + vector.name + " verifying with wrong algorithm name");
|
||||
});
|
||||
}, function(err) {
|
||||
promise_test(function(test) {
|
||||
assert_unreached("Generate wrong key for test " + vector.name + " failed: '" + err.message + "'");
|
||||
}, "generate wrong key step: " + vector.name + " verifying with wrong algorithm name");
|
||||
});
|
||||
|
||||
all_promises.push(promise);
|
||||
});
|
||||
|
||||
// Verification should fail if the plaintext is changed
|
||||
testVectors.forEach(function(vector) {
|
||||
var promise = importVectorKeys(vector, ["verify", "sign"])
|
||||
.then(function(vector) {
|
||||
var plaintext = copyBuffer(vector.plaintext);
|
||||
plaintext[0] = 255 - plaintext[0];
|
||||
promise_test(function(test) {
|
||||
var algorithmParams = {name: vector.algorithm, length: vector.length};
|
||||
if (vector.customization !== undefined) {
|
||||
algorithmParams.customization = vector.customization;
|
||||
}
|
||||
var operation = subtle.verify(algorithmParams, vector.key, vector.signature, plaintext)
|
||||
.then(function(is_verified) {
|
||||
assert_false(is_verified, "Signature is NOT verified");
|
||||
}, function(err) {
|
||||
assert_unreached("Verification should not throw error " + vector.name + ": '" + err.message + "'");
|
||||
});
|
||||
|
||||
return operation;
|
||||
}, vector.name + " verification failure due to wrong plaintext");
|
||||
|
||||
}, function(err) {
|
||||
// We need a failed test if the importVectorKey operation fails, so
|
||||
// we know we never tested verification.
|
||||
promise_test(function(test) {
|
||||
assert_unreached("importVectorKeys failed for " + vector.name + ". Message: ''" + err.message + "''");
|
||||
}, "importVectorKeys step: " + vector.name + " verification failure due to wrong plaintext");
|
||||
});
|
||||
|
||||
all_promises.push(promise);
|
||||
});
|
||||
|
||||
// Verification should fail if the signature is changed
|
||||
testVectors.forEach(function(vector) {
|
||||
var promise = importVectorKeys(vector, ["verify", "sign"])
|
||||
.then(function(vector) {
|
||||
var signature = copyBuffer(vector.signature);
|
||||
signature[0] = 255 - signature[0];
|
||||
promise_test(function(test) {
|
||||
var algorithmParams = {name: vector.algorithm, length: vector.length};
|
||||
if (vector.customization !== undefined) {
|
||||
algorithmParams.customization = vector.customization;
|
||||
}
|
||||
var operation = subtle.verify(algorithmParams, vector.key, signature, vector.plaintext)
|
||||
.then(function(is_verified) {
|
||||
assert_false(is_verified, "Signature is NOT verified");
|
||||
}, function(err) {
|
||||
assert_unreached("Verification should not throw error " + vector.name + ": '" + err.message + "'");
|
||||
});
|
||||
|
||||
return operation;
|
||||
}, vector.name + " verification failure due to wrong signature");
|
||||
|
||||
}, function(err) {
|
||||
// We need a failed test if the importVectorKey operation fails, so
|
||||
// we know we never tested verification.
|
||||
promise_test(function(test) {
|
||||
assert_unreached("importVectorKeys failed for " + vector.name + ". Message: ''" + err.message + "''");
|
||||
}, "importVectorKeys step: " + vector.name + " verification failure due to wrong signature");
|
||||
});
|
||||
|
||||
all_promises.push(promise);
|
||||
});
|
||||
|
||||
// Verification should fail if the signature is wrong length
|
||||
testVectors.forEach(function(vector) {
|
||||
var promise = importVectorKeys(vector, ["verify", "sign"])
|
||||
.then(function(vector) {
|
||||
var signature = vector.signature.slice(1); // Drop first byte
|
||||
promise_test(function(test) {
|
||||
var algorithmParams = {name: vector.algorithm, length: vector.length};
|
||||
if (vector.customization !== undefined) {
|
||||
algorithmParams.customization = vector.customization;
|
||||
}
|
||||
var operation = subtle.verify(algorithmParams, vector.key, signature, vector.plaintext)
|
||||
.then(function(is_verified) {
|
||||
assert_false(is_verified, "Signature is NOT verified");
|
||||
}, function(err) {
|
||||
assert_unreached("Verification should not throw error " + vector.name + ": '" + err.message + "'");
|
||||
});
|
||||
|
||||
return operation;
|
||||
}, vector.name + " verification failure due to short signature");
|
||||
|
||||
}, function(err) {
|
||||
// We need a failed test if the importVectorKey operation fails, so
|
||||
// we know we never tested verification.
|
||||
promise_test(function(test) {
|
||||
assert_unreached("importVectorKeys failed for " + vector.name + ". Message: ''" + err.message + "''");
|
||||
}, "importVectorKeys step: " + vector.name + " verification failure due to short signature");
|
||||
});
|
||||
|
||||
all_promises.push(promise);
|
||||
});
|
||||
|
||||
// Test verification failure due to wrong length parameter
|
||||
testVectors.forEach(function(vector) {
|
||||
var promise = importVectorKeys(vector, ["verify", "sign"])
|
||||
.then(function(vector) {
|
||||
promise_test(function(test) {
|
||||
var differentLength = vector.length === 256 ? 512 : 256;
|
||||
var algorithmParams = {name: vector.algorithm, length: differentLength};
|
||||
if (vector.customization !== undefined) {
|
||||
algorithmParams.customization = vector.customization;
|
||||
}
|
||||
var operation = subtle.verify(algorithmParams, vector.key, vector.signature, vector.plaintext)
|
||||
.then(function(is_verified) {
|
||||
assert_false(is_verified, "Signature is NOT verified with wrong length");
|
||||
}, function(err) {
|
||||
assert_unreached("Verification should not throw error " + vector.name + ": '" + err.message + "'");
|
||||
});
|
||||
|
||||
return operation;
|
||||
}, vector.name + " verification failure due to wrong length parameter");
|
||||
|
||||
}, function(err) {
|
||||
// We need a failed test if the importVectorKey operation fails, so
|
||||
// we know we never tested verification.
|
||||
promise_test(function(test) {
|
||||
assert_unreached("importVectorKeys failed for " + vector.name + ". Message: ''" + err.message + "''");
|
||||
}, "importVectorKeys step: " + vector.name + " verification failure due to wrong length parameter");
|
||||
});
|
||||
|
||||
all_promises.push(promise);
|
||||
});
|
||||
|
||||
promise_test(function() {
|
||||
return Promise.all(all_promises)
|
||||
.then(function() {done();})
|
||||
.catch(function() {done();})
|
||||
}, "setup");
|
||||
|
||||
// A test vector has all needed fields for signing and verifying, EXCEPT that the
|
||||
// key field may be null. This function replaces that null with the Correct
|
||||
// CryptoKey object.
|
||||
//
|
||||
// Returns a Promise that yields an updated vector on success.
|
||||
function importVectorKeys(vector, keyUsages) {
|
||||
if (vector.key !== null) {
|
||||
return new Promise(function(resolve, reject) {
|
||||
resolve(vector);
|
||||
});
|
||||
} else {
|
||||
return subtle.importKey("raw-secret", vector.keyBuffer, {name: vector.algorithm}, false, keyUsages)
|
||||
.then(function(key) {
|
||||
vector.key = key;
|
||||
return vector;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Returns a copy of the sourceBuffer it is sent.
|
||||
function copyBuffer(sourceBuffer) {
|
||||
var source = new Uint8Array(sourceBuffer);
|
||||
var copy = new Uint8Array(sourceBuffer.byteLength)
|
||||
|
||||
for (var i=0; i<source.byteLength; i++) {
|
||||
copy[i] = source[i];
|
||||
}
|
||||
|
||||
return copy;
|
||||
}
|
||||
|
||||
function equalBuffers(a, b) {
|
||||
if (a.byteLength !== b.byteLength) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var aBytes = new Uint8Array(a);
|
||||
var bBytes = new Uint8Array(b);
|
||||
|
||||
for (var i=0; i<a.byteLength; i++) {
|
||||
if (aBytes[i] !== bBytes[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
<!doctype html>
|
||||
<meta charset=utf-8>
|
||||
<title>WebCryptoAPI: sign() and verify() Using KMAC</title>
|
||||
<meta name="timeout" content="long">
|
||||
<script>
|
||||
self.GLOBAL = {
|
||||
isWindow: function() { return true; },
|
||||
isWorker: function() { return false; },
|
||||
isShadowRealm: function() { return false; },
|
||||
};
|
||||
</script>
|
||||
<script src="../../resources/testharness.js"></script>
|
||||
<script src="../../resources/testharnessreport.js"></script>
|
||||
<script src="kmac_vectors.js"></script>
|
||||
<script src="kmac.js"></script>
|
||||
<div id=log></div>
|
||||
<script src="../../WebCryptoAPI/sign_verify/kmac.tentative.https.any.js"></script>
|
||||
@@ -0,0 +1,6 @@
|
||||
// META: title=WebCryptoAPI: sign() and verify() Using KMAC
|
||||
// META: script=kmac_vectors.js
|
||||
// META: script=kmac.js
|
||||
// META: timeout=long
|
||||
|
||||
run_test();
|
||||
@@ -0,0 +1,143 @@
|
||||
function getTestVectors() {
|
||||
// KMAC test vectors from https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/KMAC_samples.pdf
|
||||
|
||||
var vectors = [
|
||||
{
|
||||
// Sample #1 - KMAC128, no customization
|
||||
name: "KMAC128 with no customization",
|
||||
algorithm: "KMAC128",
|
||||
length: 256,
|
||||
keyBuffer: new Uint8Array([
|
||||
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b,
|
||||
0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
|
||||
0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
|
||||
]),
|
||||
key: null,
|
||||
plaintext: new Uint8Array([0x00, 0x01, 0x02, 0x03]),
|
||||
customization: undefined,
|
||||
signature: new Uint8Array([
|
||||
0xe5, 0x78, 0x0b, 0x0d, 0x3e, 0xa6, 0xf7, 0xd3, 0xa4, 0x29, 0xc5, 0x70,
|
||||
0x6a, 0xa4, 0x3a, 0x00, 0xfa, 0xdb, 0xd7, 0xd4, 0x96, 0x28, 0x83, 0x9e,
|
||||
0x31, 0x87, 0x24, 0x3f, 0x45, 0x6e, 0xe1, 0x4e,
|
||||
]),
|
||||
},
|
||||
{
|
||||
// Sample #2 - KMAC128, with customization
|
||||
name: "KMAC128 with customization",
|
||||
algorithm: "KMAC128",
|
||||
length: 256,
|
||||
keyBuffer: new Uint8Array([
|
||||
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b,
|
||||
0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
|
||||
0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
|
||||
]),
|
||||
key: null,
|
||||
plaintext: new Uint8Array([0x00, 0x01, 0x02, 0x03]),
|
||||
customization: new Uint8Array([
|
||||
77, 121, 32, 84, 97, 103, 103, 101, 100, 32, 65, 112, 112, 108, 105, 99,
|
||||
97, 116, 105, 111, 110,
|
||||
]), // "My Tagged Application"
|
||||
signature: new Uint8Array([
|
||||
0x3b, 0x1f, 0xba, 0x96, 0x3c, 0xd8, 0xb0, 0xb5, 0x9e, 0x8c, 0x1a, 0x6d,
|
||||
0x71, 0x88, 0x8b, 0x71, 0x43, 0x65, 0x1a, 0xf8, 0xba, 0x0a, 0x70, 0x70,
|
||||
0xc0, 0x97, 0x9e, 0x28, 0x11, 0x32, 0x4a, 0xa5,
|
||||
]),
|
||||
},
|
||||
{
|
||||
// Sample #3 - KMAC128, large data, with customization
|
||||
name: "KMAC128 with large data and customization",
|
||||
algorithm: "KMAC128",
|
||||
length: 256,
|
||||
keyBuffer: new Uint8Array([
|
||||
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b,
|
||||
0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
|
||||
0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
|
||||
]),
|
||||
key: null,
|
||||
plaintext: new Uint8Array(Array.from({ length: 200 }, (_, i) => i)), // 0x00-0xC7
|
||||
customization: new Uint8Array([
|
||||
77, 121, 32, 84, 97, 103, 103, 101, 100, 32, 65, 112, 112, 108, 105, 99,
|
||||
97, 116, 105, 111, 110,
|
||||
]), // "My Tagged Application"
|
||||
signature: new Uint8Array([
|
||||
0x1f, 0x5b, 0x4e, 0x6c, 0xca, 0x02, 0x20, 0x9e, 0x0d, 0xcb, 0x5c, 0xa6,
|
||||
0x35, 0xb8, 0x9a, 0x15, 0xe2, 0x71, 0xec, 0xc7, 0x60, 0x07, 0x1d, 0xfd,
|
||||
0x80, 0x5f, 0xaa, 0x38, 0xf9, 0x72, 0x92, 0x30,
|
||||
]),
|
||||
},
|
||||
{
|
||||
// Sample #4 - KMAC256, with customization, 512-bit output
|
||||
name: "KMAC256 with customization and 512-bit output",
|
||||
algorithm: "KMAC256",
|
||||
length: 512,
|
||||
keyBuffer: new Uint8Array([
|
||||
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b,
|
||||
0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
|
||||
0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
|
||||
]),
|
||||
key: null,
|
||||
plaintext: new Uint8Array([0x00, 0x01, 0x02, 0x03]),
|
||||
customization: new Uint8Array([
|
||||
77, 121, 32, 84, 97, 103, 103, 101, 100, 32, 65, 112, 112, 108, 105, 99,
|
||||
97, 116, 105, 111, 110,
|
||||
]), // "My Tagged Application"
|
||||
signature: new Uint8Array([
|
||||
0x20, 0xc5, 0x70, 0xc3, 0x13, 0x46, 0xf7, 0x03, 0xc9, 0xac, 0x36, 0xc6,
|
||||
0x1c, 0x03, 0xcb, 0x64, 0xc3, 0x97, 0x0d, 0x0c, 0xfc, 0x78, 0x7e, 0x9b,
|
||||
0x79, 0x59, 0x9d, 0x27, 0x3a, 0x68, 0xd2, 0xf7, 0xf6, 0x9d, 0x4c, 0xc3,
|
||||
0xde, 0x9d, 0x10, 0x4a, 0x35, 0x16, 0x89, 0xf2, 0x7c, 0xf6, 0xf5, 0x95,
|
||||
0x1f, 0x01, 0x03, 0xf3, 0x3f, 0x4f, 0x24, 0x87, 0x10, 0x24, 0xd9, 0xc2,
|
||||
0x77, 0x73, 0xa8, 0xdd,
|
||||
]),
|
||||
},
|
||||
{
|
||||
// Sample #5 - KMAC256, large data, no customization, 512-bit output
|
||||
name: "KMAC256 with large data and no customization",
|
||||
algorithm: "KMAC256",
|
||||
length: 512,
|
||||
keyBuffer: new Uint8Array([
|
||||
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b,
|
||||
0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
|
||||
0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
|
||||
]),
|
||||
key: null,
|
||||
plaintext: new Uint8Array(Array.from({ length: 200 }, (_, i) => i)), // 0x00-0xC7
|
||||
customization: undefined,
|
||||
signature: new Uint8Array([
|
||||
0x75, 0x35, 0x8c, 0xf3, 0x9e, 0x41, 0x49, 0x4e, 0x94, 0x97, 0x07, 0x92,
|
||||
0x7c, 0xee, 0x0a, 0xf2, 0x0a, 0x3f, 0xf5, 0x53, 0x90, 0x4c, 0x86, 0xb0,
|
||||
0x8f, 0x21, 0xcc, 0x41, 0x4b, 0xcf, 0xd6, 0x91, 0x58, 0x9d, 0x27, 0xcf,
|
||||
0x5e, 0x15, 0x36, 0x9c, 0xbb, 0xff, 0x8b, 0x9a, 0x4c, 0x2e, 0xb1, 0x78,
|
||||
0x00, 0x85, 0x5d, 0x02, 0x35, 0xff, 0x63, 0x5d, 0xa8, 0x25, 0x33, 0xec,
|
||||
0x6b, 0x75, 0x9b, 0x69,
|
||||
]),
|
||||
},
|
||||
{
|
||||
// Sample #6 - KMAC256, large data, with customization, 512-bit output
|
||||
name: "KMAC256 with large data and customization",
|
||||
algorithm: "KMAC256",
|
||||
length: 512,
|
||||
keyBuffer: new Uint8Array([
|
||||
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b,
|
||||
0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
|
||||
0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
|
||||
]),
|
||||
key: null,
|
||||
plaintext: new Uint8Array(Array.from({ length: 200 }, (_, i) => i)), // 0x00-0xC7
|
||||
customization: new Uint8Array([
|
||||
77, 121, 32, 84, 97, 103, 103, 101, 100, 32, 65, 112, 112, 108, 105, 99,
|
||||
97, 116, 105, 111, 110,
|
||||
]), // "My Tagged Application"
|
||||
signature: new Uint8Array([
|
||||
0xb5, 0x86, 0x18, 0xf7, 0x1f, 0x92, 0xe1, 0xd5, 0x6c, 0x1b, 0x8c, 0x55,
|
||||
0xdd, 0xd7, 0xcd, 0x18, 0x8b, 0x97, 0xb4, 0xca, 0x4d, 0x99, 0x83, 0x1e,
|
||||
0xb2, 0x69, 0x9a, 0x83, 0x7d, 0xa2, 0xe4, 0xd9, 0x70, 0xfb, 0xac, 0xfd,
|
||||
0xe5, 0x00, 0x33, 0xae, 0xa5, 0x85, 0xf1, 0xa2, 0x70, 0x85, 0x10, 0xc3,
|
||||
0x2d, 0x07, 0x88, 0x08, 0x01, 0xbd, 0x18, 0x28, 0x98, 0xfe, 0x47, 0x68,
|
||||
0x76, 0xfc, 0x89, 0x65,
|
||||
]),
|
||||
},
|
||||
];
|
||||
|
||||
return vectors;
|
||||
}
|
||||
Reference in New Issue
Block a user