mirror of
https://github.com/oven-sh/bun
synced 2026-02-02 15:08:46 +00:00
Revert "Fix RSA JWK import validation bug causing Jose library failures" (#22307)
Test did not fail in previous build of Bun Reverts oven-sh/bun#22264
This commit is contained in:
12
package.json
12
package.json
@@ -1,6 +1,11 @@
|
||||
{
|
||||
"private": true,
|
||||
"name": "bun",
|
||||
"version": "1.2.22",
|
||||
"workspaces": [
|
||||
"./packages/bun-types",
|
||||
"./packages/@types/bun"
|
||||
],
|
||||
"devDependencies": {
|
||||
"@lezer/common": "^1.2.3",
|
||||
"@lezer/cpp": "^1.1.3",
|
||||
@@ -16,7 +21,6 @@
|
||||
"source-map-js": "^1.2.0",
|
||||
"typescript": "5.9.2"
|
||||
},
|
||||
"private": true,
|
||||
"resolutions": {
|
||||
"bun-types": "workspace:packages/bun-types",
|
||||
"@types/bun": "workspace:packages/@types/bun"
|
||||
@@ -81,9 +85,5 @@
|
||||
"node:test:cp": "bun ./scripts/fetch-node-test.ts ",
|
||||
"clean:zig": "rm -rf build/debug/cache/zig build/debug/CMakeCache.txt 'build/debug/*.o' .zig-cache zig-out || true",
|
||||
"sync-webkit-source": "bun ./scripts/sync-webkit-source.ts"
|
||||
},
|
||||
"workspaces": [
|
||||
"./packages/bun-types",
|
||||
"./packages/@types/bun"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,7 +66,7 @@ RefPtr<CryptoKeyRSA> CryptoKeyRSA::importJwk(CryptoAlgorithmIdentifier algorithm
|
||||
auto privateExponent = base64URLDecode(keyData.d);
|
||||
if (!privateExponent)
|
||||
return nullptr;
|
||||
if (keyData.p.isNull() && keyData.q.isNull() && keyData.dp.isNull() && keyData.dq.isNull() && keyData.qi.isNull()) {
|
||||
if (keyData.p.isNull() && keyData.q.isNull() && keyData.dp.isNull() && keyData.dp.isNull() && keyData.qi.isNull()) {
|
||||
auto privateKeyComponents = CryptoKeyRSAComponents::createPrivate(WTFMove(*modulus), WTFMove(*exponent), WTFMove(*privateExponent));
|
||||
// Notice: CryptoAlgorithmIdentifier::SHA_1 is just a placeholder. It should not have any effect if hash is std::nullopt.
|
||||
return CryptoKeyRSA::create(algorithm, hash.value_or(CryptoAlgorithmIdentifier::SHA_1), !!hash, *privateKeyComponents, extractable, usages);
|
||||
|
||||
@@ -125,10 +125,10 @@ static ExceptionOr<std::unique_ptr<CryptoAlgorithmParameters>> normalizeCryptoAl
|
||||
|
||||
auto identifier = CryptoAlgorithmRegistry::singleton().identifier(params.name);
|
||||
if (!identifier) [[unlikely]]
|
||||
RELEASE_AND_RETURN(scope, Exception { NotSupportedError });
|
||||
return Exception { NotSupportedError };
|
||||
|
||||
if (*identifier == CryptoAlgorithmIdentifier::Ed25519 && !isSafeCurvesEnabled(state))
|
||||
RELEASE_AND_RETURN(scope, Exception { NotSupportedError });
|
||||
return Exception { NotSupportedError };
|
||||
|
||||
std::unique_ptr<CryptoAlgorithmParameters> result;
|
||||
switch (operation) {
|
||||
@@ -137,7 +137,7 @@ static ExceptionOr<std::unique_ptr<CryptoAlgorithmParameters>> normalizeCryptoAl
|
||||
switch (*identifier) {
|
||||
case CryptoAlgorithmIdentifier::RSAES_PKCS1_v1_5:
|
||||
if (isRSAESPKCSWebCryptoDeprecated(state))
|
||||
RELEASE_AND_RETURN(scope, (Exception { NotSupportedError, "RSAES-PKCS1-v1_5 support is deprecated"_s }));
|
||||
return Exception { NotSupportedError, "RSAES-PKCS1-v1_5 support is deprecated"_s };
|
||||
result = makeUnique<CryptoAlgorithmParameters>(params);
|
||||
break;
|
||||
case CryptoAlgorithmIdentifier::RSA_OAEP: {
|
||||
@@ -166,7 +166,7 @@ static ExceptionOr<std::unique_ptr<CryptoAlgorithmParameters>> normalizeCryptoAl
|
||||
break;
|
||||
}
|
||||
default:
|
||||
RELEASE_AND_RETURN(scope, Exception { NotSupportedError });
|
||||
return Exception { NotSupportedError };
|
||||
}
|
||||
break;
|
||||
case Operations::Sign:
|
||||
@@ -182,7 +182,7 @@ static ExceptionOr<std::unique_ptr<CryptoAlgorithmParameters>> normalizeCryptoAl
|
||||
RETURN_IF_EXCEPTION(scope, Exception { ExistingExceptionError });
|
||||
auto hashIdentifier = toHashIdentifier(state, params.hash);
|
||||
RETURN_IF_EXCEPTION(scope, Exception { ExistingExceptionError });
|
||||
if (hashIdentifier.hasException()) RELEASE_AND_RETURN(scope, hashIdentifier.releaseException());
|
||||
if (hashIdentifier.hasException()) return hashIdentifier.releaseException();
|
||||
params.hashIdentifier = hashIdentifier.releaseReturnValue();
|
||||
result = makeUnique<CryptoAlgorithmEcdsaParams>(params);
|
||||
break;
|
||||
@@ -194,7 +194,7 @@ static ExceptionOr<std::unique_ptr<CryptoAlgorithmParameters>> normalizeCryptoAl
|
||||
break;
|
||||
}
|
||||
default:
|
||||
RELEASE_AND_RETURN(scope, Exception { NotSupportedError });
|
||||
return Exception { NotSupportedError };
|
||||
}
|
||||
break;
|
||||
case Operations::Digest:
|
||||
@@ -207,14 +207,14 @@ static ExceptionOr<std::unique_ptr<CryptoAlgorithmParameters>> normalizeCryptoAl
|
||||
result = makeUnique<CryptoAlgorithmParameters>(params);
|
||||
break;
|
||||
default:
|
||||
RELEASE_AND_RETURN(scope, Exception { NotSupportedError });
|
||||
return Exception { NotSupportedError };
|
||||
}
|
||||
break;
|
||||
case Operations::GenerateKey:
|
||||
switch (*identifier) {
|
||||
case CryptoAlgorithmIdentifier::RSAES_PKCS1_v1_5: {
|
||||
if (isRSAESPKCSWebCryptoDeprecated(state))
|
||||
RELEASE_AND_RETURN(scope, (Exception { NotSupportedError, "RSAES-PKCS1-v1_5 support is deprecated"_s }));
|
||||
return Exception { NotSupportedError, "RSAES-PKCS1-v1_5 support is deprecated"_s };
|
||||
auto params = convertDictionary<CryptoAlgorithmRsaKeyGenParams>(state, value.get());
|
||||
RETURN_IF_EXCEPTION(scope, Exception { ExistingExceptionError });
|
||||
result = makeUnique<CryptoAlgorithmRsaKeyGenParams>(params);
|
||||
@@ -227,7 +227,7 @@ static ExceptionOr<std::unique_ptr<CryptoAlgorithmParameters>> normalizeCryptoAl
|
||||
RETURN_IF_EXCEPTION(scope, Exception { ExistingExceptionError });
|
||||
auto hashIdentifier = toHashIdentifier(state, params.hash);
|
||||
RETURN_IF_EXCEPTION(scope, Exception { ExistingExceptionError });
|
||||
if (hashIdentifier.hasException()) RELEASE_AND_RETURN(scope, hashIdentifier.releaseException());
|
||||
if (hashIdentifier.hasException()) return hashIdentifier.releaseException();
|
||||
params.hashIdentifier = hashIdentifier.releaseReturnValue();
|
||||
result = makeUnique<CryptoAlgorithmRsaHashedKeyGenParams>(params);
|
||||
break;
|
||||
@@ -247,7 +247,7 @@ static ExceptionOr<std::unique_ptr<CryptoAlgorithmParameters>> normalizeCryptoAl
|
||||
RETURN_IF_EXCEPTION(scope, Exception { ExistingExceptionError });
|
||||
auto hashIdentifier = toHashIdentifier(state, params.hash);
|
||||
RETURN_IF_EXCEPTION(scope, Exception { ExistingExceptionError });
|
||||
if (hashIdentifier.hasException()) RELEASE_AND_RETURN(scope, hashIdentifier.releaseException());
|
||||
if (hashIdentifier.hasException()) return hashIdentifier.releaseException();
|
||||
params.hashIdentifier = hashIdentifier.releaseReturnValue();
|
||||
result = makeUnique<CryptoAlgorithmHmacKeyParams>(params);
|
||||
break;
|
||||
@@ -266,7 +266,7 @@ static ExceptionOr<std::unique_ptr<CryptoAlgorithmParameters>> normalizeCryptoAl
|
||||
result = makeUnique<CryptoAlgorithmParameters>(params);
|
||||
break;
|
||||
default:
|
||||
RELEASE_AND_RETURN(scope, Exception { NotSupportedError });
|
||||
return Exception { NotSupportedError };
|
||||
}
|
||||
break;
|
||||
case Operations::DeriveBits:
|
||||
@@ -302,7 +302,7 @@ static ExceptionOr<std::unique_ptr<CryptoAlgorithmParameters>> normalizeCryptoAl
|
||||
RETURN_IF_EXCEPTION(scope, Exception { ExistingExceptionError });
|
||||
auto hashIdentifier = toHashIdentifier(state, params.hash);
|
||||
RETURN_IF_EXCEPTION(scope, Exception { ExistingExceptionError });
|
||||
if (hashIdentifier.hasException()) RELEASE_AND_RETURN(scope, hashIdentifier.releaseException());
|
||||
if (hashIdentifier.hasException()) return hashIdentifier.releaseException();
|
||||
params.hashIdentifier = hashIdentifier.releaseReturnValue();
|
||||
result = makeUnique<CryptoAlgorithmHkdfParams>(params);
|
||||
break;
|
||||
@@ -312,20 +312,20 @@ static ExceptionOr<std::unique_ptr<CryptoAlgorithmParameters>> normalizeCryptoAl
|
||||
RETURN_IF_EXCEPTION(scope, Exception { ExistingExceptionError });
|
||||
auto hashIdentifier = toHashIdentifier(state, params.hash);
|
||||
RETURN_IF_EXCEPTION(scope, Exception { ExistingExceptionError });
|
||||
if (hashIdentifier.hasException()) RELEASE_AND_RETURN(scope, hashIdentifier.releaseException());
|
||||
if (hashIdentifier.hasException()) return hashIdentifier.releaseException();
|
||||
params.hashIdentifier = hashIdentifier.releaseReturnValue();
|
||||
result = makeUnique<CryptoAlgorithmPbkdf2Params>(params);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
RELEASE_AND_RETURN(scope, Exception { NotSupportedError });
|
||||
return Exception { NotSupportedError };
|
||||
}
|
||||
break;
|
||||
case Operations::ImportKey:
|
||||
switch (*identifier) {
|
||||
case CryptoAlgorithmIdentifier::RSAES_PKCS1_v1_5:
|
||||
if (isRSAESPKCSWebCryptoDeprecated(state))
|
||||
RELEASE_AND_RETURN(scope, (Exception { NotSupportedError, "RSAES-PKCS1-v1_5 support is deprecated"_s }));
|
||||
return Exception { NotSupportedError, "RSAES-PKCS1-v1_5 support is deprecated"_s };
|
||||
result = makeUnique<CryptoAlgorithmParameters>(params);
|
||||
break;
|
||||
case CryptoAlgorithmIdentifier::RSASSA_PKCS1_v1_5:
|
||||
@@ -335,7 +335,7 @@ static ExceptionOr<std::unique_ptr<CryptoAlgorithmParameters>> normalizeCryptoAl
|
||||
RETURN_IF_EXCEPTION(scope, Exception { ExistingExceptionError });
|
||||
auto hashIdentifier = toHashIdentifier(state, params.hash);
|
||||
RETURN_IF_EXCEPTION(scope, Exception { ExistingExceptionError });
|
||||
if (hashIdentifier.hasException()) RELEASE_AND_RETURN(scope, hashIdentifier.releaseException());
|
||||
if (hashIdentifier.hasException()) return hashIdentifier.releaseException();
|
||||
params.hashIdentifier = hashIdentifier.releaseReturnValue();
|
||||
result = makeUnique<CryptoAlgorithmRsaHashedImportParams>(params);
|
||||
break;
|
||||
@@ -354,7 +354,7 @@ static ExceptionOr<std::unique_ptr<CryptoAlgorithmParameters>> normalizeCryptoAl
|
||||
RETURN_IF_EXCEPTION(scope, Exception { ExistingExceptionError });
|
||||
auto hashIdentifier = toHashIdentifier(state, params.hash);
|
||||
RETURN_IF_EXCEPTION(scope, Exception { ExistingExceptionError });
|
||||
if (hashIdentifier.hasException()) RELEASE_AND_RETURN(scope, hashIdentifier.releaseException());
|
||||
if (hashIdentifier.hasException()) return hashIdentifier.releaseException();
|
||||
params.hashIdentifier = hashIdentifier.releaseReturnValue();
|
||||
result = makeUnique<CryptoAlgorithmHmacKeyParams>(params);
|
||||
break;
|
||||
@@ -375,9 +375,9 @@ static ExceptionOr<std::unique_ptr<CryptoAlgorithmParameters>> normalizeCryptoAl
|
||||
case CryptoAlgorithmIdentifier::SHA_256:
|
||||
case CryptoAlgorithmIdentifier::SHA_384:
|
||||
case CryptoAlgorithmIdentifier::SHA_512:
|
||||
RELEASE_AND_RETURN(scope, Exception { NotSupportedError });
|
||||
return Exception { NotSupportedError };
|
||||
case CryptoAlgorithmIdentifier::None:
|
||||
RELEASE_AND_RETURN(scope, Exception { NotSupportedError });
|
||||
return Exception { NotSupportedError };
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -388,7 +388,7 @@ static ExceptionOr<std::unique_ptr<CryptoAlgorithmParameters>> normalizeCryptoAl
|
||||
result = makeUnique<CryptoAlgorithmParameters>(params);
|
||||
break;
|
||||
default:
|
||||
RELEASE_AND_RETURN(scope, Exception { NotSupportedError });
|
||||
return Exception { NotSupportedError };
|
||||
}
|
||||
break;
|
||||
case Operations::GetKeyLength:
|
||||
@@ -408,7 +408,7 @@ static ExceptionOr<std::unique_ptr<CryptoAlgorithmParameters>> normalizeCryptoAl
|
||||
RETURN_IF_EXCEPTION(scope, Exception { ExistingExceptionError });
|
||||
auto hashIdentifier = toHashIdentifier(state, params.hash);
|
||||
RETURN_IF_EXCEPTION(scope, Exception { ExistingExceptionError });
|
||||
if (hashIdentifier.hasException()) RELEASE_AND_RETURN(scope, hashIdentifier.releaseException());
|
||||
if (hashIdentifier.hasException()) return hashIdentifier.releaseException();
|
||||
params.hashIdentifier = hashIdentifier.releaseReturnValue();
|
||||
result = makeUnique<CryptoAlgorithmHmacKeyParams>(params);
|
||||
break;
|
||||
@@ -418,13 +418,13 @@ static ExceptionOr<std::unique_ptr<CryptoAlgorithmParameters>> normalizeCryptoAl
|
||||
result = makeUnique<CryptoAlgorithmParameters>(params);
|
||||
break;
|
||||
default:
|
||||
RELEASE_AND_RETURN(scope, Exception { NotSupportedError });
|
||||
return Exception { NotSupportedError };
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
result->identifier = *identifier;
|
||||
RELEASE_AND_RETURN(scope, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
static CryptoKeyUsageBitmap toCryptoKeyUsageBitmap(CryptoKeyUsage usage)
|
||||
@@ -801,9 +801,7 @@ void SubtleCrypto::generateKey(JSC::JSGlobalObject& state, AlgorithmIdentifier&&
|
||||
auto scope = DECLARE_THROW_SCOPE(vm);
|
||||
auto paramsOrException = normalizeCryptoAlgorithmParameters(state, WTFMove(algorithmIdentifier), Operations::GenerateKey);
|
||||
if (paramsOrException.hasException()) {
|
||||
auto exception = paramsOrException.releaseException();
|
||||
scope.release();
|
||||
promise->reject(exception);
|
||||
promise->reject(paramsOrException.releaseException());
|
||||
return;
|
||||
}
|
||||
auto params = paramsOrException.releaseReturnValue();
|
||||
|
||||
@@ -52,7 +52,6 @@
|
||||
"isbot": "5.1.13",
|
||||
"jest-extended": "4.0.0",
|
||||
"jimp": "1.6.0",
|
||||
"jose": "5.10.0",
|
||||
"jsdom": "25.0.1",
|
||||
"jsonwebtoken": "9.0.2",
|
||||
"jws": "4.0.0",
|
||||
@@ -1623,8 +1622,6 @@
|
||||
|
||||
"jimp": ["jimp@1.6.0", "", { "dependencies": { "@jimp/core": "1.6.0", "@jimp/diff": "1.6.0", "@jimp/js-bmp": "1.6.0", "@jimp/js-gif": "1.6.0", "@jimp/js-jpeg": "1.6.0", "@jimp/js-png": "1.6.0", "@jimp/js-tiff": "1.6.0", "@jimp/plugin-blit": "1.6.0", "@jimp/plugin-blur": "1.6.0", "@jimp/plugin-circle": "1.6.0", "@jimp/plugin-color": "1.6.0", "@jimp/plugin-contain": "1.6.0", "@jimp/plugin-cover": "1.6.0", "@jimp/plugin-crop": "1.6.0", "@jimp/plugin-displace": "1.6.0", "@jimp/plugin-dither": "1.6.0", "@jimp/plugin-fisheye": "1.6.0", "@jimp/plugin-flip": "1.6.0", "@jimp/plugin-hash": "1.6.0", "@jimp/plugin-mask": "1.6.0", "@jimp/plugin-print": "1.6.0", "@jimp/plugin-quantize": "1.6.0", "@jimp/plugin-resize": "1.6.0", "@jimp/plugin-rotate": "1.6.0", "@jimp/plugin-threshold": "1.6.0", "@jimp/types": "1.6.0", "@jimp/utils": "1.6.0" } }, "sha512-YcwCHw1kiqEeI5xRpDlPPBGL2EOpBKLwO4yIBJcXWHPj5PnA5urGq0jbyhM5KoNpypQ6VboSoxc9D8HyfvngSg=="],
|
||||
|
||||
"jose": ["jose@5.10.0", "", {}, "sha512-s+3Al/p9g32Iq+oqXxkW//7jk2Vig6FF1CFqzVXoTUXt2qz89YWbL+OwS17NFYEvxC35n0FKeGO2LGYSxeM2Gg=="],
|
||||
|
||||
"joycon": ["joycon@3.1.1", "", {}, "sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw=="],
|
||||
|
||||
"jpeg-js": ["jpeg-js@0.4.4", "", {}, "sha512-WZzeDOEtTOBK4Mdsar0IqEU5sMr3vSV2RqkAIzUEV2BHnUfKGyswWFPFwK5EeDo93K3FohSHbLAjj0s1Wzd+dg=="],
|
||||
|
||||
@@ -57,7 +57,6 @@
|
||||
"isbot": "5.1.13",
|
||||
"jest-extended": "4.0.0",
|
||||
"jimp": "1.6.0",
|
||||
"jose": "5.10.0",
|
||||
"jsdom": "25.0.1",
|
||||
"jsonwebtoken": "9.0.2",
|
||||
"jws": "4.0.0",
|
||||
|
||||
@@ -1,90 +0,0 @@
|
||||
import { beforeAll, expect, test } from "bun:test";
|
||||
import { importJWK } from "jose";
|
||||
|
||||
let fullPrivateJWK: JsonWebKey;
|
||||
let publicJWK: JsonWebKey;
|
||||
let minimalPrivateJWK: JsonWebKey;
|
||||
|
||||
beforeAll(async () => {
|
||||
const keyPair = await crypto.subtle.generateKey(
|
||||
{ name: "RSASSA-PKCS1-v1_5", modulusLength: 2048, publicExponent: new Uint8Array([1, 0, 1]), hash: "SHA-256" },
|
||||
true,
|
||||
["sign", "verify"],
|
||||
);
|
||||
fullPrivateJWK = await crypto.subtle.exportKey("jwk", keyPair.privateKey);
|
||||
publicJWK = await crypto.subtle.exportKey("jwk", keyPair.publicKey);
|
||||
minimalPrivateJWK = {
|
||||
kty: fullPrivateJWK.kty,
|
||||
n: fullPrivateJWK.n,
|
||||
e: fullPrivateJWK.e,
|
||||
d: fullPrivateJWK.d,
|
||||
} as JsonWebKey;
|
||||
});
|
||||
|
||||
test("RSA JWK import should work with valid private key", async () => {
|
||||
const importedKey = await crypto.subtle.importKey(
|
||||
"jwk",
|
||||
fullPrivateJWK,
|
||||
{
|
||||
name: "RSASSA-PKCS1-v1_5",
|
||||
hash: "SHA-256",
|
||||
},
|
||||
false,
|
||||
["sign"],
|
||||
);
|
||||
|
||||
expect(importedKey.type).toBe("private");
|
||||
expect(importedKey.algorithm.name).toBe("RSASSA-PKCS1-v1_5");
|
||||
expect(importedKey.algorithm.hash.name).toBe("SHA-256");
|
||||
expect(importedKey.usages).toEqual(["sign"]);
|
||||
expect(importedKey.extractable).toBe(false);
|
||||
});
|
||||
|
||||
test("RSA JWK import should work with public key", async () => {
|
||||
const importedKey = await crypto.subtle.importKey(
|
||||
"jwk",
|
||||
publicJWK,
|
||||
{
|
||||
name: "RSASSA-PKCS1-v1_5",
|
||||
hash: "SHA-256",
|
||||
},
|
||||
false,
|
||||
["verify"],
|
||||
);
|
||||
|
||||
expect(importedKey.type).toBe("public");
|
||||
expect(importedKey.algorithm.name).toBe("RSASSA-PKCS1-v1_5");
|
||||
expect(importedKey.usages).toEqual(["verify"]);
|
||||
});
|
||||
|
||||
test("RSA JWK import should reject minimal private key (no CRT params)", async () => {
|
||||
// Note: WebCrypto spec requires CRT parameters for RSA private keys
|
||||
// This test verifies that minimal private keys without CRT parameters are properly rejected
|
||||
await expect(
|
||||
crypto.subtle.importKey(
|
||||
"jwk",
|
||||
minimalPrivateJWK,
|
||||
{
|
||||
name: "RSASSA-PKCS1-v1_5",
|
||||
hash: "SHA-256",
|
||||
},
|
||||
false,
|
||||
["sign"],
|
||||
),
|
||||
).rejects.toThrow();
|
||||
});
|
||||
|
||||
test("RSA JWK import should reject partial CRT params", async () => {
|
||||
const partial = { ...fullPrivateJWK };
|
||||
// @ts-expect-error deleting for test
|
||||
delete (partial as any).dq;
|
||||
await expect(
|
||||
crypto.subtle.importKey("jwk", partial, { name: "RSASSA-PKCS1-v1_5", hash: "SHA-256" }, false, ["sign"]),
|
||||
).rejects.toThrow();
|
||||
});
|
||||
|
||||
test("Jose library should work with RSA JWK import after fix", async () => {
|
||||
// This should not throw a DataError after the fix
|
||||
const importedKey = await importJWK(fullPrivateJWK, "RS256");
|
||||
expect(importedKey).toBeDefined();
|
||||
});
|
||||
Reference in New Issue
Block a user