【问题标题】:Producing the same signature with WebAuthn使用 WebAuthn 生成相同的签名
【发布时间】:2023-02-01 01:17:21
【问题描述】:

我刚开始在本地主机上玩WebAuthn。我被告知在credentials.response.signature 中找到的签名值正在签名credentials.response.clientDataJSON。但是,对于 navigator.credentials.get 的相同输入/挑战,我似乎得到了不同的签名。我最好的猜测是有一个时间戳或计数器进入签名的值?

我似乎无法解码 signatureauthenticatorData,这真的可以帮助我想象里面发生了什么。我能够解码 clientDataJSON 如下,任何人都有示例代码,我用它来解码其他两个上述参数?

String.fromCharCode.apply(null, new Uint8Array(credentials.response.clientDataJSON))

我还发现在解码 clientDataJSON 时,我偶尔会收到 extra field in Chrome,这对我的用例来说有点烦人。

我的目标是让用户每次验证相同的PublicKeyCredential时都产生相同的签名或散列。.有没有办法做到这一点?或者在 WebAuthn 的范围内或在其范围之外是否有其他方法可以从生物识别身份验证中受益,我可以使用这些方法从相同的输入中生成相同的签名或哈希值?

请原谅我对WebAuthn 的任何误解,我对这项神奇的技术还很陌生。我完全理解这不是 WebAuthn 的最初预期用途,因此可能需要一个糟糕的解决方法。

【问题讨论】:

    标签: javascript authentication encryption webauthn


    【解决方案1】:

    我的目标是让用户在每次验证相同的PublicKeyCredential时都产生相同的签名或散列。

    这实际上是一个真正的馊主意.使用随机挑战签署消息的全部目的是避免重放攻击。否则,如果攻击者以某种方式拦截了身份验证消息,则可以简单地重复使用该消息来冒充用户。

    我被告知在 credentials.response.signature 中找到的签名值正在签名 credentials.response.clientDataJSON

    那是不准确的。签名为authenticatorData + SHA256(clientDataJSON)

    两者都是可变的。 authenticatorData 包含一个“计数器”,每次使用凭证密钥进行身份验证时都会增加,clientDataJSON应该(或者必须为了安全)包含随机服务器端生成的挑战。

    我似乎无法解码签名或 authenticatorData,这真的可以帮助我可视化内部发生的事情。我能够如下解码 clientDataJSON,任何人都有示例代码,我用它来解码其他两个上述参数?

    签名不能被“解码”,它只能在给定足够的公钥的情况下被“验证”。对于其他参数 authenticatorDataclientDataJSON ,请查看底部的以下链接,它将对其进行解码。

    https://webauthn.passwordless.id/demos/playground.html

    我还发现在解码 clientDataJSON 时,我偶尔会在 Chrome 中得到额外的字段,这对我的用例来说有点烦人。

    我不确定,我相信这与本地主机测试。

    【讨论】:

    • 非常感谢您的详细解答!我不打算按原样传输此签名/哈希。它只会在本地使用,它是它的衍生产品,将被传输,当然每次都是唯一的,以避免重放攻击。很抱歉奇怪的用例!是否可以手动更改 authenticatorData 中的计数器,或者出于安全原因是否将其全部黑盒化?
    • 签名计数器在验证器本身中实现,无法控制。 (尽管同步的身份验证器通常会将计数器固定为零以避免也需要同步计数器。)
    • @agl 对此有进一步的阅读吗?抱歉,看起来我正在深入这个兔子洞,试图让我的用例正常工作
    • 请参阅w3.org/TR/webauthn-2/#sctn-sign-counter 并通常在该规范中搜索“签名计数器”。
    • @AntersBear 出于好奇,用例是什么?也许还有其他方法可以实现它。
    【解决方案2】:

    如果您想要与凭据关联的少量固定数据,那么您可能希望研究 credBlobprf 扩展。但是,并非所有身份验证器都支持它们。更多人将支持prf,但support for that in Chromium 将在几个月后才会出现。所以这里还没有很好的答案,但它可能比尝试修复签名更好。

    【讨论】:

    • 嗨,这很有趣,谢谢!我在哪里可以找到支持这些的设备/浏览器?
    • 最新的 Yubikeys 通常会对 CTAP 协议功能提供最大的支持。 (我这里有一个存货Yubikey Bio,它支持credBlob。)一般来说,如果你在macOS或Linux上的Chrome中进行安全密钥操作,你可以打开chrome://device-log并从中查看支持的功能列表安全密钥。对于 prf 支持,请遵循链接的 Chromium 错误,在某些时候,支持将出现在 chrome://flags/#enable-experimental-web-platform-features 后面的 Chrome Canary 中
    【解决方案3】:

    所以,首先,一般来说,当您使用相同的数据作为输入时,是否会产生相同的签名取决于所使用的签名方案。检查这个问题https://crypto.stackexchange.com/questions/26974/ 他们讨论的地方。

    现在,回到 WebAuthn(假设您使用签名算法,对于相同的输入将生成相同的签名)让我们看看签名是如何生成的。这是来自我的虚拟身份验证器的 small code,它负责生成 WebAuthn 签名:

    let authData = this._concatUint8Arrays(
        rp_id_hash,
        flags,
        sign_count, // The signature counter will always increase
        this._getAAGUID(),
        credential_id_length,
        credential_id,
        cose_key
    );
    
    // Attestation object
    let attestation_object = {'fmt': 'none', 'attStmt': {}, 'authData': authData};
    
    // ...
    
    // Generate signature
    let client_data_hash = new Uint8Array(await crypto.subtle.digest('SHA-256', client_data));
    let signatureData = this._concatUint8Arrays(authData, client_data_hash);
    let signature = await Algorithms.Sign(this.private_key, signatureData);
    

    您会注意到要签名的数据包括身份验证器的签名计数器,每次您使用身份验证器时它都会增加。这有助于检测重放攻击或克隆验证器攻击(更多信息here)。

    因此,生成相同的签名是不可行的。

    如果您想更多地了解 WebAuthn 的幕后情况,您可以查看我的 WebDevAuthn projectbrowser extension,它们允许您检查 WebAuthn 请求和响应。

    【讨论】:

      猜你喜欢
      • 2014-01-01
      • 2018-07-25
      • 2016-11-06
      • 1970-01-01
      • 2020-09-05
      • 2019-04-18
      • 2020-11-09
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多