// Push implements storage.Service. func (s *service) Push(msg *storage.AddressedMessage) error { rcptKey, err := sf.DecodePublicKey(msg.Recipient) if err != nil { return errgo.Notef(err, "invalid recipient %q", msg.Recipient) } senderKey, err := sf.DecodePublicKey(msg.Sender) if err != nil { return errgo.Notef(err, "invalid sender %q", msg.Sender) } nonce, err := sf.DecodeNonce(msg.ID) if err != nil { return errgo.Notef(err, "invalid nonce %q", msg.ID) } return s.db.Update(func(tx *bolt.Tx) error { rcptBucket, err := tx.CreateBucketIfNotExists(rcptKey[:]) if err != nil { return errgo.Mask(err) } senderBucket, err := rcptBucket.CreateBucketIfNotExists(senderKey[:]) if err != nil { return errgo.Mask(err) } err = senderBucket.Put(nonce[:], msg.Contents) if err != nil { return errgo.Mask(err) } return nil }) }
// PublicKey requests a shadowfax server's public key. An error is returned // if the server URL is not https. func PublicKey(serverURL string, client *http.Client) (*sf.PublicKey, error) { u, err := url.Parse(serverURL) if err != nil { return nil, errgo.Mask(err, errgo.Any) } if u.Scheme != "https" { return nil, errgo.Newf("public key must be requested with https") } if client == nil { client = http.DefaultClient } req, err := http.NewRequest("GET", serverURL+"/publickey", nil) if err != nil { return nil, errgo.Mask(err) } resp, err := client.Do(req) if err != nil { return nil, errgo.Mask(err) } defer resp.Body.Close() dec := json.NewDecoder(resp.Body) var publicKeyResp wire.PublicKeyResponse err = dec.Decode(&publicKeyResp) if err != nil { return nil, errgo.Mask(err) } publicKey, err := sf.DecodePublicKey(publicKeyResp.PublicKey) if err != nil { return nil, errgo.Mask(err) } return publicKey, nil }
func (h *Handler) auth(r *http.Request, client string) (*authRequest, error) { var msg wire.Message dec := json.NewDecoder(r.Body) err := dec.Decode(&msg) if err != nil { return nil, errgo.Mask(err) } clientKey, err := sf.DecodePublicKey(client) if err != nil { return nil, errgo.Mask(err) } nonce, err := sf.DecodeNonce(msg.ID) if err != nil { return nil, errgo.Mask(err) } out, ok := box.Open(nil, msg.Contents, (*[24]byte)(nonce), (*[32]byte)(clientKey), (*[32]byte)(h.keyPair.PrivateKey)) if !ok { return nil, errgo.New("authentication failed") } return &authRequest{ Handler: h, ClientKey: clientKey, Nonce: nonce, Contents: out, }, nil }
// Pop implements storage.Service. func (s *service) Pop(recipient string) (_ []*storage.AddressedMessage, popErr error) { rcptKey, err := sf.DecodePublicKey(recipient) if err != nil { return nil, errgo.Notef(err, "invalid recipient %q", recipient) } tx, err := s.db.Begin(true) if err != nil { return nil, errgo.Mask(err) } defer func() { if popErr == nil { popErr = errgo.Mask(tx.Commit()) } else { tx.Rollback() } }() var result []*storage.AddressedMessage rcptBucket, err := tx.CreateBucketIfNotExists(rcptKey[:]) if err != nil { return nil, errgo.Mask(err) } senderCursor := rcptBucket.Cursor() for sender, v := senderCursor.First(); sender != nil; sender, v = senderCursor.Next() { if v != nil { continue } senderBucket := rcptBucket.Bucket(sender) if senderBucket == nil { err = senderCursor.Delete() if err != nil { return nil, errgo.Mask(err) } continue } senderStr := basen.Base58.EncodeToString(sender) msgCursor := senderBucket.Cursor() for id, msg := msgCursor.First(); id != nil; id, msg = msgCursor.Next() { idStr := basen.Base58.EncodeToString(id) msgContents := make([]byte, len(msg)) copy(msgContents, msg) result = append(result, &storage.AddressedMessage{ Recipient: recipient, Sender: senderStr, Message: storage.Message{ ID: idStr, Contents: msgContents, }, }) msgCursor.Delete() if err != nil { return nil, errgo.Mask(err) } } } return result, nil }
func nameAdd() error { contacts, err := newContacts() if err != nil { return err } addrPk, err := sf.DecodePublicKey(*nameAddAddrArg) if err != nil { return errgo.Mask(err) } err = contacts.Put(*nameAddNameArg, addrPk) return errgo.Mask(err) }
// Pop retrieves messages addressed to the client. func (c *Client) Pop() ([]*PopMessage, error) { respContents, err := c.Request("DELETE", "/inbox/"+c.keyPair.PublicKey.Encode(), nil) if err != nil { return nil, errgo.Mask(err) } var wireMessages []wire.PopMessage err = json.Unmarshal(respContents, &wireMessages) if err != nil { return nil, errgo.Mask(err) } var popMessages []*PopMessage var errors errorSlice for _, msg := range wireMessages { nonce, err := sf.DecodeNonce(msg.ID) if err != nil { errors = append(errors, errgo.Notef(err, "ID=%q Sender=%q", msg.ID, msg.Sender)) continue } senderKey, err := sf.DecodePublicKey(msg.Sender) if err != nil { errors = append(errors, errgo.Notef(err, "ID=%q Sender=%q", msg.ID, msg.Sender)) continue } contents, ok := box.Open(nil, msg.Contents, (*[24]byte)(nonce), (*[32]byte)(senderKey), (*[32]byte)(c.keyPair.PrivateKey)) if !ok { errors = append(errors, errgo.Newf("invalid message contents: ID=%q Sender=%q", msg.ID, msg.Sender)) continue } popMessages = append(popMessages, &PopMessage{ ID: msg.ID, Contents: contents, Sender: msg.Sender, }) } if len(errors) > 0 { return popMessages, errors } return popMessages, nil }
// Push pushes a message to a recipient. func (c *Client) Push(recipient string, contents []byte) error { nonce, err := sf.NewNonce() if err != nil { return errgo.Mask(err) } rcptKey, err := sf.DecodePublicKey(recipient) if err != nil { return errgo.Mask(err) } encMsg := box.Seal(nil, contents, (*[24]byte)(nonce), (*[32]byte)(rcptKey), (*[32]byte)(c.keyPair.PrivateKey)) pushWire := []wire.PushMessage{{ Message: wire.Message{ ID: nonce.Encode(), Contents: encMsg, }, Recipient: recipient, }} reqContents, err := json.Marshal(&pushWire) if err != nil { return errgo.Mask(err) } respContents, err := c.Request("POST", "/outbox/"+c.keyPair.PublicKey.Encode(), reqContents) if err != nil { return errgo.Mask(err) } var pushReceipts []wire.PushReceipt err = json.Unmarshal(respContents, &pushReceipts) if err != nil { return errgo.Mask(err) } for _, receipt := range pushReceipts { if receipt.OK && receipt.ID == nonce.Encode() { return nil } } return errgo.New("not acknowledged") }
func newClient(keyPair *sf.KeyPair) (*sfhttp.Client, error) { var err error var serverKey *sf.PublicKey if *serverKeyFlag == "" { serverKey, err = sfhttp.PublicKey((*urlFlagVar).String(), nil) if err != nil { return nil, errgo.Mask(err) } } else { serverKey, err = sf.DecodePublicKey(*serverKeyFlag) if err != nil { return nil, errgo.Mask(err) } } return sfhttp.NewClient(keyPair, (*urlFlagVar).String(), serverKey, &http.Client{ Transport: &http.Transport{ TLSClientConfig: &tls.Config{ InsecureSkipVerify: true, }, }, }), nil }