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); }
// ============== 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); } }
// =============== 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; }