.Net 中的 WebAuthN 和 BouncyCastle

Posted

技术标签:

【中文标题】.Net 中的 WebAuthN 和 BouncyCastle【英文标题】:WebAuthN and BouncyCastle in .Net 【发布时间】:2020-01-03 18:29:31 【问题描述】:

我正在为 YubiKey 和 webAuthN 进行概念验证;我想我已经完成了基本步骤,但我在验证签名时遇到了一些问题;

有几个地方对我来说可能会出错:

1) 当我执行“navigator.credentials.create”时,我得到了发送到服务器的凭据对象。

2) 在服务器上我得到 COSE 公钥;它有一个 X 和 Y 点(这是椭圆曲线加密)

3) 我将 X 和 Y (32 Bytes Uint8Array) 转换为 Org.BouncyCastle.Math.BigInteger 我在这里遇到的一个问题有时这些 X 和 Y 坐标会产生 NEGATIVE BigInteger(最左边的位已设置) 我读到这意味着这是“前导”零字节,即 33 字节数组,字节 0 为“0” - 不确定这是否属实,但在设置第一位的情况下找不到另一条指令

4) 我从“navigator.credentials.get”得到断言并将其发送到服务器

5) 我使用上一步中的 X 和 Y 来构建公钥,

6) 我使用 Base64Decode 将 clientDataJSON 和authenticatorData 从断言解码到各自的ByteArrays

7) 我使用 SHA256 散列“clientDataJSON”元素

8) 我构建了一个包含原始“authenticatorData”和散列的“clientDataJSON”(连接)的字节数组

9) 我使用 Base64Decode 从断言中解码 Signature 元素

10) 我使用上面的公钥创建一个 Org.BouncyCastle.Crypto.Signers.ECDsaSigner

11) 我在连接的authenticatorData 和ClientDataHash 上使用VerifySignature。

这总是返回“FALSE”(即错误的签名)

以下是一些相关代码:

//Load the Base64 Encoded ByteArrays for the PublicKey X and Y (stored when registered)
Dim EncryptionX as Byte() = Base64Decode(SavedPublicKey.X)
Dim EncryptionY as Byte() = Base64Decode(SavedPublicKey.Y)


//Decode signature and AuthenticatorData elements from assertion
Dim Signature as Byte() = Base64Decode(Assertion.Signature)
Dim authenticatorData as Byte() = Base64Decode(Assertion.authenticatorData)


//Decode and HASH ClientDataJson element form assertion
Dim ClientDataJson as Byte() = Base64Decode(Assertion.ClientDataJson)
Dim shaHash = SHA256.Create
Dim ClientDataHash As Byte() = shaHash.ComputeHash(ClientDataJson)

//Concatenate the AuthenticatorData and ClientDataHash
Dim CombinedMessage as List(Of Byte)
CombinedMessage.AddRange(authenticatorData)
CombinedMessage.AddRange(ClientDataHash)
Dim MessageToValidate as Byte()=CombinedMessage.ToArray()


//Get the secp256r1 Curve (I think this is the correct curve for WebAuthN
Dim x9ecpPar As Org.BouncyCastle.Asn1.X9.X9ECParameters = Org.BouncyCastle.Asn1.Sec.SecNamedCurves.GetByName("secp256r1")

Dim ECCcurve As Org.BouncyCastle.Math.EC.ECCurve = x9ecpPar.Curve

//build the "point" form the curve and the X and Y points
Dim Q As Org.BouncyCastle.Math.EC.ECPoint = ECCcurve.CreatePoint(New Org.BouncyCastle.Math.BigInteger(EncryptionX), New Org.BouncyCastle.Math.BigInteger(EncryptionY))

//Build the Public Keys from the "Q" point using ECDSA algorthim 
Dim PublicKey As Org.BouncyCastle.Crypto.Parameters.ECPublicKeyParameters = New Org.BouncyCastle.Crypto.Parameters.ECPublicKeyParameters("ECDSA", Q, Org.BouncyCastle.Asn1.Sec.SecObjectIdentifiers.SecP256r1)


//Get an ANS1 Input stream from the Signature ByteArray
Dim ASN1 = New Org.BouncyCastle.Asn1.Asn1InputStream(Signature)


Dim Sequence As Org.BouncyCastle.Asn1.Asn1Sequence = ASN1.ReadObject()

Dim eR As Org.BouncyCastle.Math.BigInteger = DirectCast(Sequence(0), Org.BouncyCastle.Asn1.DerInteger).PositiveValue

Dim eS As Org.BouncyCastle.Math.BigInteger = DirectCast(seq(1), Org.BouncyCastle.Asn1.DerInteger).PositiveValue

Dim signer As Org.BouncyCastle.Crypto.Signers.ECDsaSigner = New Org.BouncyCastle.Crypto.Signers.ECDsaSigner

signer.Init(False, PublicKey)
Dim SignatureGood As Boolean = signer.VerifySignature(MessageToValidate, er, es)


//**** SignatureGood  ALWAYS False *****

非常感谢任何帮助! 提前致谢!

【问题讨论】:

【参考方案1】:

原本打算深入(如您所愿)进入 WebAuthn,但我最终只是转而使用(并贡献于)这个出色的项目 (https://github.com/abergs/fido2-net-lib)。至少它会有你可以参考的代码。

我可能会从这里开始:https://github.com/abergs/fido2-net-lib/blob/master/Src/Fido2/Objects/CredentialPublicKey.cs

【讨论】:

感谢您的建议;我确实看过,但它使用 .net 核心,并且该项目适用于 ADFS 3.0 中的 MFA .dll;我认为它不支持 .net 核心。但我会尝试让那个图书馆工作;也许我可以有所作为。 希望它至少可以作为一个很好的参考实现。祝你好运!

以上是关于.Net 中的 WebAuthN 和 BouncyCastle的主要内容,如果未能解决你的问题,请参考以下文章

如何为Android和IOS实现FIDO2(WebAuthn)

从 Bouncy Castle 中的文本创建 RSA 公钥的问题

使用 WebAuthN 可以拒绝某些类型的身份验证方法 FIDO2)

Webauthn - Windows Hello 身份验证器选择不起作用

如何使用Bouncy Castle Crypto API来加密和解密数据

Auth0 WebAuthn Passwordless将现代身份验证的便捷性和安全性推向新高度