in src/bun.js/bindings/webcrypto/CryptoKeyRSA.cpp [38:132]
RefPtr<CryptoKeyRSA> CryptoKeyRSA::importJwk(CryptoAlgorithmIdentifier algorithm, std::optional<CryptoAlgorithmIdentifier> hash, JsonWebKey&& keyData, bool extractable, CryptoKeyUsageBitmap usages)
{
if (keyData.kty != "RSA"_s)
return nullptr;
if (keyData.key_ops && ((keyData.usages & usages) != usages))
return nullptr;
if (keyData.ext && !keyData.ext.value() && extractable)
return nullptr;
if (keyData.n.isNull() || keyData.e.isNull())
return nullptr;
auto modulus = base64URLDecode(keyData.n);
if (!modulus)
return nullptr;
// Per RFC 7518 Section 6.3.1.1: https://tools.ietf.org/html/rfc7518#section-6.3.1.1
if (!modulus->isEmpty() && !modulus->at(0))
modulus->remove(0);
auto exponent = base64URLDecode(keyData.e);
if (!exponent)
return nullptr;
if (keyData.d.isNull()) {
// import public key
auto publicKeyComponents = CryptoKeyRSAComponents::createPublic(WTFMove(*modulus), WTFMove(*exponent));
// 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, *publicKeyComponents, extractable, usages);
}
// import private key
auto privateExponent = base64URLDecode(keyData.d);
if (!privateExponent)
return nullptr;
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);
}
if (keyData.p.isNull() || keyData.q.isNull() || keyData.dp.isNull() || keyData.dq.isNull() || keyData.qi.isNull())
return nullptr;
auto firstPrimeFactor = base64URLDecode(keyData.p);
if (!firstPrimeFactor)
return nullptr;
auto firstFactorCRTExponent = base64URLDecode(keyData.dp);
if (!firstFactorCRTExponent)
return nullptr;
auto secondPrimeFactor = base64URLDecode(keyData.q);
if (!secondPrimeFactor)
return nullptr;
auto secondFactorCRTExponent = base64URLDecode(keyData.dq);
if (!secondFactorCRTExponent)
return nullptr;
auto secondFactorCRTCoefficient = base64URLDecode(keyData.qi);
if (!secondFactorCRTCoefficient)
return nullptr;
CryptoKeyRSAComponents::PrimeInfo firstPrimeInfo;
firstPrimeInfo.primeFactor = WTFMove(*firstPrimeFactor);
firstPrimeInfo.factorCRTExponent = WTFMove(*firstFactorCRTExponent);
CryptoKeyRSAComponents::PrimeInfo secondPrimeInfo;
secondPrimeInfo.primeFactor = WTFMove(*secondPrimeFactor);
secondPrimeInfo.factorCRTExponent = WTFMove(*secondFactorCRTExponent);
secondPrimeInfo.factorCRTCoefficient = WTFMove(*secondFactorCRTCoefficient);
if (!keyData.oth) {
auto privateKeyComponents = CryptoKeyRSAComponents::createPrivateWithAdditionalData(WTFMove(*modulus), WTFMove(*exponent), WTFMove(*privateExponent), WTFMove(firstPrimeInfo), WTFMove(secondPrimeInfo), {});
// 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);
}
Vector<CryptoKeyRSAComponents::PrimeInfo> otherPrimeInfos;
for (const auto& value : keyData.oth.value()) {
auto primeFactor = base64URLDecode(value.r);
if (!primeFactor)
return nullptr;
auto factorCRTExponent = base64URLDecode(value.d);
if (!factorCRTExponent)
return nullptr;
auto factorCRTCoefficient = base64URLDecode(value.t);
if (!factorCRTCoefficient)
return nullptr;
CryptoKeyRSAComponents::PrimeInfo info;
info.primeFactor = WTFMove(*primeFactor);
info.factorCRTExponent = WTFMove(*factorCRTExponent);
info.factorCRTCoefficient = WTFMove(*factorCRTCoefficient);
otherPrimeInfos.append(WTFMove(info));
}
auto privateKeyComponents = CryptoKeyRSAComponents::createPrivateWithAdditionalData(WTFMove(*modulus), WTFMove(*exponent), WTFMove(*privateExponent), WTFMove(firstPrimeInfo), WTFMove(secondPrimeInfo), WTFMove(otherPrimeInfos));
// 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);
}