public static void VerifySignature(PublicKeyCredential cred, byte[] authData, byte[] clientData, byte[] signature, string rpid) { if (cred == null) { throw new ArgumentNullException(nameof(cred)); } var payload = authData.Concat(CredentialUtility.Hash(clientData)).ToArray(); var rawSignature = DERSignature.Deserialize(signature); var authDataSpan = authData.AsSpan(); var rpidHash = authDataSpan.Slice(0, 32); var flags = (AuthenticatorDataFlags)authDataSpan[32]; var counterSpan = authDataSpan.Slice(33, 4); counterSpan.Reverse(); uint counter = BitConverter.ToUInt32(counterSpan); if ((flags & AuthenticatorDataFlags.UserPresent) == 0) { throw new Exception("user does not present"); } if (!rpidHash.SequenceEqual(CredentialUtility.Hash(Encoding.UTF8.GetBytes(rpid)))) { throw new Exception("RP ID Hash does not match"); } var publicKey = CBORObject.DecodeFromBytes(cred.PublicKey); var x = publicKey.MapGet(-2).GetByteString(); var y = publicKey.MapGet(-3).GetByteString(); var ecDsa = ECDsa.Create(new ECParameters { Curve = ECCurve.NamedCurves.nistP256, Q = new ECPoint { X = x, Y = y } }); var isValid = ecDsa.VerifyData(payload, rawSignature, HashAlgorithmName.SHA256); if (!isValid) { throw new Exception("invalid signature"); } if (cred.SignCounter >= counter) { throw new Exception("invalid signature counter"); } cred.SignCounter = counter; }
public void Add(PublicKeyCredential cred) => _data.Add(cred);