rossby

package module
v0.0.0-...-d5010d9 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 23, 2019 License: AGPL-3.0 Imports: 15 Imported by: 0

README

Rossby

Build Status codecov GoDoc Go Report Card

Rossby implements a distributed, encrypted message service that is intended to be geo-replicated. Rossby's goal is to facilitate the sending and receiving of messages while also ensuring that as much work as possible is pushed to the client side. Requiring clients to handle most of the encryption and message management ensures that rossby has as little detail as possible to be exposed to any security vulnerabilities.

Requirements

Required
  • A user should be able to send and receive messages from multiple devices
  • Users are identified by multiple phone numbers or email addresses
  • Messages should either be sent person to person or to a group
  • Private keys should remain on the device and never be transferred over the network
  • Public keys should be stored on the system and able to be retrieved by contacts
  • Deduplicate messages (?)
Optional
  • User should be able to send read receipts
  • Users should be able to send typing indicators
  • User should be able to block other users
  • Users should be able to allow or disallow receiving messages from anyone
  • Users should be able to verify other users by exchanging a safety number
  • Users should be able to send pictures and locations (and other rich media)

Messaging Context

A goal of our system is to ensure that as much work is done on the client-side as possible to ensure as much security as we can manage.

Messaging Context

Person to person (basic case):

A encrypts message with B’s public key then sends to B’s message queue. If A doesn’t have B’s public key, A requests it from the key store. Only B will be able to decrypt the message before it leaves A’s phone.

Groups (complex case) 2 options:

  1. Create per-group keys that have to be shared with all members of the group
  2. Send messages to each member of the group encrypted with their public key

Because keys should not be exchanged over the network, we will go with option 2.

Data Storage

All data stores are partitionable key-value stores that are perfect for demonstrating geo-replication with Alia. Because of strong consistency requirements and inter-object relations, this is a very good geo-distributed system example.

Data Storage

Each user has a unique inbox and is identified by a GUID - Box ID. The BoxID is the basic unit of relation and other tables are partitioned to ensure optimal reads. The inbox lookup is a read/insert/delete only mapping of a user identifier (e.g. phone number, email, or device) to the Box ID. The key store is a read/update/insert only mapping of the box id to the public key; note that the system only maintains a single public key per box at any given time.

The profiles table and the message queue are the two tables that are updated the most often. The profiles table has metadata related to the state of messaging for the user. The message queue has messages appended to it for delivery to devices.

Each device tracks what messages have been delivered to it via the device pointers. Once the message has been delivered to all devices the queue can be cleaned up. This ensures that the server does not store messages for all time and we don’t incur large data storage costs. We can also expire messages if they’ve been in the queue for too long and are held up by an offline device.

Should we just put the public key into the profile?

API

Register

  • Send: device, phone/email, public key
  • Server: store data, mark unauthorized, send unique code, acknowledge the request.
  • Error: phone/email already in box id table or pub key table (link devices instead)

Authorize

  • Send: device, auth key
  • Server: mark authorized (note: no username/password)
  • Respond: send device token encrypted by client public key

Fetch Messages

  • Send: device, box id, hawk authentication with unique token
  • Server: retrieve messages, update device pointer (on send or confirm?)
  • Respond: messages, status
  • Error: request is unauthenticated by hawk token
  • Client: decrypt messages with private and add to each chatbox

Request Key/Profile (add contact)

  • Send: phone number/email, hawk authentication with unique token
  • Server: check permissions for contacts
  • Respond: profile/public key for user
  • Error: no user, not authorized, (if not allowed to discover contact, send no user)

Send Message

  • Client: encrypt message(s) with recipient public key
  • Send: recipient(s), encrypted message(s), haw authentication with unique tokens
  • Server: enqueue messages in inboxes, acknowledge the request
  • Error: request unauthenticated, unknown recipient (also case iff blocked)

Documentation

Overview

Package rossby implements a distributed, encrypted message service that is intended to be geo-replicated. Rossby's goal is to facilitate the sending and receiving of messages while also ensuring that as much work as possible is pushed to the client side. Requiring clients to handle most of the encryption and message management ensures that rossby has as little detail as possible to be exposed to any security vulnerabilities.

Index

Constants

View Source
const (
	LogTrace uint8 = iota
	LogDebug
	LogInfo
	LogCaution
	LogStatus
	LogWarn
	LogSilent
)

Levels for implementing the debug and trace message functionality.

View Source
const CautionThreshold = 80

CautionThreshold for issuing caution logs after accumulating cautions.

Variables

This section is empty.

Functions

func LogLevel

func LogLevel() string

LogLevel returns a string representation of the current level

func SetLogLevel

func SetLogLevel(level uint8)

SetLogLevel modifies the log level for messages at runtime. Ensures that the highest level that can be set is the trace level.

func SetLogger

func SetLogger(l *log.Logger)

SetLogger sets the logger for writing output to. Can set to a noplog to remove all log messages (or set the log level to silent).

func Version

func Version(short bool) string

Version returns a string representation of the semantic package version number.

Types

type Config

type Config struct {
	Address  string `default:":1205"`                   // the host and port to bind the server to ($ROSSBY_ADDRESS)
	Database string `default:"fixtures/db"`             // the path to the directory of the badger database ($ROSSBY_DATABASE)
	LogLevel int    `default:"3" envconfig:"log_level"` // verbosity of logging, lower is more verbose ($ROSSBY_LOG_LEVEL)
}

Config stores the optional settings that modify the behavior of rossby at runtime. A config can be created either through default values specified on the struct tags, or fetched from environment variables prefixed with ROSSBY_.

TODO: change the database default path after development TODO: allow configuration from cli context or from YAML file

func (*Config) DatabaseOptions

func (c *Config) DatabaseOptions() (opts badger.Options)

DatabaseOptions returns the badger configuration to open and access the database.

func (*Config) Load

func (c *Config) Load() (err error)

Load the configuration from the environment and set default values.

type DBLogger

type DBLogger struct{}

DBLogger implements badger.Logger to ensure database log messages get appropriately logged at the level specified by Rossby.

TODO: Generalize this structure and the rest of this package into a kansaslabs log package

func (*DBLogger) Debugf

func (l *DBLogger) Debugf(msg string, a ...interface{})

Debugf writes a message to trace

func (*DBLogger) Errorf

func (l *DBLogger) Errorf(msg string, a ...interface{})

Errorf writes a log message to warn

func (*DBLogger) Infof

func (l *DBLogger) Infof(msg string, a ...interface{})

Infof writes a message to info

func (*DBLogger) Warningf

func (l *DBLogger) Warningf(msg string, a ...interface{})

Warningf writes a log message to caution

type Replica

type Replica struct {
	// contains filtered or unexported fields
}

Replica objects contain the state to run a single rossby replica instance which manages a local database instance and handles messages from clients and peers to distribute messages across the network. There is always one replica object per Rossby process.

func New

func New(options *Config) (r *Replica, err error)

New creates a Rossby replica with the specified config or loads the config from the environment if no configuration is passed. The replica is initialized and validated once created but is not running.

func (*Replica) Authorize

func (s *Replica) Authorize(ctx context.Context, in *pb.AuthorizeRequest) (*pb.AuthorizeReply, error)

Authorize implements the Rossby server interface.

func (*Replica) Chat

func (s *Replica) Chat(stream pb.Rossby_ChatServer) error

Chat implements the Rossby server interface.

func (*Replica) Contact

func (s *Replica) Contact(ctx context.Context, in *pb.ContactRequest) (*pb.ContactReply, error)

Contact implements the Rossby server interface.

func (*Replica) Deliver

func (s *Replica) Deliver(ctx context.Context, in *pb.Messages) (*pb.DeliverResponse, error)

Deliver implements the Rossby server interface.

func (*Replica) Fetch

func (s *Replica) Fetch(ctx context.Context, in *pb.FetchRequest) (*pb.Messages, error)

Fetch implements the Rossby server interface.

func (*Replica) Listen

func (r *Replica) Listen() error

Listen for messages from clients and respond to them.

func (*Replica) Register

func (s *Replica) Register(ctx context.Context, in *pb.RegisterRequest) (*pb.RegisterReply, error)

Register implements the Rossby server interface.

Directories

Path Synopsis
Package bucket implements prefixed-keys to separate collections of similar data in the database.
Package bucket implements prefixed-keys to separate collections of similar data in the database.
cmd

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL