Actually implementing correct signature construction

This commit is contained in:
Sarah Jamie Lewis 2018-06-22 11:11:23 -07:00
parent 1ea1521fee
commit 22aebae0e5
14 changed files with 98 additions and 92 deletions

View File

@ -80,13 +80,13 @@ func (g *Group) Invite() ([]byte, error) {
}
// AddMessage takes a DecryptedGroupMessage and adds it to the Groups Timeline
func (g *Group) AddMessage(message *protocol.DecryptedGroupMessage, verified bool) *Message {
func (g *Group) AddMessage(message *protocol.DecryptedGroupMessage, sig []byte, verified bool) *Message {
g.lock.Lock()
timelineMessage := &Message{
Message: message.GetText(),
Timestamp: time.Unix(int64(message.GetTimestamp()), 0),
Received: time.Now(),
Signature: message.GetSignature(),
Signature: sig,
Verified: verified,
PeerID: message.GetOnion(),
PreviousMessageSig: message.GetPreviousMessageSig(),

View File

@ -14,7 +14,6 @@ func TestGroup(t *testing.T) {
Text: proto.String("Hello World!"),
Timestamp: proto.Int32(int32(time.Now().Unix())),
SignedGroupId: []byte{},
Signature: []byte{},
PreviousMessageSig: []byte{},
Padding: []byte{},
}

View File

@ -23,21 +23,21 @@ func TestMessagePadding(t *testing.T) {
group := alice.GetGroupByGroupID(gid)
c1, _ := sarah.EncryptMessageToGroup("Hello World 1", group.GroupID)
c1, s1, _ := sarah.EncryptMessageToGroup("Hello World 1", group.GroupID)
t.Logf("Length of Encrypted Message: %v", len(c1))
alice.AttemptDecryption(c1)
alice.AttemptDecryption(c1, s1)
c2, _ := alice.EncryptMessageToGroup("Hello World 2", group.GroupID)
c2, s2, _ := alice.EncryptMessageToGroup("Hello World 2", group.GroupID)
t.Logf("Length of Encrypted Message: %v", len(c2))
alice.AttemptDecryption(c2)
alice.AttemptDecryption(c2, s2)
c3, _ := alice.EncryptMessageToGroup("Hello World 3", group.GroupID)
c3, s3, _ := alice.EncryptMessageToGroup("Hello World 3", group.GroupID)
t.Logf("Length of Encrypted Message: %v", len(c3))
alice.AttemptDecryption(c3)
alice.AttemptDecryption(c3, s3)
c4, _ := alice.EncryptMessageToGroup("Hello World this is a much longer message 3", group.GroupID)
c4, s4, _ := alice.EncryptMessageToGroup("Hello World this is a much longer message 3", group.GroupID)
t.Logf("Length of Encrypted Message: %v", len(c4))
alice.AttemptDecryption(c4)
alice.AttemptDecryption(c4, s4)
}
@ -59,33 +59,33 @@ func TestTranscriptConsistency(t *testing.T) {
t.Logf("group: %v, sarah %v", group, sarah)
c1, _ := alice.EncryptMessageToGroup("Hello World 1", group.GroupID)
c1, s1, _ := alice.EncryptMessageToGroup("Hello World 1", group.GroupID)
t.Logf("Length of Encrypted Message: %v", len(c1))
alice.AttemptDecryption(c1)
alice.AttemptDecryption(c1, s1)
c2, _ := alice.EncryptMessageToGroup("Hello World 2", group.GroupID)
c2, s2, _ := alice.EncryptMessageToGroup("Hello World 2", group.GroupID)
t.Logf("Length of Encrypted Message: %v", len(c2))
alice.AttemptDecryption(c2)
alice.AttemptDecryption(c2, s2)
c3, _ := alice.EncryptMessageToGroup("Hello World 3", group.GroupID)
c3, s3, _ := alice.EncryptMessageToGroup("Hello World 3", group.GroupID)
t.Logf("Length of Encrypted Message: %v", len(c3))
alice.AttemptDecryption(c3)
alice.AttemptDecryption(c3, s3)
time.Sleep(time.Second * 1)
c4, _ := alice.EncryptMessageToGroup("Hello World 4", group.GroupID)
c4, s4, _ := alice.EncryptMessageToGroup("Hello World 4", group.GroupID)
t.Logf("Length of Encrypted Message: %v", len(c4))
alice.AttemptDecryption(c4)
alice.AttemptDecryption(c4, s4)
c5, _ := alice.EncryptMessageToGroup("Hello World 5", group.GroupID)
c5, s5, _ := alice.EncryptMessageToGroup("Hello World 5", group.GroupID)
t.Logf("Length of Encrypted Message: %v", len(c5))
_, m1 := sarah.AttemptDecryption(c1)
sarah.AttemptDecryption(c1) // Try a duplicate
_, m2 := sarah.AttemptDecryption(c2)
_, m3 := sarah.AttemptDecryption(c3)
_, m4 := sarah.AttemptDecryption(c4)
_, m5 := sarah.AttemptDecryption(c5)
_, m1 := sarah.AttemptDecryption(c1, s1)
sarah.AttemptDecryption(c1, s1) // Try a duplicate
_, m2 := sarah.AttemptDecryption(c2, s2)
_, m3 := sarah.AttemptDecryption(c3, s3)
_, m4 := sarah.AttemptDecryption(c4, s4)
_, m5 := sarah.AttemptDecryption(c5, s5)
// Now we simulate a client receiving these messages completely out of order
timeline.Insert(m1)

View File

@ -10,7 +10,6 @@ import (
"git.openprivacy.ca/openprivacy/libricochet-go/utils"
"golang.org/x/crypto/ed25519"
"io"
"strconv"
"sync"
"time"
)
@ -171,16 +170,21 @@ func (p *Profile) GetContact(onion string) (*PublicProfile, bool) {
}
// VerifyGroupMessage confirms the authenticity of a message given an onion, message and signature.
func (p *Profile) VerifyGroupMessage(onion string, groupID string, message string, timestamp int32, signature []byte) bool {
func (p *Profile) VerifyGroupMessage(onion string, groupID string, message string, timestamp int32, ciphertext []byte, signature []byte) bool {
group := p.GetGroupByGroupID(groupID)
if group == nil {
return false
}
if onion == p.Onion {
m := message + groupID + strconv.Itoa(int(timestamp))
m := groupID + group.GroupServer + string(ciphertext)
return ed25519.Verify(p.Ed25519PublicKey, []byte(m), signature)
}
contact, found := p.GetContact(onion)
if found {
m := message + groupID + strconv.Itoa(int(timestamp))
m := groupID + group.GroupServer + string(ciphertext)
return ed25519.Verify(contact.Ed25519PublicKey, []byte(m), signature)
}
return false
@ -250,7 +254,7 @@ func (p *Profile) AddGroup(group *Group) {
}
// AttemptDecryption takes a ciphertext and signature and attempts to decrypt it under known groups.
func (p *Profile) AttemptDecryption(ciphertext []byte) (bool, *Message) {
func (p *Profile) AttemptDecryption(ciphertext []byte, signature []byte) (bool, *Message) {
for _, group := range p.Groups {
success, dgm := group.DecryptMessage(ciphertext)
if success {
@ -269,8 +273,8 @@ func (p *Profile) AttemptDecryption(ciphertext []byte) (bool, *Message) {
}
}
verified := p.VerifyGroupMessage(dgm.GetOnion(), group.GroupID, dgm.GetText(), dgm.GetTimestamp(), dgm.GetSignature())
return true, group.AddMessage(dgm, verified)
verified := p.VerifyGroupMessage(dgm.GetOnion(), group.GroupID, dgm.GetText(), dgm.GetTimestamp(), ciphertext, signature)
return true, group.AddMessage(dgm, signature, verified)
}
}
return false, nil
@ -284,11 +288,11 @@ func getRandomness(arr *[]byte) {
// EncryptMessageToGroup when given a message and a group, encrypts and signs the message under the group and
// profile
func (p *Profile) EncryptMessageToGroup(message string, groupID string) ([]byte, error) {
func (p *Profile) EncryptMessageToGroup(message string, groupID string) ([]byte, []byte, error) {
group := p.GetGroupByGroupID(groupID)
if group != nil {
timestamp := time.Now().Unix()
signature := p.SignMessage(message + groupID + strconv.Itoa(int(timestamp)))
var prevSig []byte
if len(group.Timeline.Messages) > 0 {
prevSig = group.Timeline.Messages[len(group.Timeline.Messages)-1].Signature
@ -305,12 +309,12 @@ func (p *Profile) EncryptMessageToGroup(message string, groupID string) ([]byte,
Text: proto.String(message),
SignedGroupId: group.SignedGroupID[:],
Timestamp: proto.Int32(int32(timestamp)),
Signature: signature,
PreviousMessageSig: prevSig,
Padding: padding[:],
}
ciphertext := group.EncryptMessage(dm)
return ciphertext, nil
signature := p.SignMessage(groupID + group.GroupServer + string(ciphertext))
return ciphertext, signature, nil
}
return nil, errors.New("group does not exist")
return nil, nil, errors.New("group does not exist")
}

View File

@ -104,29 +104,29 @@ func TestProfileGroup(t *testing.T) {
group := alice.GetGroupByGroupID(gid)
sarah.AcceptInvite(group.GroupID)
c, _ := sarah.EncryptMessageToGroup("Hello World", group.GroupID)
alice.AttemptDecryption(c)
c, s1, _ := sarah.EncryptMessageToGroup("Hello World", group.GroupID)
alice.AttemptDecryption(c, s1)
gid2, invite2, _ := alice.StartGroup("bbb.onion")
gci2 := &protocol.CwtchPeerPacket{}
proto.Unmarshal(invite2, gci2)
sarah.ProcessInvite(gci2.GetGroupChatInvite(), alice.Onion)
group2 := alice.GetGroupByGroupID(gid2)
c2, _ := sarah.EncryptMessageToGroup("Hello World", group2.GroupID)
alice.AttemptDecryption(c2)
c2, s2, _ := sarah.EncryptMessageToGroup("Hello World", group2.GroupID)
alice.AttemptDecryption(c2, s2)
bob := GenerateNewProfile("bob")
bob.AddContact(alice.Onion, &alice.PublicProfile)
bob.ProcessInvite(gci2.GetGroupChatInvite(), alice.Onion)
c3, err := bob.EncryptMessageToGroup("Bobs Message", group2.GroupID)
c3, s3, err := bob.EncryptMessageToGroup("Bobs Message", group2.GroupID)
if err == nil {
ok, message := alice.AttemptDecryption(c3)
ok, message := alice.AttemptDecryption(c3, s3)
if ok != true || message.Verified == true {
t.Errorf("Bobs message to the group should be decrypted but not verified by alice instead %v %v", message, ok)
}
eve := GenerateNewProfile("eve")
ok, _ = eve.AttemptDecryption(c3)
ok, _ = eve.AttemptDecryption(c3, s3)
if ok {
t.Errorf("Eves hould not be able to decrypt messages!")
}

View File

@ -29,7 +29,7 @@ func (ts *TestServer) HandleGroupMessage(gm *protocol.GroupMessage) {
}
func (ts *TestServer) HandleFetchRequest() []*protocol.GroupMessage {
return []*protocol.GroupMessage{{Ciphertext: []byte("hello"), Spamguard: []byte{}}, {Ciphertext: []byte("hello"), Spamguard: []byte{}}}
return []*protocol.GroupMessage{{Ciphertext: []byte("hello"), Signature: []byte{}, Spamguard: []byte{}}, {Ciphertext: []byte("hello"), Signature: []byte{}, Spamguard: []byte{}}}
}
func runtestserver(t *testing.T, ts *TestServer, privateKey *rsa.PrivateKey) {
@ -92,7 +92,7 @@ func TestPeerServerConnection(t *testing.T) {
t.Errorf("connection should now be authed(%v), instead was %v", AUTHENTICATED, state)
}
gm := &protocol.GroupMessage{Ciphertext: []byte("hello")}
gm := &protocol.GroupMessage{Ciphertext: []byte("hello"), Signature: []byte{}}
psc.SendGroupMessage(gm)
time.Sleep(time.Second * 2)
if ts.Received == false {

View File

@ -214,7 +214,7 @@ func (cp *cwtchPeer) InviteOnionToGroup(onion string, groupid string) error {
// ReceiveGroupMessage is a callback function that processes GroupMessages from a given server
func (cp *cwtchPeer) ReceiveGroupMessage(server string, gm *protocol.GroupMessage) {
cp.Profile.AttemptDecryption(gm.Ciphertext)
cp.Profile.AttemptDecryption(gm.Ciphertext, gm.Signature)
}
// JoinServer manages a new server connection with the given onion address
@ -232,12 +232,13 @@ func (cp *cwtchPeer) SendMessageToGroup(groupid string, message string) error {
if psc == nil {
return errors.New("could not find server connection to send message to")
}
ct, err := cp.Profile.EncryptMessageToGroup(message, groupid)
ct, sig, err := cp.Profile.EncryptMessageToGroup(message, groupid)
if err != nil {
return err
}
gm := &protocol.GroupMessage{
Ciphertext: ct,
Signature: sig,
}
err = psc.SendGroupMessage(gm)
return err

View File

@ -74,7 +74,7 @@ func TestPeerFetchChannel(t *testing.T) {
csp := &protocol.CwtchServerPacket{
GroupMessage: &protocol.GroupMessage{
Ciphertext: []byte("hello"), Spamguard: []byte{},
Ciphertext: []byte("hello"), Signature: []byte{}, Spamguard: []byte{},
},
}
packet, _ := proto.Marshal(csp)

View File

@ -71,7 +71,7 @@ func TestPeerListenChannel(t *testing.T) {
}
csp := &protocol.CwtchServerPacket{
GroupMessage: &protocol.GroupMessage{Ciphertext: []byte("hello"), Spamguard: []byte{}},
GroupMessage: &protocol.GroupMessage{Ciphertext: []byte("hello"), Signature: []byte{}, Spamguard: []byte{}},
}
packet, _ := proto.Marshal(csp)

View File

@ -50,6 +50,7 @@ func (*FetchMessage) Descriptor() ([]byte, []int) { return fileDescriptor2, []in
type GroupMessage struct {
Ciphertext []byte `protobuf:"bytes,1,req,name=ciphertext" json:"ciphertext,omitempty"`
Spamguard []byte `protobuf:"bytes,2,req,name=spamguard" json:"spamguard,omitempty"`
Signature []byte `protobuf:"bytes,3,req,name=signature" json:"signature,omitempty"`
XXX_unrecognized []byte `json:"-"`
}
@ -72,6 +73,13 @@ func (m *GroupMessage) GetSpamguard() []byte {
return nil
}
func (m *GroupMessage) GetSignature() []byte {
if m != nil {
return m.Signature
}
return nil
}
// DecryptedGroupMessage is *never* sent in the clear on the wire
// and is only ever sent when encrypted in the ciphertext parameter of
// GroupMessage
@ -79,11 +87,10 @@ type DecryptedGroupMessage struct {
Onion *string `protobuf:"bytes,1,req,name=onion" json:"onion,omitempty"`
Timestamp *int32 `protobuf:"varint,2,req,name=timestamp" json:"timestamp,omitempty"`
Text *string `protobuf:"bytes,3,req,name=text" json:"text,omitempty"`
Signature []byte `protobuf:"bytes,4,req,name=signature" json:"signature,omitempty"`
SignedGroupId []byte `protobuf:"bytes,5,req,name=signed_group_id,json=signedGroupId" json:"signed_group_id,omitempty"`
PreviousMessageSig []byte `protobuf:"bytes,6,req,name=previous_message_sig,json=previousMessageSig" json:"previous_message_sig,omitempty"`
SignedGroupId []byte `protobuf:"bytes,4,req,name=signed_group_id,json=signedGroupId" json:"signed_group_id,omitempty"`
PreviousMessageSig []byte `protobuf:"bytes,5,req,name=previous_message_sig,json=previousMessageSig" json:"previous_message_sig,omitempty"`
// Used to prevent analysis on text length, length is 1024 - len(text)
Padding []byte `protobuf:"bytes,7,req,name=padding" json:"padding,omitempty"`
Padding []byte `protobuf:"bytes,6,req,name=padding" json:"padding,omitempty"`
XXX_unrecognized []byte `json:"-"`
}
@ -113,13 +120,6 @@ func (m *DecryptedGroupMessage) GetText() string {
return ""
}
func (m *DecryptedGroupMessage) GetSignature() []byte {
if m != nil {
return m.Signature
}
return nil
}
func (m *DecryptedGroupMessage) GetSignedGroupId() []byte {
if m != nil {
return m.SignedGroupId
@ -161,29 +161,28 @@ func init() {
func init() { proto.RegisterFile("group_message.proto", fileDescriptor2) }
var fileDescriptor2 = []byte{
// 372 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x52, 0xdd, 0xaa, 0xd3, 0x30,
0x1c, 0xa7, 0xfb, 0x70, 0xee, 0xbf, 0x6e, 0x62, 0x9c, 0x1a, 0x44, 0xa4, 0xf4, 0x42, 0x76, 0x35,
0xc4, 0x4b, 0x87, 0x20, 0x4c, 0x14, 0x41, 0x45, 0xba, 0x07, 0x28, 0xa1, 0xfd, 0x2f, 0x0d, 0xb6,
0x49, 0x48, 0xd2, 0x9d, 0x73, 0xde, 0xe0, 0x3c, 0xdc, 0x79, 0x99, 0xf3, 0x06, 0x87, 0xa6, 0xeb,
0xd6, 0x9d, 0x8b, 0x73, 0x55, 0x7e, 0xdf, 0x21, 0x0d, 0xbc, 0xe2, 0x46, 0xd5, 0x3a, 0xad, 0xd0,
0x5a, 0xc6, 0x71, 0xad, 0x8d, 0x72, 0x8a, 0x3c, 0xf7, 0x9f, 0x4c, 0x95, 0xef, 0x96, 0x5b, 0x25,
0x9d, 0x51, 0xe5, 0xb6, 0x60, 0x52, 0x62, 0xd9, 0xea, 0xf1, 0x5d, 0x00, 0x2f, 0xb7, 0x57, 0x2e,
0x2b, 0x76, 0x68, 0x0e, 0x68, 0xfe, 0xb1, 0xec, 0x3f, 0x3a, 0xb2, 0x81, 0xf9, 0x45, 0x19, 0x0d,
0xa2, 0x60, 0x35, 0xfb, 0xfc, 0x66, 0xdd, 0xb5, 0xad, 0x7f, 0x36, 0xf2, 0x9f, 0x56, 0x4d, 0x42,
0xde, 0x43, 0x4d, 0x78, 0x8f, 0x2e, 0x2b, 0x4e, 0xe1, 0xc1, 0xe3, 0xf0, 0x8f, 0x46, 0x3e, 0x85,
0xf7, 0x3d, 0x44, 0xbe, 0xc2, 0xe2, 0x62, 0xd9, 0xd2, 0x61, 0x34, 0x7c, 0x62, 0x7a, 0xde, 0x9f,
0xb6, 0xf1, 0x02, 0xc2, 0x7e, 0x79, 0xfc, 0x1b, 0xc2, 0xbe, 0x9d, 0x7c, 0x00, 0xc8, 0x84, 0x2e,
0xd0, 0x38, 0xbc, 0x76, 0x34, 0x88, 0x06, 0xab, 0x30, 0xe9, 0x31, 0xe4, 0x3d, 0x4c, 0xad, 0x66,
0x15, 0xaf, 0x99, 0xc9, 0xe9, 0xc0, 0xcb, 0x67, 0x22, 0xbe, 0x0f, 0xe0, 0xf5, 0x77, 0xcc, 0xcc,
0x8d, 0x76, 0x98, 0x5f, 0xf4, 0x2e, 0x61, 0xac, 0xa4, 0x50, 0xd2, 0x57, 0x4e, 0x93, 0x16, 0x34,
0x6d, 0x4e, 0x54, 0x68, 0x1d, 0xab, 0xb4, 0x6f, 0x1b, 0x27, 0x67, 0x82, 0x10, 0x18, 0xf9, 0x53,
0x0c, 0x7d, 0x64, 0x74, 0xda, 0x17, 0x5c, 0x32, 0x57, 0x1b, 0xa4, 0xa3, 0xe3, 0x7e, 0x47, 0x90,
0x8f, 0xf0, 0xa2, 0x01, 0x98, 0xa7, 0xed, 0x1d, 0x89, 0x9c, 0x8e, 0xbd, 0x67, 0xde, 0xd2, 0xfe,
0x48, 0xbf, 0x72, 0xf2, 0x09, 0x96, 0xda, 0xe0, 0x41, 0xa8, 0xda, 0x76, 0xf7, 0x98, 0x5a, 0xc1,
0xe9, 0x33, 0x6f, 0x26, 0x9d, 0x76, 0x3c, 0xfc, 0x4e, 0x70, 0x42, 0x61, 0xa2, 0x59, 0x9e, 0x0b,
0xc9, 0xe9, 0xc4, 0x9b, 0x3a, 0xf8, 0x65, 0x03, 0xa1, 0xf5, 0x4f, 0x23, 0x95, 0x4a, 0x66, 0x48,
0xde, 0x9e, 0x7f, 0xc4, 0xf1, 0x25, 0x25, 0x68, 0xeb, 0xd2, 0xd1, 0xdb, 0x6f, 0x51, 0xb0, 0x0a,
0x93, 0x59, 0xeb, 0xfe, 0xdb, 0x98, 0x1f, 0x02, 0x00, 0x00, 0xff, 0xff, 0x3c, 0x2e, 0xc6, 0x75,
0x93, 0x02, 0x00, 0x00,
// 360 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x5c, 0x92, 0x4d, 0x6e, 0xdb, 0x30,
0x10, 0x85, 0x21, 0xff, 0xb4, 0xf5, 0x58, 0x6e, 0x51, 0xd6, 0x6d, 0x89, 0xa2, 0x28, 0x0c, 0x2d,
0x0a, 0xaf, 0x8c, 0x20, 0xcb, 0x78, 0x13, 0xc0, 0x41, 0x82, 0x2c, 0x12, 0x04, 0xf2, 0x01, 0x04,
0x42, 0x1a, 0x53, 0x4c, 0x24, 0x92, 0x20, 0x29, 0x27, 0xb9, 0x41, 0x36, 0x39, 0x5d, 0x2e, 0x14,
0x88, 0xb2, 0x6c, 0x39, 0x2b, 0x69, 0xde, 0x37, 0x6f, 0xde, 0x80, 0x24, 0xfc, 0xe0, 0x46, 0x55,
0x3a, 0x29, 0xd1, 0x5a, 0xc6, 0x71, 0xa1, 0x8d, 0x72, 0x8a, 0x7c, 0xf1, 0x9f, 0x54, 0x15, 0x7f,
0xa6, 0x2b, 0x25, 0x9d, 0x51, 0xc5, 0x2a, 0x67, 0x52, 0x62, 0xd1, 0xf0, 0xe8, 0x35, 0x80, 0xef,
0xab, 0x47, 0x97, 0xe6, 0x6b, 0x34, 0x5b, 0x34, 0x77, 0x2c, 0x7d, 0x40, 0x47, 0x96, 0x30, 0x39,
0x1a, 0x46, 0x83, 0x59, 0x30, 0x1f, 0x9f, 0xfe, 0x5a, 0xb4, 0xd3, 0x16, 0x57, 0x35, 0xbe, 0x69,
0x68, 0x1c, 0xf2, 0x4e, 0x55, 0x9b, 0x37, 0xe8, 0xd2, 0x7c, 0x6f, 0xee, 0x7d, 0x34, 0x5f, 0xd6,
0x78, 0x6f, 0xde, 0x74, 0xaa, 0xe8, 0x2b, 0x84, 0x5d, 0x1a, 0xdd, 0x43, 0xd8, 0x8d, 0x22, 0xff,
0x00, 0x52, 0xa1, 0x73, 0x34, 0x0e, 0x9f, 0x1c, 0x0d, 0x66, 0xbd, 0x79, 0x18, 0x77, 0x14, 0xf2,
0x17, 0x46, 0x56, 0xb3, 0x92, 0x57, 0xcc, 0x64, 0xb4, 0xe7, 0xf1, 0x41, 0xf0, 0x54, 0x70, 0xc9,
0x5c, 0x65, 0x90, 0xf6, 0x77, 0xb4, 0x15, 0xa2, 0xb7, 0x00, 0x7e, 0x5e, 0x60, 0x6a, 0x9e, 0xb5,
0xc3, 0xec, 0x28, 0x75, 0x0a, 0x43, 0x25, 0x85, 0x92, 0x3e, 0x70, 0x14, 0x37, 0x45, 0x3d, 0xcd,
0x89, 0x12, 0xad, 0x63, 0xa5, 0xf6, 0x59, 0xc3, 0xf8, 0x20, 0x10, 0x02, 0x03, 0xbf, 0x63, 0xdf,
0x5b, 0xfc, 0x3f, 0xf9, 0x0f, 0xdf, 0xea, 0x38, 0xcc, 0x92, 0xe6, 0x78, 0x45, 0x46, 0x07, 0x7e,
0x8b, 0x49, 0x23, 0xfb, 0xd0, 0xeb, 0x8c, 0x9c, 0xc0, 0x54, 0x1b, 0xdc, 0x0a, 0x55, 0xd9, 0xf6,
0x14, 0x13, 0x2b, 0x38, 0x1d, 0xfa, 0x66, 0xd2, 0xb2, 0xdd, 0x7a, 0x6b, 0xc1, 0x09, 0x85, 0xcf,
0x9a, 0x65, 0x99, 0x90, 0x9c, 0x7e, 0xf2, 0x4d, 0x6d, 0x79, 0xb6, 0x84, 0xd0, 0xfa, 0xbb, 0x4d,
0xa4, 0x92, 0x29, 0x92, 0xdf, 0x87, 0x7b, 0xd8, 0x3d, 0x85, 0x18, 0x6d, 0x55, 0x38, 0xfa, 0x72,
0x3e, 0x0b, 0xe6, 0x61, 0x3c, 0x6e, 0xba, 0x6f, 0xeb, 0xe6, 0xf7, 0x00, 0x00, 0x00, 0xff, 0xff,
0x33, 0x30, 0xca, 0x8b, 0x54, 0x02, 0x00, 0x00,
}

View File

@ -18,6 +18,7 @@ message FetchMessage {
message GroupMessage {
required bytes ciphertext = 1;
required bytes spamguard = 2;
required bytes signature = 3;
}
// DecryptedGroupMessage is *never* sent in the clear on the wire
@ -27,9 +28,8 @@ message DecryptedGroupMessage {
required string onion = 1;
required int32 timestamp = 2;
required string text = 3;
required bytes signature = 4;
required bytes signed_group_id = 5;
required bytes previous_message_sig =6;
required bytes signed_group_id = 4;
required bytes previous_message_sig =5;
// Used to prevent analysis on text length, length is 1024 - len(text)
required bytes padding = 7;
required bytes padding = 6;
}

View File

@ -69,6 +69,7 @@ func TestServerListenChannel(t *testing.T) {
if control.GetChannelResult() != nil {
gm := &protocol.GroupMessage{
Ciphertext: []byte("Hello"),
Signature: []byte{},
Spamguard: []byte{},
}
cslc.SendGroupMessage(gm)

View File

@ -86,6 +86,7 @@ func TestServerSendChannel(t *testing.T) {
gm := &protocol.GroupMessage{
Ciphertext: []byte("Hello"),
Signature: []byte{},
Spamguard: sgsolve,
}
@ -147,6 +148,7 @@ func TestServerSendChannelNoSpamGuard(t *testing.T) {
gm := &protocol.GroupMessage{
Ciphertext: []byte("hello"),
Signature: []byte{},
Spamguard: sgsolve,
}

View File

@ -182,7 +182,7 @@ func TestCwtchPeerIntegration(t *testing.T) {
bob.JoinServer(serverAddr)
fmt.Println("Waiting for peerings and server joins...")
time.Sleep(time.Second * 60)
time.Sleep(time.Second * 120)
fmt.Println("Alice inviting Bob to group...")
err = alice.InviteOnionToGroup(bob.GetProfile().Onion, groupID)