users can send (but not read) messages

master
Jordan Orelli 10 years ago
parent 7d8c23038f
commit b8e2800df2

@ -282,7 +282,9 @@ func (c *Client) exec(line string) {
case "notes/list":
c.listNotes(parts[1:])
case "keys/get":
c.getKey(parts[1:])
c.fetchKey(parts[1:])
case "msg/send":
c.sendMessage(parts[1:])
default:
c.err("unrecognized client command: %s", parts[0])
}
@ -386,7 +388,7 @@ func (c *Client) encryptNote(title string, message []rune) (*EncryptedNote, erro
// key functions
// ------------------------------------------------------------------------------
func (c *Client) getKey(args []string) {
func (c *Client) fetchKey(args []string) {
if len(args) != 1 {
c.err("keys/get takes exactly one arg")
return
@ -408,18 +410,93 @@ func (c *Client) saveKey(nick string, key rsa.PublicKey) {
c.keyStore[nick] = key
}
func (c *Client) getKey(nick string) (*rsa.PublicKey, error) {
if key, ok := c.keyStore[nick]; ok {
return &key, nil
}
c.fetchKey([]string{nick})
if key, ok := c.keyStore[nick]; ok {
return &key, nil
}
return nil, fmt.Errorf("no such key")
}
func (c *Client) handleKeyResponse(body json.RawMessage) error {
c.info(string(body))
// c.info(string(body))
var res KeyResponse
if err := json.Unmarshal(body, &res); err != nil {
c.err(err.Error())
return err
}
c.info("%v", res)
// c.info("%v", res)
c.saveKey(res.Nick, res.Key)
return nil
}
// ------------------------------------------------------------------------------
// message functions
// ------------------------------------------------------------------------------
func (c *Client) sendMessage(args []string) {
if len(args) != 1 {
c.err("send message requires exactly 1 arg, saw %d", len(args))
return
}
to := args[0]
c.info("fetching key...")
pkey, err := c.getKey(to)
if err != nil {
c.err("%v", err)
return
}
c.info("ok we have a key")
text, err := c.readTextBlock()
if err != nil {
c.err("%v", err)
return
}
aesKey, err := c.aesKey()
if err != nil {
c.err("couldn't create an aes key: %v", err)
return
}
ctext, err := c.aesEncrypt(aesKey, []byte(string(text)))
if err != nil {
c.err("couldn't aes encrypt message text: %v", err)
return
}
cnick, err := c.aesEncrypt(aesKey, []byte(c.nick))
if err != nil {
c.err("couldn't aes encrypt nick: %v", err)
return
}
ckey, err := rsa.EncryptPKCS1v15(rand.Reader, pkey, aesKey)
if err != nil {
c.err("couldn't rsa encrypt aes key: %v", err)
return
}
m := Message{
Key: ckey,
From: cnick,
To: to,
Text: ctext,
}
res, err := c.sendRequest(m)
if err != nil {
c.err("%v", err)
return
}
c.info("%v", <-res)
}
func (c *Client) readTextBlock() ([]rune, error) {
// god dammit what have i gotten myself into
msg := make([]rune, 0, 400)

30
db.go

@ -5,6 +5,9 @@ import (
"encoding/json"
"fmt"
"github.com/syndtr/goleveldb/leveldb"
"github.com/syndtr/goleveldb/leveldb/opt"
"github.com/syndtr/goleveldb/leveldb/util"
"strings"
"sync"
)
@ -30,13 +33,34 @@ func (db *userdb) getPublicKey() (*rsa.PublicKey, error) {
return &key, nil
}
func getUserDB(nick string) (*userdb, error) {
func (db *userdb) nextKey(prefix string) (string, error) {
r := util.BytesPrefix([]byte(prefix))
it := db.NewIterator(r, nil)
defer it.Release()
id := 0
if it.Last() {
key := it.Key()
id_s := strings.TrimPrefix(string(key), prefix)
lastId, err := decodeInt(id_s)
if err != nil {
return "0", fmt.Errorf("error getting note id: %v", err)
}
id = lastId + 1
}
return fmt.Sprintf("%s%s", prefix, encodeInt(id)), nil
}
func getUserDB(nick string, create bool) (*userdb, error) {
if db, ok := openDBs[nick]; ok {
return &db, nil
}
opts := &opt.Options{
ErrorIfMissing: create,
}
path := fmt.Sprintf("./%s.db", nick)
conn, err := leveldb.OpenFile(path, nil)
conn, err := leveldb.OpenFile(path, opts)
if err != nil {
return nil, fmt.Errorf("unable to open db file at %s: %v", path, err)
}
@ -51,7 +75,7 @@ func getUserDB(nick string) (*userdb, error) {
}
func getUserKey(nick string) (*rsa.PublicKey, error) {
db, err := getUserDB(nick)
db, err := getUserDB(nick, false)
if err != nil {
return nil, err
}

@ -0,0 +1 @@
This is Alice. This is Alice's secret message for herself.

@ -13,6 +13,12 @@ type Envelope struct {
Body json.RawMessage
}
type Bool bool
func (b Bool) Kind() string {
return "bool"
}
type request interface {
Kind() string
}

@ -52,6 +52,8 @@ func (s *serverConnection) handleRequest(request Envelope) error {
return s.handleListNotesRequest(request.Id, request.Body)
case "key":
return s.handleKeyRequest(request.Id, request.Body)
case "message":
return s.handleMessageRequest(request.Id, request.Body)
default:
return fmt.Errorf("no such request type: %v", request.Kind)
}
@ -208,8 +210,31 @@ func (s *serverConnection) handleKeyRequest(requestId int, body json.RawMessage)
return s.sendResponse(requestId, res)
}
func (s *serverConnection) handleMessageRequest(requestId int, body json.RawMessage) error {
var req Message
if err := json.Unmarshal(body, &req); err != nil {
error_log.Printf("unable to read message request: %v", err)
return err
}
db, err := getUserDB(req.To, false)
if err != nil {
return err
}
k, err := db.nextKey("messages/")
if err != nil {
return fmt.Errorf("unable to save message: %v", err)
}
if err := db.Put([]byte(k), body, nil); err != nil {
return fmt.Errorf("unable to save message: %v", err)
}
return s.sendResponse(requestId, Bool(true))
}
func (s *serverConnection) openDB() error {
db, err := getUserDB(s.nick)
db, err := getUserDB(s.nick, true)
if err != nil {
return err
}

Loading…
Cancel
Save