mirror of
https://github.com/LadybirdBrowser/ladybird
synced 2026-04-30 11:37:16 +02:00
LibWeb: Refresh imported WebCryptoAPI WPT files
Refresh imported WebCryptoAPI WPT files to current upstream versions, including the shared fixtures and helper scripts they rely on. This keeps the in-tree imported coverage up to date and rebaselines the expectations for the refreshed tests that continue to match Ladybird's current behavior. The wrapKey_unwrapKey update is handled separately, since the newer upstream test exercises raw-secret key formats that needed an engine fix first.
This commit is contained in:
committed by
Andreas Kling
parent
b2db3574c5
commit
472f366ef5
Notes:
github-actions[bot]
2026-03-29 11:23:25 +00:00
Author: https://github.com/awesomekling Commit: https://github.com/LadybirdBrowser/ladybird/commit/472f366ef5d Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/8665
@@ -93,6 +93,67 @@ function run_test() {
|
||||
all_promises.push(promise);
|
||||
});
|
||||
|
||||
// Check for encryption of an empty value if the buffer is transferred while calling encrypt.
|
||||
passingVectors.forEach(function(vector) {
|
||||
var plaintext = copyBuffer(vector.plaintext);
|
||||
var promise = importVectorKey(vector, ["encrypt", "decrypt"])
|
||||
.then(function(vector) {
|
||||
promise_test(function(test) {
|
||||
var operation = subtle.encrypt({
|
||||
...vector.algorithm,
|
||||
get name() {
|
||||
plaintext.buffer.transfer();
|
||||
return vector.algorithm.name;
|
||||
}
|
||||
}, vector.key, plaintext)
|
||||
.then(function(result) {
|
||||
var expectedLength =
|
||||
["AES-GCM", "AES-OCB"].includes(vector.algorithm.name) ? vector.algorithm.tagLength / 8 :
|
||||
vector.algorithm.name === "AES-CBC" ? 16 :
|
||||
0;
|
||||
assert_equals(result.byteLength, expectedLength, "Transferred plaintext yields an empty ciphertext");
|
||||
}, function(err) {
|
||||
assert_unreached("encrypt error for test " + vector.name + ": " + err.message);
|
||||
});
|
||||
return operation;
|
||||
}, vector.name + " with transferred plaintext during call");
|
||||
}, function(err) {
|
||||
// We need a failed test if the importVectorKey operation fails, so
|
||||
// we know we never tested encryption
|
||||
promise_test(function(test) {
|
||||
assert_unreached("importKey failed for " + vector.name);
|
||||
}, "importKey step: " + vector.name + " with transferred plaintext during call");
|
||||
});
|
||||
|
||||
all_promises.push(promise);
|
||||
});
|
||||
|
||||
// Check for successful encryption even if the buffer is transferred after calling encrypt.
|
||||
passingVectors.forEach(function(vector) {
|
||||
var plaintext = copyBuffer(vector.plaintext);
|
||||
var promise = importVectorKey(vector, ["encrypt", "decrypt"])
|
||||
.then(function(vector) {
|
||||
promise_test(function(test) {
|
||||
var operation = subtle.encrypt(vector.algorithm, vector.key, plaintext)
|
||||
.then(function(result) {
|
||||
assert_true(equalBuffers(result, vector.result), "Should return expected result");
|
||||
}, function(err) {
|
||||
assert_unreached("encrypt error for test " + vector.name + ": " + err.message);
|
||||
});
|
||||
plaintext.buffer.transfer();
|
||||
return operation;
|
||||
}, vector.name + " with transferred plaintext after call");
|
||||
}, function(err) {
|
||||
// We need a failed test if the importVectorKey operation fails, so
|
||||
// we know we never tested encryption
|
||||
promise_test(function(test) {
|
||||
assert_unreached("importKey failed for " + vector.name);
|
||||
}, "importKey step: " + vector.name + " with transferred plaintext after call");
|
||||
});
|
||||
|
||||
all_promises.push(promise);
|
||||
});
|
||||
|
||||
// Check for successful decryption.
|
||||
passingVectors.forEach(function(vector) {
|
||||
var promise = importVectorKey(vector, ["encrypt", "decrypt"])
|
||||
@@ -174,6 +235,71 @@ function run_test() {
|
||||
all_promises.push(promise);
|
||||
});
|
||||
|
||||
// Check for decryption when ciphertext is transferred while calling decrypt.
|
||||
passingVectors.forEach(function(vector) {
|
||||
var ciphertext = copyBuffer(vector.result);
|
||||
var promise = importVectorKey(vector, ["encrypt", "decrypt"])
|
||||
.then(function(vector) {
|
||||
promise_test(function(test) {
|
||||
var operation = subtle.decrypt({
|
||||
...vector.algorithm,
|
||||
get name() {
|
||||
ciphertext.buffer.transfer();
|
||||
return vector.algorithm.name;
|
||||
}
|
||||
}, vector.key, ciphertext)
|
||||
.then(function(result) {
|
||||
if (vector.algorithm.name === "AES-CTR") {
|
||||
assert_equals(result.byteLength, 0, "Transferred ciphertext yields empty plaintext");
|
||||
} else {
|
||||
assert_unreached("decrypt should not have succeeded for " + vector.name);
|
||||
}
|
||||
}, function(err) {
|
||||
if (vector.algorithm.name === "AES-CTR") {
|
||||
assert_unreached("decrypt error for test " + vector.name + ": " + err.message);
|
||||
} else {
|
||||
assert_equals(err.name, "OperationError", "Should throw an OperationError instead of " + err.message);
|
||||
}
|
||||
});
|
||||
return operation;
|
||||
}, vector.name + " decryption with transferred ciphertext during call");
|
||||
}, function(err) {
|
||||
// We need a failed test if the importVectorKey operation fails, so
|
||||
// we know we never tested encryption
|
||||
promise_test(function(test) {
|
||||
assert_unreached("importKey failed for " + vector.name);
|
||||
}, "importKey step for decryption: " + vector.name + " with transferred ciphertext during call");
|
||||
});
|
||||
|
||||
all_promises.push(promise);
|
||||
});
|
||||
|
||||
// Check for successful decryption even if ciphertext is transferred after calling encrypt.
|
||||
passingVectors.forEach(function(vector) {
|
||||
var ciphertext = copyBuffer(vector.result);
|
||||
var promise = importVectorKey(vector, ["encrypt", "decrypt"])
|
||||
.then(function(vector) {
|
||||
promise_test(function(test) {
|
||||
var operation = subtle.decrypt(vector.algorithm, vector.key, ciphertext)
|
||||
.then(function(result) {
|
||||
assert_true(equalBuffers(result, vector.plaintext), "Should return expected result");
|
||||
}, function(err) {
|
||||
assert_unreached("decrypt error for test " + vector.name + ": " + err.message);
|
||||
});
|
||||
ciphertext.buffer.transfer();
|
||||
return operation;
|
||||
}, vector.name + " decryption with transferred ciphertext after call");
|
||||
}, function(err) {
|
||||
// We need a failed test if the importVectorKey operation fails, so
|
||||
// we know we never tested encryption
|
||||
promise_test(function(test) {
|
||||
assert_unreached("importKey failed for " + vector.name);
|
||||
}, "importKey step for decryption: " + vector.name + " with transferred ciphertext after call");
|
||||
});
|
||||
|
||||
all_promises.push(promise);
|
||||
});
|
||||
|
||||
// Everything that succeeded should fail if no "encrypt" usage.
|
||||
passingVectors.forEach(function(vector) {
|
||||
// Don't want to overwrite key being used for success tests!
|
||||
@@ -356,34 +482,5 @@ function run_test() {
|
||||
}
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ self.GLOBAL = {
|
||||
</script>
|
||||
<script src="../../resources/testharness.js"></script>
|
||||
<script src="../../resources/testharnessreport.js"></script>
|
||||
<script src="../util/helpers.js"></script>
|
||||
<script src="aes_gcm_96_iv_fixtures.js"></script>
|
||||
<script src="aes_gcm_vectors.js"></script>
|
||||
<script src="aes.js"></script>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
// META: title=WebCryptoAPI: encrypt() Using AES-GCM w/ 96-bit iv
|
||||
// META: script=../util/helpers.js
|
||||
// META: script=aes_gcm_96_iv_fixtures.js
|
||||
// META: script=aes_gcm_vectors.js
|
||||
// META: script=aes.js
|
||||
|
||||
@@ -11,6 +11,7 @@ self.GLOBAL = {
|
||||
</script>
|
||||
<script src="../../resources/testharness.js"></script>
|
||||
<script src="../../resources/testharnessreport.js"></script>
|
||||
<script src="../util/helpers.js"></script>
|
||||
<script src="aes_gcm_256_iv_fixtures.js"></script>
|
||||
<script src="aes_gcm_vectors.js"></script>
|
||||
<script src="aes.js"></script>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
// META: title=WebCryptoAPI: encrypt() Using AES-GCM w/ 256-bit iv
|
||||
// META: script=../util/helpers.js
|
||||
// META: script=aes_gcm_256_iv_fixtures.js
|
||||
// META: script=aes_gcm_vectors.js
|
||||
// META: script=aes.js
|
||||
|
||||
@@ -59,7 +59,6 @@ function getTestVectors() {
|
||||
// Scenarios that should fail because of a bad tag length, causing an OperationError
|
||||
var failing = [];
|
||||
keyLengths.forEach(function(keyLength) {
|
||||
// First, make some tests for bad tag lengths
|
||||
[24, 48, 72, 95, 129].forEach(function(badTagLength) {
|
||||
failing.push({
|
||||
name: "AES-GCM " + keyLength.toString() + "-bit key, " + (iv.byteLength << 3).toString() + "-bit iv, " + "illegal tag length " + badTagLength.toString() + "-bits",
|
||||
|
||||
@@ -11,6 +11,7 @@ self.GLOBAL = {
|
||||
</script>
|
||||
<script src="../../resources/testharness.js"></script>
|
||||
<script src="../../resources/testharnessreport.js"></script>
|
||||
<script src="../util/helpers.js"></script>
|
||||
<script src="aes_ocb_fixtures.js"></script>
|
||||
<script src="aes_ocb_vectors.js"></script>
|
||||
<script src="aes.js"></script>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
// META: title=WebCryptoAPI: encrypt() Using AES-OCB w/ 120-bit iv
|
||||
// META: script=../util/helpers.js
|
||||
// META: script=aes_ocb_fixtures.js
|
||||
// META: script=aes_ocb_vectors.js
|
||||
// META: script=aes.js
|
||||
|
||||
@@ -11,6 +11,6 @@ self.GLOBAL = {
|
||||
</script>
|
||||
<script src="../../resources/testharness.js"></script>
|
||||
<script src="../../resources/testharnessreport.js"></script>
|
||||
|
||||
<script src="../util/helpers.js"></script>
|
||||
<div id=log></div>
|
||||
<script src="../../WebCryptoAPI/encrypt_decrypt/chacha20_poly1305.tentative.https.any.js"></script>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
// META: title=WebCryptoAPI: encrypt()/decrypt() ChaCha20-Poly1305
|
||||
// META: timeout=long
|
||||
// META: script=../util/helpers.js
|
||||
|
||||
var subtle = crypto.subtle; // Change to test prefixed implementations
|
||||
|
||||
@@ -120,20 +121,6 @@ var encryptedData = {
|
||||
},
|
||||
};
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
// Test ChaCha20-Poly1305 encryption/decryption
|
||||
var algorithmName = 'ChaCha20-Poly1305';
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ function run_test() {
|
||||
.then(function(plaintext) {
|
||||
assert_true(equalBuffers(plaintext, vector.plaintext, "Decryption works"));
|
||||
}, function(err) {
|
||||
assert_unreached("Decryption should not throw error " + vector.name + ": " + err.message + "'");
|
||||
assert_unreached("Decryption should not throw error " + vector.name + ": '" + err.message + "'");
|
||||
});
|
||||
}, vector.name + " decryption");
|
||||
|
||||
@@ -40,7 +40,45 @@ function run_test() {
|
||||
all_promises.push(promise);
|
||||
});
|
||||
|
||||
// Test decryption with an altered buffer
|
||||
// Test decryption with an altered buffer during call
|
||||
passingVectors.forEach(function(vector) {
|
||||
var promise = importVectorKeys(vector, ["encrypt"], ["decrypt"])
|
||||
.then(function(vectors) {
|
||||
// Get a one byte longer plaintext to encrypt
|
||||
if (!("ciphertext" in vector)) {
|
||||
return;
|
||||
}
|
||||
|
||||
promise_test(function(test) {
|
||||
var ciphertext = copyBuffer(vector.ciphertext);
|
||||
ciphertext[0] = 255 - ciphertext[0];
|
||||
var operation = subtle.decrypt({
|
||||
...vector.algorithm,
|
||||
get name() {
|
||||
ciphertext[0] = vector.ciphertext[0];
|
||||
return vector.algorithm.name;
|
||||
}
|
||||
}, vector.privateKey, ciphertext)
|
||||
.then(function(plaintext) {
|
||||
assert_true(equalBuffers(plaintext, vector.plaintext, "Decryption works"));
|
||||
}, function(err) {
|
||||
assert_unreached("Decryption should not throw error " + vector.name + ": '" + err.message + "'");
|
||||
});
|
||||
return operation;
|
||||
}, vector.name + " decryption with altered ciphertext during call");
|
||||
|
||||
}, function(err) {
|
||||
// We need a failed test if the importVectorKey operation fails, so
|
||||
// we know we never tested encryption
|
||||
promise_test(function(test) {
|
||||
assert_unreached("importVectorKeys failed for " + vector.name + ". Message: ''" + err.message + "''");
|
||||
}, "importVectorKeys step: " + vector.name + " decryption with altered ciphertext during call");
|
||||
});
|
||||
|
||||
all_promises.push(promise);
|
||||
});
|
||||
|
||||
// Test decryption with an altered buffer after call
|
||||
passingVectors.forEach(function(vector) {
|
||||
var promise = importVectorKeys(vector, ["encrypt"], ["decrypt"])
|
||||
.then(function(vectors) {
|
||||
@@ -55,18 +93,87 @@ function run_test() {
|
||||
.then(function(plaintext) {
|
||||
assert_true(equalBuffers(plaintext, vector.plaintext, "Decryption works"));
|
||||
}, function(err) {
|
||||
assert_unreached("Decryption should not throw error " + vector.name + ": " + err.message + "'");
|
||||
assert_unreached("Decryption should not throw error " + vector.name + ": '" + err.message + "'");
|
||||
});
|
||||
ciphertext[0] = 255 - ciphertext[0];
|
||||
return operation;
|
||||
}, vector.name + " decryption with altered ciphertext");
|
||||
}, vector.name + " decryption with altered ciphertext after call");
|
||||
|
||||
}, function(err) {
|
||||
// We need a failed test if the importVectorKey operation fails, so
|
||||
// we know we never tested encryption
|
||||
promise_test(function(test) {
|
||||
assert_unreached("importVectorKeys failed for " + vector.name + ". Message: ''" + err.message + "''");
|
||||
}, "importVectorKeys step: " + vector.name + " decryption with altered ciphertext");
|
||||
}, "importVectorKeys step: " + vector.name + " decryption with altered ciphertext after call");
|
||||
});
|
||||
|
||||
all_promises.push(promise);
|
||||
});
|
||||
|
||||
// Test decryption with a transferred buffer during call
|
||||
passingVectors.forEach(function(vector) {
|
||||
var promise = importVectorKeys(vector, ["encrypt"], ["decrypt"])
|
||||
.then(function(vectors) {
|
||||
// Get a one byte longer plaintext to encrypt
|
||||
if (!("ciphertext" in vector)) {
|
||||
return;
|
||||
}
|
||||
|
||||
promise_test(function(test) {
|
||||
var ciphertext = copyBuffer(vector.ciphertext);
|
||||
var operation = subtle.decrypt({
|
||||
...vector.algorithm,
|
||||
get name() {
|
||||
ciphertext.buffer.transfer();
|
||||
return vector.algorithm.name;
|
||||
}
|
||||
}, vector.privateKey, ciphertext)
|
||||
.then(function(plaintext) {
|
||||
assert_unreached("Decryption should not have succeeded for " + vector.name);
|
||||
}, function(err) {
|
||||
assert_equals(err.name, "OperationError", "Should throw OperationError instead of " + err.message);
|
||||
});
|
||||
return operation;
|
||||
}, vector.name + " decryption with transferred ciphertext during call");
|
||||
|
||||
}, function(err) {
|
||||
// We need a failed test if the importVectorKey operation fails, so
|
||||
// we know we never tested encryption
|
||||
promise_test(function(test) {
|
||||
assert_unreached("importVectorKeys failed for " + vector.name + ". Message: ''" + err.message + "''");
|
||||
}, "importVectorKeys step: " + vector.name + " decryption with transferred ciphertext during call");
|
||||
});
|
||||
|
||||
all_promises.push(promise);
|
||||
});
|
||||
|
||||
// Test decryption with a transferred buffer after call
|
||||
passingVectors.forEach(function(vector) {
|
||||
var promise = importVectorKeys(vector, ["encrypt"], ["decrypt"])
|
||||
.then(function(vectors) {
|
||||
// Get a one byte longer plaintext to encrypt
|
||||
if (!("ciphertext" in vector)) {
|
||||
return;
|
||||
}
|
||||
|
||||
promise_test(function(test) {
|
||||
var ciphertext = copyBuffer(vector.ciphertext);
|
||||
var operation = subtle.decrypt(vector.algorithm, vector.privateKey, ciphertext)
|
||||
.then(function(plaintext) {
|
||||
assert_true(equalBuffers(plaintext, vector.plaintext, "Decryption works"));
|
||||
}, function(err) {
|
||||
assert_unreached("Decryption should not throw error " + vector.name + ": '" + err.message + "'");
|
||||
});
|
||||
ciphertext.buffer.transfer();
|
||||
return operation;
|
||||
}, vector.name + " decryption with transferred ciphertext after call");
|
||||
|
||||
}, function(err) {
|
||||
// We need a failed test if the importVectorKey operation fails, so
|
||||
// we know we never tested encryption
|
||||
promise_test(function(test) {
|
||||
assert_unreached("importVectorKeys failed for " + vector.name + ". Message: ''" + err.message + "''");
|
||||
}, "importVectorKeys step: " + vector.name + " decryption with transferred ciphertext after call");
|
||||
});
|
||||
|
||||
all_promises.push(promise);
|
||||
@@ -79,7 +186,7 @@ function run_test() {
|
||||
promise_test(function(test) {
|
||||
return subtle.decrypt(vector.algorithm, vector.publicKey, vector.ciphertext)
|
||||
.then(function(plaintext) {
|
||||
assert_unreached("Should have thrown error for using publicKey to decrypt in " + vector.name + ": " + err.message + "'");
|
||||
assert_unreached("Should have thrown error for using publicKey to decrypt in " + vector.name + ": '" + err.message + "'");
|
||||
}, function(err) {
|
||||
assert_equals(err.name, "InvalidAccessError", "Should throw InvalidAccessError instead of " + err.message);
|
||||
});
|
||||
@@ -107,7 +214,7 @@ function run_test() {
|
||||
promise_test(function(test) {
|
||||
return subtle.decrypt(vector.algorithm, vector.publicKey, vector.ciphertext)
|
||||
.then(function(plaintext) {
|
||||
assert_unreached("Should have thrown error for no decrypt usage in " + vector.name + ": " + err.message + "'");
|
||||
assert_unreached("Should have thrown error for no decrypt usage in " + vector.name + ": '" + err.message + "'");
|
||||
}, function(err) {
|
||||
assert_equals(err.name, "InvalidAccessError", "Should throw InvalidAccessError instead of " + err.message);
|
||||
});
|
||||
@@ -125,6 +232,57 @@ function run_test() {
|
||||
});
|
||||
|
||||
|
||||
// Check for successful encryption even if plaintext is altered during call.
|
||||
passingVectors.forEach(function(vector) {
|
||||
var promise = importVectorKeys(vector, ["encrypt"], ["decrypt"])
|
||||
.then(function(vectors) {
|
||||
promise_test(function(test) {
|
||||
var plaintext = copyBuffer(vector.plaintext);
|
||||
plaintext[0] = 255 - plaintext[0];
|
||||
var operation = subtle.encrypt({
|
||||
...vector.algorithm,
|
||||
get name() {
|
||||
plaintext[0] = vector.plaintext[0];
|
||||
return vector.algorithm.name;
|
||||
}
|
||||
}, vector.publicKey, plaintext)
|
||||
.then(function(ciphertext) {
|
||||
assert_equals(ciphertext.byteLength * 8, vector.privateKey.algorithm.modulusLength, "Ciphertext length matches modulus length");
|
||||
// Can we get the original plaintext back via decrypt?
|
||||
return subtle.decrypt(vector.algorithm, vector.privateKey, ciphertext)
|
||||
.then(function(result) {
|
||||
assert_true(equalBuffers(result, vector.plaintext), "Round trip returns original plaintext");
|
||||
return ciphertext;
|
||||
}, function(err) {
|
||||
assert_unreached("decrypt error for test " + vector.name + ": '" + err.message + "'");
|
||||
});
|
||||
})
|
||||
.then(function(priorCiphertext) {
|
||||
// Will a second encrypt give us different ciphertext, as it should?
|
||||
return subtle.encrypt(vector.algorithm, vector.publicKey, vector.plaintext)
|
||||
.then(function(ciphertext) {
|
||||
assert_false(equalBuffers(priorCiphertext, ciphertext), "Two encrypts give different results")
|
||||
}, function(err) {
|
||||
assert_unreached("second time encrypt error for test " + vector.name + ": '" + err.message + "'");
|
||||
});
|
||||
}, function(err) {
|
||||
assert_unreached("decrypt error for test " + vector.name + ": '" + err.message + "'");
|
||||
});
|
||||
|
||||
return operation;
|
||||
}, vector.name + " with altered plaintext during call");
|
||||
|
||||
}, function(err) {
|
||||
// We need a failed test if the importVectorKey operation fails, so
|
||||
// we know we never tested encryption
|
||||
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 encryption even if plaintext is altered after call.
|
||||
passingVectors.forEach(function(vector) {
|
||||
var promise = importVectorKeys(vector, ["encrypt"], ["decrypt"])
|
||||
@@ -140,7 +298,7 @@ function run_test() {
|
||||
assert_true(equalBuffers(result, vector.plaintext), "Round trip returns original plaintext");
|
||||
return ciphertext;
|
||||
}, function(err) {
|
||||
assert_unreached("decrypt error for test " + vector.name + ": " + err.message + "'");
|
||||
assert_unreached("decrypt error for test " + vector.name + ": '" + err.message + "'");
|
||||
});
|
||||
})
|
||||
.then(function(priorCiphertext) {
|
||||
@@ -157,14 +315,100 @@ function run_test() {
|
||||
|
||||
plaintext[0] = 255 - plaintext[0];
|
||||
return operation;
|
||||
}, vector.name + " with altered plaintext");
|
||||
}, vector.name + " with altered plaintext after call");
|
||||
|
||||
}, function(err) {
|
||||
// We need a failed test if the importVectorKey operation fails, so
|
||||
// we know we never tested encryption
|
||||
promise_test(function(test) {
|
||||
assert_unreached("importVectorKeys failed for " + vector.name + ". Message: ''" + err.message + "''");
|
||||
}, "importVectorKeys step: " + vector.name + " with altered plaintext");
|
||||
}, "importVectorKeys step: " + vector.name + " with altered plaintext after call");
|
||||
});
|
||||
|
||||
all_promises.push(promise);
|
||||
});
|
||||
|
||||
// Check for encryption of an empty value if plaintext is transferred during call.
|
||||
passingVectors.forEach(function(vector) {
|
||||
var promise = importVectorKeys(vector, ["encrypt"], ["decrypt"])
|
||||
.then(function(vectors) {
|
||||
promise_test(function(test) {
|
||||
var plaintext = copyBuffer(vector.plaintext);
|
||||
var operation = subtle.encrypt({
|
||||
...vector.algorithm,
|
||||
get name() {
|
||||
plaintext.buffer.transfer();
|
||||
return vector.algorithm.name;
|
||||
}
|
||||
}, vector.publicKey, plaintext)
|
||||
.then(function(ciphertext) {
|
||||
assert_equals(ciphertext.byteLength * 8, vector.privateKey.algorithm.modulusLength, "Ciphertext length matches modulus length");
|
||||
// Do we get an empty plaintext back via decrypt?
|
||||
return subtle.decrypt(vector.algorithm, vector.privateKey, ciphertext)
|
||||
.then(function(result) {
|
||||
assert_equals(result.byteLength, 0, "Decryption returns empty plaintext");
|
||||
return ciphertext;
|
||||
}, function(err) {
|
||||
assert_unreached("decrypt error for test " + vector.name + ": '" + err.message + "'");
|
||||
});
|
||||
}, function(err) {
|
||||
assert_unreached("encrypt error for test " + vector.name + ": '" + err.message + "'");
|
||||
});
|
||||
|
||||
return operation;
|
||||
}, vector.name + " with transferred plaintext during call");
|
||||
|
||||
}, function(err) {
|
||||
// We need a failed test if the importVectorKey operation fails, so
|
||||
// we know we never tested encryption
|
||||
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 encryption even if plaintext is transferred after call.
|
||||
passingVectors.forEach(function(vector) {
|
||||
var promise = importVectorKeys(vector, ["encrypt"], ["decrypt"])
|
||||
.then(function(vectors) {
|
||||
promise_test(function(test) {
|
||||
var plaintext = copyBuffer(vector.plaintext);
|
||||
var operation = subtle.encrypt(vector.algorithm, vector.publicKey, plaintext)
|
||||
.then(function(ciphertext) {
|
||||
assert_equals(ciphertext.byteLength * 8, vector.privateKey.algorithm.modulusLength, "Ciphertext length matches modulus length");
|
||||
// Can we get the original plaintext back via decrypt?
|
||||
return subtle.decrypt(vector.algorithm, vector.privateKey, ciphertext)
|
||||
.then(function(result) {
|
||||
assert_true(equalBuffers(result, vector.plaintext), "Round trip returns original plaintext");
|
||||
return ciphertext;
|
||||
}, function(err) {
|
||||
assert_unreached("decrypt error for test " + vector.name + ": '" + err.message + "'");
|
||||
});
|
||||
})
|
||||
.then(function(priorCiphertext) {
|
||||
// Will a second encrypt give us different ciphertext, as it should?
|
||||
return subtle.encrypt(vector.algorithm, vector.publicKey, vector.plaintext)
|
||||
.then(function(ciphertext) {
|
||||
assert_false(equalBuffers(priorCiphertext, ciphertext), "Two encrypts give different results")
|
||||
}, function(err) {
|
||||
assert_unreached("second time encrypt error for test " + vector.name + ": '" + err.message + "'");
|
||||
});
|
||||
}, function(err) {
|
||||
assert_unreached("decrypt error for test " + vector.name + ": '" + err.message + "'");
|
||||
});
|
||||
|
||||
plaintext.buffer.transfer();
|
||||
return operation;
|
||||
}, vector.name + " with transferred plaintext after call");
|
||||
|
||||
}, function(err) {
|
||||
// We need a failed test if the importVectorKey operation fails, so
|
||||
// we know we never tested encryption
|
||||
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);
|
||||
@@ -185,7 +429,7 @@ function run_test() {
|
||||
assert_true(equalBuffers(result, vector.plaintext), "Round trip returns original plaintext");
|
||||
return ciphertext;
|
||||
}, function(err) {
|
||||
assert_unreached("decrypt error for test " + vector.name + ": " + err.message + "'");
|
||||
assert_unreached("decrypt error for test " + vector.name + ": '" + err.message + "'");
|
||||
});
|
||||
})
|
||||
.then(function(priorCiphertext) {
|
||||
@@ -223,7 +467,7 @@ function run_test() {
|
||||
promise_test(function(test) {
|
||||
return subtle.encrypt(vector.algorithm, vector.publicKey, plaintext)
|
||||
.then(function(ciphertext) {
|
||||
assert_unreached("Should have thrown error for too long plaintext in " + vector.name + ": " + err.message + "'");
|
||||
assert_unreached("Should have thrown error for too long plaintext in " + vector.name + ": '" + err.message + "'");
|
||||
}, function(err) {
|
||||
assert_equals(err.name, "OperationError", "Should throw OperationError instead of " + err.message);
|
||||
});
|
||||
@@ -248,7 +492,7 @@ function run_test() {
|
||||
promise_test(function(test) {
|
||||
return subtle.encrypt(vector.algorithm, vector.privateKey, vector.plaintext)
|
||||
.then(function(ciphertext) {
|
||||
assert_unreached("Should have thrown error for using privateKey to encrypt in " + vector.name + ": " + err.message + "'");
|
||||
assert_unreached("Should have thrown error for using privateKey to encrypt in " + vector.name + ": '" + err.message + "'");
|
||||
}, function(err) {
|
||||
assert_equals(err.name, "InvalidAccessError", "Should throw InvalidAccessError instead of " + err.message);
|
||||
});
|
||||
@@ -276,7 +520,7 @@ function run_test() {
|
||||
promise_test(function(test) {
|
||||
return subtle.encrypt(vector.algorithm, vector.publicKey, vector.plaintext)
|
||||
.then(function(ciphertext) {
|
||||
assert_unreached("Should have thrown error for no encrypt usage in " + vector.name + ": " + err.message + "'");
|
||||
assert_unreached("Should have thrown error for no encrypt usage in " + vector.name + ": '" + err.message + "'");
|
||||
}, function(err) {
|
||||
assert_equals(err.name, "InvalidAccessError", "Should throw InvalidAccessError instead of " + err.message);
|
||||
});
|
||||
@@ -316,18 +560,7 @@ function run_test() {
|
||||
.then(function(key) {
|
||||
vector.publicKey = 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;
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
if (vector.privateKey !== null) {
|
||||
@@ -345,34 +578,5 @@ function run_test() {
|
||||
return Promise.all([publicPromise, privatePromise]);
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ self.GLOBAL = {
|
||||
</script>
|
||||
<script src="../../resources/testharness.js"></script>
|
||||
<script src="../../resources/testharnessreport.js"></script>
|
||||
<script src="../util/helpers.js"></script>
|
||||
<script src="rsa_vectors.js"></script>
|
||||
<script src="rsa.js"></script>
|
||||
<div id=log></div>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
// META: title=WebCryptoAPI: encrypt() Using RSA-OAEP
|
||||
// META: script=../util/helpers.js
|
||||
// META: script=rsa_vectors.js
|
||||
// META: script=rsa.js
|
||||
// META: timeout=long
|
||||
|
||||
Reference in New Issue
Block a user