public uint FinishAuthentication(FidoStartedAuthentication startedAuthentication,
                                         FidoAuthenticateResponse authResponse,
                                         FidoDeviceRegistration deviceRegistration,
                                         IEnumerable <FidoFacetId> trustedFacetIds)
        {
            authResponse.Validate();

            var clientData = authResponse.ClientData;

            ExpectClientDataType(clientData, AuthenticateType);

            if (clientData.Challenge != startedAuthentication.Challenge)
            {
                throw new InvalidOperationException("Incorrect challenge signed in client data");
            }

            ValidateOrigin(trustedFacetIds, new FidoFacetId(clientData.Origin));

            var signatureData = authResponse.SignatureData;

            VerifyAuthSignature(startedAuthentication.AppId, signatureData, clientData, deviceRegistration);

            deviceRegistration.UpdateCounter(signatureData.Counter);
            return(signatureData.Counter);
        }
        public uint FinishAuthentication(FidoStartedAuthentication startedAuthentication,
                                         string rawAuthResponse,
                                         FidoDeviceRegistration deviceRegistration,
                                         IEnumerable <FidoFacetId> trustedFacetIds)
        {
            var authResponse = FidoAuthenticateResponse.FromJson(rawAuthResponse);

            return(FinishAuthentication(startedAuthentication, authResponse, deviceRegistration, trustedFacetIds));
        }
        public FidoStartedAuthentication StartAuthentication(FidoAppId appId, FidoDeviceRegistration deviceRegistration)
        {
            if (appId == null)
            {
                throw new ArgumentNullException("appId");
            }
            if (deviceRegistration == null)
            {
                throw new ArgumentNullException("deviceRegistration");
            }

            var challenge = _generateFidoChallenge.GenerateChallenge();

            return(new FidoStartedAuthentication(appId,
                                                 WebSafeBase64Converter.ToBase64String(challenge),
                                                 deviceRegistration.KeyHandle));
        }
        private void VerifyAuthSignature(FidoAppId appId, FidoSignatureData signatureData, FidoClientData clientData,
                                         FidoDeviceRegistration deviceRegistration)
        {
            if (appId == null)
            {
                throw new ArgumentNullException("appId");
            }
            if (signatureData == null)
            {
                throw new ArgumentNullException("signatureData");
            }
            if (clientData == null)
            {
                throw new ArgumentNullException("clientData");
            }
            if (deviceRegistration == null)
            {
                throw new ArgumentNullException("deviceRegistration");
            }

            if (String.IsNullOrEmpty(clientData.RawJsonValue))
            {
                throw new InvalidOperationException("Client data has no JSON representation");
            }

            var counterBytes = BitConverter.GetBytes(signatureData.Counter);

            if (BitConverter.IsLittleEndian)
            {
                Array.Reverse(counterBytes);
            }

            var signedBytes = PackBytes(
                Helpers.Sha256(appId.ToString()),
                new [] { signatureData.UserPresence },
                counterBytes,
                Helpers.Sha256(clientData.RawJsonValue));

            VerifySignature(deviceRegistration, signatureData.Signature, signedBytes);

            if (signatureData.UserPresence != UserPresentFlag)
            {
                throw new InvalidOperationException("User presence invalid during authentication");
            }
        }
        private void VerifySignature(FidoDeviceRegistration deviceRegistration, FidoSignature signature,
                                     byte[] signedBytes)
        {
            try
            {
                var certPublicKey = deviceRegistration.PublicKey.PublicKey;
                var signer        = SignerUtilities.GetSigner("SHA-256withECDSA");
                signer.Init(false, certPublicKey);
                signer.BlockUpdate(signedBytes, 0, signedBytes.Length);

                if (signer.VerifySignature(signature.ToByteArray()))
                {
                    throw new InvalidOperationException("Invalid signature");
                }
            }
            catch
            {
                throw new InvalidOperationException("Invalid signature");
            }
        }