Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor CLI packages #195

Merged
merged 13 commits into from
Dec 15, 2017
2 changes: 1 addition & 1 deletion coniksbots/bot.go → application/bots/bot.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
// Currently, this interface is used to implement a Twitter account
// verification bot.

package coniksbots
package bots

import (
"bytes"
Expand Down
52 changes: 52 additions & 0 deletions application/bots/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package bots

import (
"github.com/coniks-sys/coniks-go/application"
)

// A TwitterConfig contains the address of the named UNIX socket
// through which the bot and the CONIKS server communicate,
// the OAuth information needed to authenticate the bot with Twitter,
// and the bot's reserved Twitter handle. These values are specified
// in a configuration file, which is read at initialization time.
type TwitterConfig struct {
CONIKSAddress string `toml:"coniks_address"`
TwitterOAuth `toml:"twitter_oauth"`
Handle string `toml:"twitter_bot_handle"`
}

// A TwitterOAuth contains the four secret values needed to authenticate
// the bot with Twitter. These values are unique to each application
// that uses the Twitter API to access an account's feed and direct
// messages, and must be generated via Twitter's developer portal.
type TwitterOAuth struct {
ConsumerKey string
ConsumerSecret string
AccessToken string
AccessSecret string
}

var _ application.AppConfig = (*TwitterConfig)(nil)

// NewTwitterConfig initializes a new Twitter registration bot configuration
// with the given server address, Twitter handle, and OAuth credentials.
func NewTwitterConfig(addr, handle string, oauth TwitterOAuth) *TwitterConfig {
var conf = TwitterConfig{
CONIKSAddress: addr,
Handle: handle,
TwitterOAuth: oauth,
}

return &conf
}

// Load initializes a Twitter registration proxy configuration from the
// corresponding config file.
func (conf *TwitterConfig) Load(file string) error {
tmp, err := application.LoadConfig(file)
if err != nil {
return err
}
conf = tmp.(*TwitterConfig)
return nil
}
13 changes: 4 additions & 9 deletions coniksbots/doc.go → application/bots/doc.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
Package coniksbots implements the CONIKS account verification
Package bots implements the CONIKS account verification
protocol for first-party identity providers.

Many communication services provide user identifiers for
Expand All @@ -9,11 +9,11 @@ wishing to communicate securely often opt to use a third-party
end-to-end encrypted communication service, which allows them
to connect their first-party account.

coniksbots provides such third-party secure communication services
bots provides such third-party secure communication services
that use CONIKS for key management with a mechanism for
ensuring that the first-party usernames registered with the
CONIKS key directory belong to a legitimate first-party account.
More specifically, coniksbots provides registration proxies which
More specifically, bots provides registration proxies which
verify that each first-party username belongs to a
corresponding first-party account before forwarding the new
registration to the third-party CONIKS server.
Expand All @@ -28,10 +28,5 @@ Twitter Bot

This module provides a registration proxy for Twitter accounts
that implements the CONIKS account verification Bot interface.

Cli

This subpackage provides an executable reference implementation for a CONIKS
registration proxy for Twitter accounts.
*/
package coniksbots
package bots
40 changes: 8 additions & 32 deletions coniksbots/twitterbot.go → application/bots/twitterbot.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// A registration proxy for Twitter accounts that implements the
// CONIKS account verification Bot interface.

package coniksbots
package bots

import (
"fmt"
Expand All @@ -10,8 +10,7 @@ import (
"strings"
"time"

"github.com/BurntSushi/toml"
"github.com/coniks-sys/coniks-go/coniksserver"
"github.com/coniks-sys/coniks-go/application"
"github.com/coniks-sys/coniks-go/protocol"
"github.com/dghubble/go-twitter/twitter"
"github.com/dghubble/oauth1"
Expand All @@ -34,28 +33,6 @@ type TwitterBot struct {

var _ Bot = (*TwitterBot)(nil)

// A TwitterConfig contains the address of the named UNIX socket
// through which the bot and the CONIKS server communicate,
// the OAuth information needed to authenticate the bot with Twitter,
// and the bot's reserved Twitter handle. These values are specified
// in a configuration file, which is read at initialization time.
type TwitterConfig struct {
CONIKSAddress string `toml:"coniks_address"`
TwitterOAuth `toml:"twitter_oauth"`
Handle string `toml:"twitter_bot_handle"`
}

// A TwitterOAuth contains the four secret values needed to authenticate
// the bot with Twitter. These values are unique to each application
// that uses the Twitter API to access an account's feed and direct
// messages, and must be generated via Twitter's developer portal.
type TwitterOAuth struct {
ConsumerKey string
ConsumerSecret string
AccessToken string
AccessSecret string
}

// NewTwitterBot constructs a new account verification bot for Twitter
// accounts that implements the Bot interface.
//
Expand All @@ -66,16 +43,15 @@ type TwitterOAuth struct {
// tuple. Otherwise, it returns a TwitterBot struct
// with the appropriate values obtained during the setup.
func NewTwitterBot(path string) (Bot, error) {
var conf TwitterConfig
if _, err := toml.DecodeFile(path, &conf); err != nil {
return nil, fmt.Errorf("Failed to load config: %v", err)
var conf *TwitterConfig = &TwitterConfig{}
if err := conf.Load(path); err != nil {
return nil, err
}

// Notify if the CONIKS key server is down
if _, err := os.Stat(conf.CONIKSAddress); os.IsNotExist(err) {
return nil, fmt.Errorf("CONIKS Key Server is down")
}

auth := conf.TwitterOAuth
config := oauth1.NewConfig(auth.ConsumerKey, auth.ConsumerSecret)
token := oauth1.NewToken(auth.AccessToken, auth.AccessSecret)
Expand Down Expand Up @@ -167,7 +143,7 @@ func (bot *TwitterBot) Stop() {
func (bot *TwitterBot) HandleRegistration(username string, msg []byte) string {
// validate request message
invalid := false
req, err := coniksserver.UnmarshalRequest(msg)
req, err := application.UnmarshalRequest(msg)
if err != nil {
invalid = true
} else {
Expand All @@ -180,7 +156,7 @@ func (bot *TwitterBot) HandleRegistration(username string, msg []byte) string {
}
if invalid {
log.Println("[registration bot] Malformed client request")
res, err := coniksserver.MarshalResponse(
res, err := application.MarshalResponse(
protocol.NewErrorResponse(protocol.ErrMalformedMessage))
if err != nil {
panic(err)
Expand All @@ -192,7 +168,7 @@ func (bot *TwitterBot) HandleRegistration(username string, msg []byte) string {
res, err := SendRequestToCONIKS(bot.coniksAddress, msg)
if err != nil {
log.Println("[registration bot] " + err.Error())
res, err := coniksserver.MarshalResponse(
res, err := application.MarshalResponse(
protocol.NewErrorResponse(protocol.ErrDirectory))
if err != nil {
panic(err)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package coniksbots
package bots

import (
"encoding/json"
Expand Down
47 changes: 26 additions & 21 deletions coniksclient/config.go → application/client/config.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,8 @@
package coniksclient
package client

import (
"fmt"
"io/ioutil"

"github.com/BurntSushi/toml"
"github.com/coniks-sys/coniks-go/application"
"github.com/coniks-sys/coniks-go/crypto/sign"
"github.com/coniks-sys/coniks-go/utils"
)

// Config contains the client's configuration needed to send a request to a
Expand All @@ -26,27 +22,36 @@ type Config struct {
Address string `toml:"address"`
}

// LoadConfig returns a client's configuration read from the given filename.
var _ application.AppConfig = (*Config)(nil)

// NewConfig initializes a new client configuration with the given
// server signing public key path, registration address, and
// server address.
func NewConfig(signPubkeyPath, regAddr, serverAddr string) *Config {
var conf = Config{
SignPubkeyPath: signPubkeyPath,
RegAddress: regAddr,
Address: serverAddr,
}

return &conf
}

// Load initializes a client's configuration from the given file.
// It reads the signing public-key file and parses the actual key.
// If there is any parsing or IO-error it returns an error (and the returned
// config will be nil).
func LoadConfig(file string) (*Config, error) {
var conf Config
if _, err := toml.DecodeFile(file, &conf); err != nil {
return nil, fmt.Errorf("Failed to load config: %v", err)
func (conf *Config) Load(file string) error {
tmp, err := application.LoadConfig(file)
if err != nil {
return err
}
conf = tmp.(*Config)

// load signing key
signPath := utils.ResolvePath(conf.SignPubkeyPath, file)
signPubKey, err := ioutil.ReadFile(signPath)
signPubKey, err := application.LoadSigningPubKey(conf.SignPubkeyPath, file)
if err != nil {
return nil, fmt.Errorf("Cannot read signing key: %v", err)
return err
}
if len(signPubKey) != sign.PublicKeySize {
return nil, fmt.Errorf("Signing public-key must be 32 bytes (got %d)", len(signPubKey))
}

conf.SigningPubKey = signPubKey

return &conf, nil
return nil
}
25 changes: 25 additions & 0 deletions application/client/encoding.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package client

import (
"github.com/coniks-sys/coniks-go/application"
"github.com/coniks-sys/coniks-go/protocol"
)

// CreateRegistrationMsg returns a JSON encoding of
// a protocol.RegistrationRequest for the given (name, key) pair.
func CreateRegistrationMsg(name string, key []byte) ([]byte, error) {
return application.MarshalRequest(protocol.RegistrationType,
&protocol.RegistrationRequest{
Username: name,
Key: key,
})
}

// CreateKeyLookupMsg returns a JSON encoding of
// a protocol.KeyLookupRequest for the given name.
func CreateKeyLookupMsg(name string) ([]byte, error) {
return application.MarshalRequest(protocol.KeyLookupType,
&protocol.RegistrationRequest{
Username: name,
})
}
61 changes: 61 additions & 0 deletions application/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package application

import (
"bytes"
"fmt"
"io/ioutil"

"github.com/BurntSushi/toml"
"github.com/coniks-sys/coniks-go/crypto/sign"
"github.com/coniks-sys/coniks-go/utils"
)

// AppConfig is the generic type used to specify the configuration of
// any kind of CONIKS application-level executable (e.g. key server,
// client etc.).
type AppConfig interface {
Load(file string) error
}

// LoadSigningPubKey loads a public signing key at the given path
// specified in the given config file.
// If there is any parsing error or the key is malformed,
// LoadSigningPubKey() returns an error with a nil key.
func LoadSigningPubKey(path, file string) (sign.PublicKey, error) {
signPath := utils.ResolvePath(path, file)
signPubKey, err := ioutil.ReadFile(signPath)
if err != nil {
return nil, fmt.Errorf("Cannot read signing key: %v", err)
}
if len(signPubKey) != sign.PublicKeySize {
return nil, fmt.Errorf("Signing public-key must be 32 bytes (got %d)", len(signPubKey))
}
return signPubKey, nil
}

// LoadConfig loads an application configuration from the given toml-encoded
// file. If there is any decoding error, an LoadConfig() returns an error
// with a nil config.
func LoadConfig(file string) (AppConfig, error) {
var conf AppConfig
if _, err := toml.DecodeFile(file, &conf); err != nil {
return nil, fmt.Errorf("Failed to load config: %v", err)
}
return conf, nil
}

// SaveConfig stores the given configuration conf in the given
// file using toml encoding.
// If there is any encoding or IO error, SaveConfig() returns an error.
func SaveConfig(file string, conf AppConfig) error {
var confBuf bytes.Buffer

e := toml.NewEncoder(&confBuf)
if err := e.Encode(conf); err != nil {
return err
}
if err := utils.WriteFile(file, confBuf.Bytes(), 0644); err != nil {
return err
}
return nil
}
Loading