2018-03-09 20:44:13 +00:00
|
|
|
package model
|
|
|
|
|
|
|
|
import (
|
|
|
|
"crypto/rand"
|
|
|
|
"fmt"
|
|
|
|
"golang.org/x/crypto/nacl/secretbox"
|
|
|
|
"io"
|
|
|
|
)
|
|
|
|
|
2018-03-15 16:33:26 +00:00
|
|
|
|
|
|
|
//Group defines and encapsulates Cwtch's conception of group chat. Which are sessions
|
|
|
|
// tied to a server under a given group key. Each group has a set of messages.
|
2018-03-09 20:44:13 +00:00
|
|
|
type Group struct {
|
|
|
|
GroupID string
|
|
|
|
GroupKey [32]byte
|
|
|
|
GroupServer string
|
|
|
|
Timeline []Message
|
|
|
|
}
|
|
|
|
|
2018-03-15 16:33:26 +00:00
|
|
|
// NewGroup initializes a new group associated with a given CwtchServer
|
2018-03-09 20:44:13 +00:00
|
|
|
func NewGroup(server string) *Group {
|
|
|
|
group := new(Group)
|
|
|
|
group.GroupServer = server
|
|
|
|
|
|
|
|
var groupID [16]byte
|
|
|
|
if _, err := io.ReadFull(rand.Reader, groupID[:]); err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
group.GroupID = fmt.Sprintf("%x", groupID)
|
|
|
|
|
|
|
|
var groupKey [32]byte
|
|
|
|
if _, err := io.ReadFull(rand.Reader, groupKey[:]); err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
copy(group.GroupKey[:], groupKey[:])
|
|
|
|
return group
|
|
|
|
}
|
|
|
|
|
2018-03-15 16:33:26 +00:00
|
|
|
// AddMember ...
|
2018-03-09 20:44:13 +00:00
|
|
|
func (g *Group) AddMember() {
|
|
|
|
// TODO: Rotate Key
|
|
|
|
}
|
|
|
|
|
2018-03-15 16:33:26 +00:00
|
|
|
// RemoveMember ...
|
2018-03-09 20:44:13 +00:00
|
|
|
func (g *Group) RemoveMember() {
|
|
|
|
// TODO: Rotate Key
|
|
|
|
}
|
|
|
|
|
2018-03-15 16:33:26 +00:00
|
|
|
//EncryptMessage takes a message and encrypts the message under the group key.
|
2018-03-09 20:44:13 +00:00
|
|
|
func (g *Group) EncryptMessage(message string) []byte {
|
|
|
|
var nonce [24]byte
|
|
|
|
if _, err := io.ReadFull(rand.Reader, nonce[:]); err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
encrypted := secretbox.Seal(nonce[:], []byte(message), &nonce, &g.GroupKey)
|
|
|
|
return encrypted
|
|
|
|
}
|
|
|
|
|
2018-03-15 16:33:26 +00:00
|
|
|
// DecryptMessage takes a ciphertext and returns true and the decrypted message if the
|
|
|
|
// cipher text can be successfully decrypted,else false.
|
2018-03-09 20:44:13 +00:00
|
|
|
func (g *Group) DecryptMessage(ciphertext []byte) (bool, string) {
|
|
|
|
var decryptNonce [24]byte
|
|
|
|
copy(decryptNonce[:], ciphertext[:24])
|
|
|
|
decrypted, ok := secretbox.Open(nil, ciphertext[24:], &decryptNonce, &g.GroupKey)
|
|
|
|
if ok {
|
|
|
|
return true, string(decrypted)
|
|
|
|
}
|
|
|
|
return false, ""
|
|
|
|
}
|