NodeJs Crypto 无法验证 Fido2 公钥和签名

问题描述 投票:0回答:1

在尝试使用 AWS Cognito 实现密钥登录时,我找到了 AWS 编写的指南 (https://github.com/aws-samples/webauthn-with-amazon-cognito/)。它展示了如何使用 lambda 触发器来响应挑战并实施流程。我的解决方案在 UI 上使用 React,在 API 上使用 ASP Net,虽然演示代码是使用 Fido2-Lib 库的 Nodejs 实现,但我发现我可以使用 Fido2NetLib 库在 C# 中实现几乎相同的功能。

一切都很顺利,所有移动部分通常都围绕创建和解析凭证进行调整,甚至 Cognito 的 AWS lambda 似乎也运行得很好,直到登录的关键点到来。当公钥和签名得到验证。我首先研究了这个想法,认为密钥采用了意想不到的格式。我意识到演示代码中的 Fido2-Lib 输出 PEM 格式密钥,而 Fido2NetLib 不提供该选项,而是提供 COSE 格式 CBOR 对象(与标准一致 - 不过,在我写这篇文章时,我假设 PEM 密钥来自 Fido2-Lib 的也是 PEM 格式内的 CBOR)。

我仔细检查了密钥的内容,并确保它们都非常标准并且可以被 NodeJS Crypto 接受

error:1E08010C:DECODER routines::unsupported

使用这些信息,我编写了一个测试程序来测试验证方法,并尝试添加 PEM 格式(“---- BEGIN PRIVATE KEY ----”),没有喜悦,我尝试了,获取 CBOR 的内容映射私钥并(了解 DER 格式)创建一个 DER 格式密钥,我相信 crypto 可以接受,使用以下示例代码,但没有乐趣,同样的 UNSUPPORTED ROUTINE 错误。

1: 2 - key type Elliptic Curve format 3: -7 - algorithm used ES256 -1: 1 - curve type P-256 -2: buffer(32) - x co-ordinate -3: buffer(32) - y co-ordinate

我很欣赏这是一个模糊的主题,并尝试修改对 crypto 的验证调用以传递更多参数,了解 Fido2NetLib 中密钥的格式以及它与 Fido2-Lib 的不同之处,我想我应该在这里联系看看如果我遇到一些愚蠢的事情,其他人已经解决了。

node.js amazon-web-services amazon-cognito cryptojs passkey
1个回答
0
投票

但是,我不知道您在哪里“学习”了 DER,但是 您发布的代码并没有创建任何与 DER 类似的东西。它确实将 EC

point

转换为 X9-and-SEC1 格式,这是最常见的标准,并且在 OpenSSL 以及 Nodejs 的 PEM 和 DER 格式中使用,但它本身既不是 PEM 也不是 DER 或甚至是有效的密钥。 如果你有nodejs 16(我希望你有OpenSSL 3),它支持JOSE中使用的JWK格式,这(并非偶然)更接近COSE。尝试 const coseKey = Buffer.from(publicKeyCredJSON.publicKey, 'base64'); // Parse COSE key const parsedKey = cbor.decodeFirstSync(coseKey); // Extract necessary information const keyType = parsedKey.get(1); // Key type const algorithm = parsedKey.get(3); // Algorithm const xCoord = parsedKey.get(-2); const yCoord = parsedKey.get(-3);// Key value // Convert key data to buffer const publicKey = Buffer.concat([Buffer.from([0x04]), xCoord, yCoord]); // Sample data and signature to verify (replace with your actual data and signature) const rawAuthnrData = Buffer.from(challengeAnswerJSON.response.authenticatorData, 'base64'); const rawClientData = Buffer.from(challengeAnswerJSON.response.clientDataJSON, 'base64'); // Create verifier const verifier = crypto.createVerify('SHA256'); // Provide data verifier.update(rawAuthnrData); verifier.update(rawClientData); // Verify signature const isValid = verifier.verify(publicKey, challengeAnswerJSON.response.signature, 'base64');` ,其中 EC 公钥

的最小

RFC7518 规范是 {format:'jwk', key:{perRFC7518}}

对于较旧的 Nodejs,原则上您需要构建 RFC5480 中定义的 DER 格式(或其 PEM 等效项,但工作量更大,没有任何好处);这包括一个外部标头、一个包含 id-ecPublicKey 和曲线 OID 的 AlgorithmIdentifier,以及一个包含 SEC1 格式的点的 BIT STRING(与 X9 相同,但不包括混合,这对您来说不是问题)。然而,由于每条曲线的点长度是固定的,

对于给定的曲线
,这个 DER 结构实际上是一个固定前缀加上点,您可以从您创建的一次性密钥(也适用于 P-256!)复制固定前缀Nodejs 或 OpenSSL(它们在这里是同一件事)。

© www.soinside.com 2019 - 2024. All rights reserved.