javascript - 网络工作者环境中 JWK 的 x509 公钥
问题描述
我想在“Cloudflare 工作者”环境中验证“firebase JWT 令牌” 。
问题是 firebase-auth不提供标准/.well-known/jwks.json
,而是提供x806 public key certificate
(pem)格式
我正在使用“Webcrypto API”来完成加密工作,这就是我要做的
// Get CryptoKey
const key = await crypto.subtle.importKey(
"jwk", // it's possible to change this format if the pem can be changed to other standards
jwk, // ?? Here is the missing piece
{ name: "RSASSA-PKCS1-v1_5", hash: "SHA-256" },
false,
["verify"]
);
// Verify
const success = await crypto.subtle.verify(
"RSASSA-PKCS1-v1_5",
key,
signature, // JWT signature
data // JWT payload
);
我在 Github 上尝试了几个包,我发现的所有库要么不起作用,要么使用在 CF 环境中不起作用的 nodejs API(例如缓冲区)
有人可以指点我如何
- 将 firebase 公钥转换为 JWK 或
- 将公钥转换为可以接受的其他标准(
"raw" | "pkcs8" | "spki"
)importKey
注意:我们在“CF Workers”环境中,所以所有“nodejs”api 都不起作用
谢谢
解决方案
我不确定您对 CF 工作人员有什么可用的,但这可能是从以下内容开始:
const forge = require('node-forge')
const NodeRSA = require('node-rsa')
const {createHash} = require('crypto')
const base64url = require('base64url')
const getCertificateDer = certPem => {
return forge.util.encode64(
forge.asn1
.toDer(forge.pki.certificateToAsn1(forge.pki.certificateFromPem(certPem)))
.getBytes(),
)
}
const getModulusExponent = certPem => {
const nodeRsa = new NodeRSA()
nodeRsa.importKey(certPem)
const {n: modulus, e: exponent} = nodeRsa.exportKey('components-public')
return {
modulus,
exponent,
}
}
const getCertThumbprint = certDer => {
const derBinaryStr = Buffer.from(certDer).toString('binary')
const shasum = createHash('sha1')
shasum.update(derBinaryStr)
return shasum.digest('base64')
}
const getCertThumbprintEncoded = certDer => base64url.encode(getCertThumbprint(certDer))
const certPem = "<your pem certificate>"
const {modulus, exponent} = getModulusExponent(certPem)
const certDer = getCertificateDer(certPem)
const thumbprintEncoded = getCertThumbprintEncoded(certDer)
const jwksInfo = {
alg: 'RSA256',
kty: 'RSA',
use: 'sig',
x5c: [certDer],
e: String(exponent),
n: modulus.toString('base64'),
kid: thumbprintEncoded,
x5t: thumbprintEncoded,
}
由于您不能使用 Buffer 并且可能无法使用节点的加密库,因此您必须找到该getCertThumbprint
功能的替代品。但它所做的只是创建一个 sha1 哈希certDer
并对其进行 base64 编码,因此这可能并不困难。
更新:这可能会替代getCertThumbprint
. 我做了一些测试,它似乎返回了与上面相同的值,但我没有用它来验证 JWT。
const sha1 = require('sha1')
const getCertThumbprint = certDer => btoa(sha1(certDer))
推荐阅读
- javascript - 将英语转换为尼泊尔语打字 JS。当我按 A 时,它应该被翻译成ब等等
- excel - Excel:如何通过 VBA 搜索电子表格 2 中是否存在电子表格 1 值
- amp-html - 响应必须在“feed.entry”包含一个数组或对象。放大器列表
- php - 如何强制 Dreamweaver 正确编码 PHP 文件?
- android - 获取具有可访问性android的窗口文本
- r - 如何用行均值估算缺失值?
- kdevelop - 当没有工具视图时,有没有办法在 Kdevelop 中隐藏面板?
- python - 如何在python中出现异常后再次跳转到相同的函数
- javascript - Vue通过另一个数组过滤一个数组
- json - 我似乎无法从 OpenSky-network 创建数据字符串