mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-10-23 08:30:50 +00:00
Some checks are pending
CI / Linux, x86_64, Fuzzers_CI, Clang (push) Waiting to run
CI / macOS, arm64, Sanitizer_CI, Clang (push) Waiting to run
CI / Linux, x86_64, Sanitizer_CI, GNU (push) Waiting to run
CI / Linux, x86_64, Sanitizer_CI, Clang (push) Waiting to run
Package the js repl as a binary artifact / Linux, arm64 (push) Waiting to run
Package the js repl as a binary artifact / macOS, arm64 (push) Waiting to run
Package the js repl as a binary artifact / Linux, x86_64 (push) Waiting to run
Run test262 and test-wasm / run_and_update_results (push) Waiting to run
Lint Code / lint (push) Waiting to run
Label PRs with merge conflicts / auto-labeler (push) Waiting to run
Push notes / build (push) Waiting to run
Fix various TODO by checking the validity of RSA keys when they are imported. Also add some internal tests since WPT doesn't seem to provide them.
80 lines
2.8 KiB
HTML
80 lines
2.8 KiB
HTML
<!DOCTYPE html>
|
|
<script src="../include.js"></script>
|
|
<script>
|
|
function b64ToBn(b64) {
|
|
const bin = atob(b64.replace(/-/g, '+').replace(/_/g, '/'));
|
|
const hex = bin.split('').map((ch) => ch.charCodeAt(0).toString(16).padStart(2, '0')).join('');
|
|
return [BigInt('0x' + hex), bin.length];
|
|
}
|
|
|
|
function bnToB64(bn, len) {
|
|
const hex = bn.toString(16);
|
|
const bin = hex.match(/.{1,2}/g).map((byte) => String.fromCharCode(parseInt(byte, 16))).join('');
|
|
return btoa(bin.padStart(len, '\x00')).replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
|
|
}
|
|
|
|
function corruptJwk(key) {
|
|
const [bn, len] = b64ToBn(key.d);
|
|
|
|
// Corrupt the private key
|
|
return {
|
|
...key,
|
|
d: bnToB64(bn ^ 1n, len),
|
|
};
|
|
}
|
|
|
|
function corruptPkcs8Pub(privateKey) {
|
|
// Corrupt the public key, which is encoded between 33 and 165 for the PKCS8
|
|
const corrupted = new Uint8Array(privateKey);
|
|
corrupted[128] ^= 0x01;
|
|
return corrupted.buffer;
|
|
}
|
|
|
|
function corruptPkcs8Priv(privateKey) {
|
|
// Corrupt a piece of the private key, which is encoded at the end of the PKCS8
|
|
const corrupted = new Uint8Array(privateKey);
|
|
corrupted[corrupted.length - 20] ^= 0x01;
|
|
return corrupted.buffer;
|
|
}
|
|
|
|
asyncTest(async done => {
|
|
for (const [name, genUsages, privUsages] of [
|
|
["RSASSA-PKCS1-v1_5", ["sign", "verify"], ["sign"]],
|
|
["RSA-PSS", ["sign", "verify"], ["sign"]],
|
|
["RSA-OAEP", ["encrypt", "decrypt"], ["decrypt"]],
|
|
]) {
|
|
for (const hash of ["SHA-1", "SHA-256", "SHA-384", "SHA-512"]) {
|
|
const keyPair = await window.crypto.subtle.generateKey({
|
|
name: name,
|
|
hash: hash,
|
|
modulusLength: 1024,
|
|
publicExponent: new Uint8Array([1, 0, 1]),
|
|
}, true, genUsages);
|
|
|
|
// NOTE: We don't check the public key for RSA since it's harder to corrupt.
|
|
|
|
for (const [format, corruptFn] of [["jwk", corruptJwk], ["pkcs8", corruptPkcs8Priv], ["pkcs8", corruptPkcs8Pub]]) {
|
|
const privateKey = await window.crypto.subtle.exportKey(format, keyPair.privateKey);
|
|
|
|
// Prove that the original key can be imported successfully
|
|
await window.crypto.subtle.importKey(format, privateKey, {name: name, hash: hash,}, false, privUsages);
|
|
|
|
// Corrupt the private key and try to import it
|
|
const corruptedPrivateKey = corruptFn(privateKey);
|
|
|
|
try {
|
|
await window.crypto.subtle.importKey(format, corruptedPrivateKey, {
|
|
name: name,
|
|
hash: hash,
|
|
}, false, privUsages);
|
|
println(`${name.padEnd(5, ' ')} ${hash} PRIV - ${format.padEnd(5, ' ')} FAILED`);
|
|
} catch (e) {
|
|
println(`${name.padEnd(5, ' ')} ${hash} PRIV - ${format.padEnd(5, ' ')} OK: ${e}`);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
done();
|
|
});
|
|
</script>
|