removing panics and reorder invite-to-group args

This commit is contained in:
Dan Ballard 2018-09-26 17:08:54 -07:00
parent aef41ed4fa
commit a5ad2a6644
8 changed files with 66 additions and 45 deletions

View File

@ -57,8 +57,11 @@ func (app *application) CreatePeer(name string, password string) (peer.CwtchPeer
log.Printf("CreatePeer(%v)\n", name)
randomFileName := generateRandomFilename()
p := peer.NewCwtchPeer(name, password, path.Join(app.directory, "profiles", randomFileName))
err := p.Save()
p, err := peer.NewCwtchPeer(name, password, path.Join(app.directory, "profiles", randomFileName))
if err != nil {
return nil, err
}
err = p.Save()
if err != nil {
p.Shutdown() //attempt
return nil, fmt.Errorf("Error attempting to save new profile: %v", err)
@ -131,7 +134,7 @@ func (app *application) startPeer(peer peer.CwtchPeer) {
go func() {
e := peer.Listen()
if e != nil {
log.Panic(e)
log.Fatalf("ERROR: peer %v has crashed with: %v\n", peer.GetProfile().Onion, e)
}
}()
}

View File

@ -72,7 +72,7 @@ var usages = map[string]string{
"/timeline": "/timeline [groupid]",
"/accept-invite": "/accept-invite [groupid]",
"/invite": "/invite [peerid]",
"/invite-to-group": "/invite-to-group [peerid] [groupid]",
"/invite-to-group": "/invite-to-group [groupid] [peerid]",
"/new-group": "/new-group [server]",
"/help": "",
"/trust": "/trust [peerid]",
@ -175,26 +175,26 @@ func completer(d prompt.Document) []prompt.Suggest {
return prompt.FilterHasPrefix(s, d.GetWordBeforeCursor(), true)
}
// suggest peerid AND groupid
// suggest groupid AND peerid
if strings.HasPrefix(w, "/invite-to-group") {
if d.FindStartOfPreviousWordWithSpace() == 0 {
s = []prompt.Suggest{}
contacts := peer.GetContacts()
for _, onion := range contacts {
contact := peer.GetContact(onion)
s = append(s, prompt.Suggest{Text: contact.Onion, Description: contact.Name})
groups := peer.GetGroups()
for _, groupID := range groups {
group := peer.GetGroup(groupID)
if group.Owner == "self" {
s = append(s, prompt.Suggest{Text: group.GroupID, Description: "Group owned by " + group.Owner + " on " + group.GroupServer})
}
}
return prompt.FilterHasPrefix(s, d.GetWordBeforeCursor(), true)
}
s = []prompt.Suggest{}
groups := peer.GetGroups()
for _, groupID := range groups {
group := peer.GetGroup(groupID)
if group.Owner == "self" {
s = append(s, prompt.Suggest{Text: group.GroupID, Description: "Group owned by " + group.Owner + " on " + group.GroupServer})
}
contacts := peer.GetContacts()
for _, onion := range contacts {
contact := peer.GetContact(onion)
s = append(s, prompt.Suggest{Text: contact.Onion, Description: contact.Name})
}
return prompt.FilterHasPrefix(s, d.GetWordBeforeCursor(), true)
}
@ -450,7 +450,7 @@ func main() {
case "/invite-to-group":
if len(commands) == 3 {
fmt.Printf("Inviting %v to %v\n", commands[1], commands[2])
err := peer.InviteOnionToGroup(commands[1], commands[2])
err := peer.InviteOnionToGroup(commands[2], commands[1])
if err != nil {
fmt.Printf("Error: %v\n", err)
}

View File

@ -9,6 +9,7 @@ import (
"github.com/golang/protobuf/proto"
"golang.org/x/crypto/nacl/secretbox"
"io"
"log"
"sync"
"time"
)
@ -29,23 +30,25 @@ type Group struct {
}
// NewGroup initializes a new group associated with a given CwtchServer
func NewGroup(server string) *Group {
func NewGroup(server string) (*Group, error) {
group := new(Group)
group.GroupServer = server
var groupID [16]byte
if _, err := io.ReadFull(rand.Reader, groupID[:]); err != nil {
panic(err)
log.Printf("Error: Cannot read from random: %v\n", err)
return nil, err
}
group.GroupID = fmt.Sprintf("%x", groupID)
var groupKey [32]byte
if _, err := io.ReadFull(rand.Reader, groupKey[:]); err != nil {
panic(err)
log.Printf("Error: Cannot read from random: %v\n", err)
return nil, err
}
copy(group.GroupKey[:], groupKey[:])
group.Owner = "self"
return group
return group, nil
}
// SignGroup adds a signature to the group.
@ -117,15 +120,16 @@ func (g *Group) GetTimeline() (t []Message) {
}
//EncryptMessage takes a message and encrypts the message under the group key.
func (g *Group) EncryptMessage(message *protocol.DecryptedGroupMessage) []byte {
func (g *Group) EncryptMessage(message *protocol.DecryptedGroupMessage) ([]byte, error) {
var nonce [24]byte
if _, err := io.ReadFull(rand.Reader, nonce[:]); err != nil {
panic(err)
log.Printf("Error: Cannot read from random: %v\n", err)
return nil, err
}
wire, err := proto.Marshal(message)
utils.CheckError(err)
encrypted := secretbox.Seal(nonce[:], []byte(wire), &nonce, &g.GroupKey)
return encrypted
return encrypted, nil
}
// DecryptMessage takes a ciphertext and returns true and the decrypted message if the

View File

@ -8,7 +8,7 @@ import (
)
func TestGroup(t *testing.T) {
g := NewGroup("server.onion")
g, _ := NewGroup("server.onion")
dgm := &protocol.DecryptedGroupMessage{
Onion: proto.String("onion"),
Text: proto.String("Hello World!"),
@ -17,7 +17,7 @@ func TestGroup(t *testing.T) {
PreviousMessageSig: []byte{},
Padding: []byte{},
}
encMessage := g.EncryptMessage(dgm)
encMessage, _ := g.EncryptMessage(dgm)
ok, message := g.DecryptMessage(encMessage)
if !ok || message.GetText() != "Hello World!" {
t.Errorf("group encryption was invalid, or returned wrong message decrypted:%v message:%v", ok, message)

View File

@ -222,7 +222,10 @@ func (p *Profile) StartGroup(server string) (groupID string, invite []byte, err
//StartGroupWithMessage when given a server, and an initial message creates a new Group under this profile and returns the group id an a precomputed
// invite which can be sent on the wire.
func (p *Profile) StartGroupWithMessage(server string, initialMessage []byte) (groupID string, invite []byte, err error) {
group := NewGroup(server)
group, err := NewGroup(server)
if err != nil {
return "", nil, err
}
groupID = group.GroupID
signedGroupID := p.SignMessage(groupID + server)
group.SignGroup(signedGroupID)
@ -336,7 +339,10 @@ func (p *Profile) EncryptMessageToGroup(message string, groupID string) ([]byte,
PreviousMessageSig: prevSig,
Padding: padding[:],
}
ciphertext := group.EncryptMessage(dm)
ciphertext, err := group.EncryptMessage(dm)
if err != nil {
return nil, nil, err
}
signature := p.SignMessage(groupID + group.GroupServer + string(ciphertext))
return ciphertext, signature, nil
}

View File

@ -75,24 +75,26 @@ type CwtchPeer interface {
}
// createKey derives a key and salt for use in encrypting cwtchPeers
func createKey(password string) ([32]byte, [128]byte) {
func createKey(password string) ([32]byte, [128]byte, error) {
var salt [128]byte
if _, err := io.ReadFull(rand.Reader, salt[:]); err != nil {
panic(err)
log.Printf("Error: Cannot read from random: %v\n", err)
return [32]byte{}, salt, err
}
dk := pbkdf2.Key([]byte(password), salt[:], 4096, 32, sha3.New512)
var dkr [32]byte
copy(dkr[:], dk)
return dkr, salt
return dkr, salt, nil
}
//encryptProfile encrypts the cwtchPeer via the specified key.
func encryptProfile(p *cwtchPeer, key [32]byte) []byte {
func encryptProfile(p *cwtchPeer, key [32]byte) ([]byte, error) {
var nonce [24]byte
if _, err := io.ReadFull(rand.Reader, nonce[:]); err != nil {
panic(err)
log.Printf("Error: Cannot read from random: %v\n", err)
return nil, err
}
//copy the struct, then remove the key and salt before saving the copy
@ -104,7 +106,7 @@ func encryptProfile(p *cwtchPeer, key [32]byte) []byte {
cpc.salt = blanksalt
bytes, _ := json.Marshal(cpc)
encrypted := secretbox.Seal(nonce[:], []byte(bytes), &nonce, &key)
return encrypted
return encrypted, nil
}
//decryptProfile decrypts the passed ciphertext into a cwtchPeer via the specified key.
@ -145,26 +147,32 @@ func (cp *cwtchPeer) setup() {
}
// NewCwtchPeer creates and returns a new cwtchPeer with the given name.
func NewCwtchPeer(name string, password string, profilefile string) CwtchPeer {
func NewCwtchPeer(name string, password string, profilefile string) (CwtchPeer, error) {
cp := new(cwtchPeer)
cp.profilefile = profilefile
cp.Profile = model.GenerateNewProfile(name)
cp.setup()
key, salt := createKey(password)
key, salt, err := createKey(password)
if err != nil {
return nil, err
}
cp.key = key
cp.salt = salt
return cp
return cp, nil
}
// Save saves the cwtchPeer profile state to a file.
func (cp *cwtchPeer) Save() error {
cp.mutex.Lock()
encryptedbytes := encryptProfile(cp, cp.key)
defer cp.mutex.Unlock()
encryptedbytes, err := encryptProfile(cp, cp.key)
if err != nil {
return err
}
// the salt for the derived key is appended to the front of the file
encryptedbytes = append(cp.salt[:], encryptedbytes...)
err := ioutil.WriteFile(cp.profilefile, encryptedbytes, 0600)
cp.mutex.Unlock()
err = ioutil.WriteFile(cp.profilefile, encryptedbytes, 0600)
return err
}

View File

@ -6,7 +6,7 @@ import (
func TestCwtchPeerGenerate(t *testing.T) {
alice := NewCwtchPeer("alice", "testpass", "./alice.json")
alice, _ := NewCwtchPeer("alice", "testpass", "./alice.json")
alice.Save()
aliceLoaded, err := LoadCwtchPeer("./alice.json", "testpass")
@ -26,8 +26,8 @@ func TestCwtchPeerGenerate(t *testing.T) {
func TestTrustPeer(t *testing.T) {
groupName := "test.server"
alice := NewCwtchPeer("alice", "alicepass", "")
bob := NewCwtchPeer("bob", "bobpass", "")
alice, _ := NewCwtchPeer("alice", "alicepass", "")
bob, _ := NewCwtchPeer("bob", "bobpass", "")
bobOnion := bob.GetProfile().Onion
aliceOnion := alice.GetProfile().Onion

View File

@ -143,17 +143,17 @@ func TestCwtchPeerIntegration(t *testing.T) {
// ***** Peer setup *****
fmt.Println("Creating Alice...")
alice := peer.NewCwtchPeer("Alice", "alicepass", "")
alice, _ := peer.NewCwtchPeer("Alice", "alicepass", "")
go alice.Listen()
fmt.Println("Alice created:", alice.GetProfile().Onion)
fmt.Println("Creating Bob...")
bob := peer.NewCwtchPeer("Bob", "bobpass", "")
bob, _ := peer.NewCwtchPeer("Bob", "bobpass", "")
go bob.Listen()
fmt.Println("Bob created:", bob.GetProfile().Onion)
fmt.Println("Creating Carol...")
carol := peer.NewCwtchPeer("Carol", "carolpass", "")
carol, _ := peer.NewCwtchPeer("Carol", "carolpass", "")
go carol.Listen()
fmt.Println("Carol created:", carol.GetProfile().Onion)