.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 身份验证器选择不起作用