public bool SubmitResponse(SignatureMessage message)
        {
            bool retval = false;

            try
            {
                // Use the public key hint to identify which public key to use.
                byte[] challenge;
                byte[] publicKey = DAL.Instance.GetPublicKeyForUser(message.UserId, message.PublicKeyHint, out challenge);

                CngKey pubCngKey = new SubjectPublicKeyInfo(publicKey).GetPublicKey();

                // Validate that the original challenge was signed using the corresponding private key.
                using (RSACng pubKey = new RSACng(pubCngKey))
                {
                    byte[] signature = Convert.FromBase64String(message.Signature);
                    retval = pubKey.VerifyData(challenge, signature, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
                }
            }
            catch (Exception)
            {
            }

            // Return a boolean response to the client
            // TODO:  What should actually be returned is an authentication token (OAuth or equivalent)
            // that the client uses for subsequent authentication requests
            return(retval);
        }
Example #2
0
        // ============== Processing Data ===============

        void RecvLoop()
        {
            try
            {
                byte[]   buffer = new byte[MaxBufferSize];
                EndPoint from   = serverEndPoint;

                while (state != State.Terminated)
                {
                    int len = socket.ReceiveFrom(buffer, ref from);
                    lastSeen = DateTime.Now;

#if SLEEPY_STATS
                    //Log.Write($"RECV: {len}");
                    stats.RecvBytesTotal += (ulong)len;
                    stats.RecvTotal++;
#endif

                    if (len == SignatureMessage.connMesLen)
                    {
                        SignatureMessage sigMes = SignatureMessage.Deserialize(buffer);
                        if (sigMes.IsValid)
                        {
                            if (sigMes.Connect)
                            {
                                state = State.Connected;
                                OnConnect?.Invoke();
                            }
                            else
                            {
                                ForceDisconnect(false);
                            }
                            return;
                        }
                    }

                    OnPacket(buffer, len);
                }
            }
            catch (ThreadAbortException) { }
            catch (ThreadInterruptedException) { }
            catch (SocketException) { /* Noramlly WSA Blcoking Call Canceled when closing */ }
            catch (Exception e)
            {
                Log.Write("RecvLoop Exception On Client, reason: " + e.Message + "\n<b>Stack:</b> " + e.StackTrace);
            }
        }
Example #3
0
        // =============== Process Data ===================

        void RecvLoop()
        {
            try
            {
                byte[]   buffer = new byte[MaxBufferSize];
                EndPoint from   = serverEndPoint;
                while (state != State.Terminated)
                {
                    int len = socket.ReceiveFrom(buffer, ref from);

                    Connections.TryGetValue(from, out Connection conn);

#if SLEEPY_STATS
                    //Log.Write($"RECV: {len}");
                    stats.RecvBytesTotal += (ulong)len;
                    stats.RecvTotal++;
#endif

                    conn?.UpdateLastSeen();

                    if (len == SignatureMessage.connMesLen)
                    {
                        SignatureMessage sigMes = SignatureMessage.Deserialize(buffer);
                        if (sigMes.IsValid)
                        {
                            if (sigMes.Connect) // client Asking to connect
                            {
                                if (conn == null)
                                {
                                    conn = new Connection(from);
                                    Connections.Add(from, conn);
                                    Send(conn.Conn, SignatureMessage.connectSigMes);
                                    OnConnect?.Invoke(conn);
                                }
                            }
                            else // client asking to disconnect
                            {
                                if (conn != null)
                                {
                                    Connections.Remove(from);
                                    Send(conn.Conn, SignatureMessage.disconnectSigMes);
                                    OnDisconnect?.Invoke(conn);
                                }
                            }
                            continue;
                        }
                    }

                    if (conn != null)
                    {
                        OnPacket(conn, buffer, len);
                    }
                }
            }
            catch (ThreadAbortException) { }
            catch (ThreadInterruptedException) { }
            catch (SocketException) { /* Noramlly WSA Blcoking Call Canceled when closing */ }
            catch (Exception e)
            {
                Log.Write("RecvLoop Exception On Server, reason: " + e.Message + "\n<b>Stack:</b> " + e.StackTrace);
            }
        }
        public async Task<bool> SubmitResponse(SignatureMessage message)
        {
            bool retval = false;

            try
            {
                string challenge;
                JsonWebKey publicKey = _credentialService.GetPublicKeyForUser(message.UserId, message.PublicKeyHint, out challenge);

                var decodedClientData = message.ClientData.Rfc4648Base64UrlDecode();
                var decodedAuthnrData = message.AuthnrData.Rfc4648Base64UrlDecode();

                var clientDataJson = Encoding.UTF8.GetString(decodedClientData);
                var clientData = JsonConvert.DeserializeObject<ClientData>(clientDataJson);
                if (clientData.Challenge != challenge) return false;
                
                var sha256 = SHA256.Create();
                var hashedClientData = sha256.ComputeHash(decodedClientData);
                var buffer = new byte[decodedAuthnrData.Length + hashedClientData.Length];
                decodedAuthnrData.CopyTo(buffer, 0);
                hashedClientData.CopyTo(buffer, decodedAuthnrData.Length);

                var publicKeyInfo = new RSAParameters();
                publicKeyInfo.Modulus = publicKey.N.Rfc4648Base64UrlDecode();
                publicKeyInfo.Exponent = publicKey.E.Rfc4648Base64UrlDecode();
                var rsa = new RSACng();
                rsa.ImportParameters(publicKeyInfo);

                byte[] signature = message.Signature.Rfc4648Base64UrlDecode();
                retval = rsa.VerifyData(buffer, signature, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
                if (retval)
                {
                    var user = _signInService.FindBySubject(message.UserId);
                    await IssueCookie(user, "idsvr", "fido");
                }
            }
            catch (Exception)
            { }
            
            return retval;
        }
        public static ArraySegment<byte> ToSignatureMessageBlock(SignatureMessage package, IExchangeEncrypt publicKey)
        {
            if (package == null) throw new ArgumentNullException("package");
            if (publicKey == null) throw new ArgumentNullException("publicKey");

            ArraySegment<byte> value;

            using (Stream packageStream = package.Export(_bufferManager))
            using (Stream compressStream = ContentConverter.Compress(packageStream))
            using (Stream paddingStream = ContentConverter.AddPadding(compressStream, 1024 * 256))
            using (Stream hashStream = ContentConverter.AddHash(paddingStream))
            using (Stream cryptostream = ContentConverter.Encrypt(hashStream, publicKey))
            using (Stream typeStream = ContentConverter.AddType(cryptostream, "SignatureMessage"))
            {
                value = new ArraySegment<byte>(_bufferManager.TakeBuffer((int)typeStream.Length), 0, (int)typeStream.Length);
                typeStream.Read(value.Array, value.Offset, value.Count);
            }

            return value;
        }