16
20
Derivar 16

Adding padding and length stuff

Este cometimento está contido em:
Sarah Jamie Lewis 2018-05-28 10:44:47 -07:00
ascendente 7a94394e59
cometimento 6de91969ae
8 ficheiros modificados com 108 adições e 31 eliminações

Ver ficheiro

@ -50,6 +50,7 @@ func NewGroup(server string) *Group {
// SignGroup adds a signature to the group.
func (g *Group) SignGroup(signature []byte) {
g.SignedGroupID = signature
copy(g.Timeline.SignedGroupId[:], g.SignedGroupID)
}
// Compromised should be called if we detect a a groupkey leak.
@ -95,7 +96,7 @@ func (g *Group) AddMessage(message *protocol.DecryptedGroupMessage, verified boo
return timelineMessage
}
// GetTimeline provides a safe copy of the timeline
// GetTimeline provides a safe copy of the timeline-=
func (g *Group) GetTimeline() (t []Message) {
g.lock.Lock()
t = g.Timeline.GetMessages()

Ver ficheiro

@ -16,6 +16,7 @@ func TestGroup(t *testing.T) {
SignedGroupId: []byte{},
Signature: []byte{},
PreviousMessageSig: []byte{},
Padding: []byte{},
}
encMessage := g.EncryptMessage(dgm)
ok, message := g.DecryptMessage(encMessage)

Ver ficheiro

@ -9,8 +9,9 @@ import (
// Timeline encapsulates a collection of ordered messages, and a mechanism to access them
// in a threadsafe manner.
type Timeline struct {
Messages []Message
lock sync.Mutex
Messages []Message
SignedGroupId []byte
lock sync.Mutex
}
// Message is a local representation of a given message sent over a group chat channel.
@ -54,14 +55,14 @@ func (t *Timeline) Swap(i, j int) {
t.Messages[i], t.Messages[j] = t.Messages[j], t.Messages[i]
}
// Less checks 2 messages (i andj) in the timeline and returns true if i cccured before j, else false
// Less checks 2 messages (i andj) in the timeline and returns true if i occcured before j, else false
func (t *Timeline) Less(i, j int) bool {
if t.Messages[i].Timestamp.Before(t.Messages[j].Timestamp) {
return true
}
if compareSignatures(t.Messages[i].PreviousMessageSig, []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}) {
if compareSignatures(t.Messages[i].PreviousMessageSig, t.SignedGroupId) {
return true
}

Ver ficheiro

@ -3,10 +3,44 @@ package model
import (
"git.mascherari.press/cwtch/protocol"
"github.com/golang/protobuf/proto"
"strconv"
"testing"
"time"
)
func TestMessagePadding(t *testing.T) {
// Setup the Group
sarah := GenerateNewProfile("Sarah")
alice := GenerateNewProfile("Alice")
sarah.AddContact(alice.Onion, &alice.PublicProfile)
alice.AddContact(sarah.Onion, &sarah.PublicProfile)
gid, invite, _ := alice.StartGroup("aaa.onion")
gci := &protocol.CwtchPeerPacket{}
proto.Unmarshal(invite, gci)
sarah.ProcessInvite(gci.GetGroupChatInvite(), alice.Onion)
group := alice.GetGroupByGroupID(gid)
c1, _ := sarah.EncryptMessageToGroup("Hello World 1", group.GroupID)
t.Logf("Length of Encrypted Message: %v", len(c1))
alice.AttemptDecryption(c1)
c2, _ := alice.EncryptMessageToGroup("Hello World 2", group.GroupID)
t.Logf("Length of Encrypted Message: %v", len(c2))
alice.AttemptDecryption(c2)
c3, _ := alice.EncryptMessageToGroup("Hello World 3", group.GroupID)
t.Logf("Length of Encrypted Message: %v", len(c3))
alice.AttemptDecryption(c3)
c4, _ := 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)
}
func TestTranscriptConsistency(t *testing.T) {
timeline := new(Timeline)
@ -26,20 +60,25 @@ func TestTranscriptConsistency(t *testing.T) {
t.Logf("group: %v, sarah %v", group, sarah)
c1, _ := sarah.EncryptMessageToGroup("Hello World 1", group.GroupID)
t.Logf("Length of Encrypted Message: %v", len(c1))
alice.AttemptDecryption(c1)
c2, _ := alice.EncryptMessageToGroup("Hello World 2", group.GroupID)
t.Logf("Length of Encrypted Message: %v", len(c2))
alice.AttemptDecryption(c2)
c3, _ := alice.EncryptMessageToGroup("Hello World 3", group.GroupID)
t.Logf("Length of Encrypted Message: %v", len(c3))
alice.AttemptDecryption(c3)
time.Sleep(time.Second * 1)
c4, _ := alice.EncryptMessageToGroup("Hello World 4", group.GroupID)
t.Logf("Length of Encrypted Message: %v", len(c4))
alice.AttemptDecryption(c4)
c5, _ := alice.EncryptMessageToGroup("Hello World 5", group.GroupID)
t.Logf("Length of Encrypted Message: %v", len(c5))
_, m1 := sarah.AttemptDecryption(c1)
_, m2 := sarah.AttemptDecryption(c2)
@ -55,6 +94,10 @@ func TestTranscriptConsistency(t *testing.T) {
timeline.Insert(m2)
for i, m := range timeline.GetMessages() {
if m.Message != "Hello World "+strconv.Itoa(i+1) {
t.Fatalf("Timeline Out of Order!: %v %v", i, m)
}
t.Logf("Messages %v: %v %x %x", i, m.Message, m.Signature, m.PreviousMessageSig)
}
}

Ver ficheiro

@ -10,6 +10,7 @@ import (
"github.com/golang/protobuf/proto"
"github.com/s-rah/go-ricochet/utils"
"golang.org/x/crypto/ed25519"
"io"
"io/ioutil"
"strconv"
"time"
@ -177,6 +178,12 @@ func (p *Profile) AttemptDecryption(ciphertext []byte) (bool, *Message) {
return false, nil
}
func getRandomness(arr *[]byte) {
if _, err := io.ReadFull(rand.Reader, (*arr)[:]); err != nil {
utils.CheckError(err)
}
}
// 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) {
@ -188,8 +195,13 @@ func (p *Profile) EncryptMessageToGroup(message string, groupID string) ([]byte,
if len(group.Timeline.Messages) > 0 {
prevSig = group.Timeline.Messages[len(group.Timeline.Messages)-1].Signature
} else {
prevSig = []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
prevSig = group.SignedGroupID
}
lenPadding := 1024 - len(message)
padding := make([]byte, lenPadding)
getRandomness(&padding)
dm := &protocol.DecryptedGroupMessage{
Onion: proto.String(p.Onion),
Text: proto.String(message),
@ -197,6 +209,7 @@ func (p *Profile) EncryptMessageToGroup(message string, groupID string) ([]byte,
Timestamp: proto.Int32(int32(timestamp)),
Signature: signature,
PreviousMessageSig: prevSig,
Padding: padding[:],
}
ciphertext := group.EncryptMessage(dm)
return ciphertext, nil

Ver ficheiro

@ -90,7 +90,9 @@ type DecryptedGroupMessage struct {
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"`
XXX_unrecognized []byte `json:"-"`
// Used to prevent analysis on text length, length is 1024 - len(text)
Padding []byte `protobuf:"bytes,7,req,name=padding" json:"padding,omitempty"`
XXX_unrecognized []byte `json:"-"`
}
func (m *DecryptedGroupMessage) Reset() { *m = DecryptedGroupMessage{} }
@ -140,6 +142,13 @@ func (m *DecryptedGroupMessage) GetPreviousMessageSig() []byte {
return nil
}
func (m *DecryptedGroupMessage) GetPadding() []byte {
if m != nil {
return m.Padding
}
return nil
}
var E_ServerNonce = &proto.ExtensionDesc{
ExtendedType: (*control.ChannelResult)(nil),
ExtensionType: ([]byte)(nil),
@ -160,28 +169,29 @@ func init() {
func init() { proto.RegisterFile("group_message.proto", fileDescriptor2) }
var fileDescriptor2 = []byte{
// 358 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x52, 0xcd, 0x4a, 0xeb, 0x40,
0x14, 0x26, 0xfd, 0xb9, 0xdc, 0x9e, 0xa6, 0xbd, 0xdc, 0xb9, 0xbd, 0x3a, 0x88, 0x48, 0xc8, 0x42,
0xba, 0x2a, 0xe2, 0xd2, 0x22, 0x08, 0x15, 0x45, 0x50, 0x91, 0xf4, 0x01, 0x42, 0x48, 0x4e, 0x93,
0xc1, 0x64, 0x66, 0x98, 0x99, 0x54, 0x7d, 0x03, 0x1f, 0xce, 0xbd, 0xaf, 0x23, 0x99, 0x34, 0x6d,
0xea, 0xc2, 0xd5, 0x70, 0xbe, 0xdf, 0xc3, 0x61, 0xe0, 0x5f, 0xaa, 0x44, 0x29, 0xc3, 0x02, 0xb5,
0x8e, 0x52, 0x9c, 0x49, 0x25, 0x8c, 0x20, 0xbf, 0xed, 0x13, 0x8b, 0xfc, 0x68, 0xb2, 0x10, 0xdc,
0x28, 0x91, 0x2f, 0xb2, 0x88, 0x73, 0xcc, 0x6b, 0xde, 0xff, 0x70, 0xe0, 0xef, 0xe2, 0xc5, 0xc4,
0xd9, 0x12, 0xd5, 0x1a, 0xd5, 0x53, 0x14, 0x3f, 0xa3, 0x21, 0x73, 0x18, 0xed, 0x85, 0x51, 0xc7,
0x73, 0xa6, 0xc3, 0xf3, 0x83, 0x59, 0x93, 0x36, 0xbb, 0xad, 0xe8, 0x87, 0x9a, 0x0d, 0xdc, 0xb4,
0x35, 0x55, 0xe6, 0x15, 0x9a, 0x38, 0xdb, 0x9a, 0x3b, 0xdf, 0xcd, 0x37, 0x15, 0xbd, 0x35, 0xaf,
0x5a, 0x13, 0xb9, 0x84, 0xf1, 0x5e, 0xb3, 0xa6, 0x5d, 0xaf, 0xfb, 0x43, 0xf5, 0xa8, 0x5d, 0xad,
0xfd, 0x31, 0xb8, 0xed, 0x70, 0xff, 0x1e, 0xdc, 0xb6, 0x9c, 0x9c, 0x00, 0xc4, 0x4c, 0x66, 0xa8,
0x0c, 0xbe, 0x1a, 0xea, 0x78, 0x9d, 0xa9, 0x1b, 0xb4, 0x10, 0x72, 0x0c, 0x03, 0x2d, 0xa3, 0x22,
0x2d, 0x23, 0x95, 0xd0, 0x8e, 0xa5, 0x77, 0x80, 0xff, 0xe9, 0xc0, 0xff, 0x6b, 0x8c, 0xd5, 0x9b,
0x34, 0x98, 0xec, 0xe5, 0x4e, 0xa0, 0x2f, 0x38, 0x13, 0xdc, 0x46, 0x0e, 0x82, 0x7a, 0xa8, 0xd2,
0x0c, 0x2b, 0x50, 0x9b, 0xa8, 0x90, 0x36, 0xad, 0x1f, 0xec, 0x00, 0x42, 0xa0, 0x67, 0xb7, 0xe8,
0x5a, 0x4b, 0x6f, 0xdb, 0xcf, 0x52, 0x1e, 0x99, 0x52, 0x21, 0xed, 0x6d, 0xfa, 0x1b, 0x80, 0x9c,
0xc2, 0x9f, 0x6a, 0xc0, 0x24, 0xac, 0x6f, 0xc4, 0x12, 0xda, 0xb7, 0x9a, 0x51, 0x0d, 0xdb, 0x95,
0xee, 0x12, 0x72, 0x06, 0x13, 0xa9, 0x70, 0xcd, 0x44, 0xa9, 0x9b, 0x3b, 0x86, 0x9a, 0xa5, 0xf4,
0x97, 0x15, 0x93, 0x86, 0xdb, 0x2c, 0xbf, 0x64, 0xe9, 0xc5, 0x1c, 0x5c, 0x6d, 0x3f, 0x40, 0xc8,
0x05, 0x8f, 0x91, 0x1c, 0xee, 0xce, 0xbd, 0xf9, 0x2f, 0x01, 0xea, 0x32, 0x37, 0xf4, 0xfd, 0xca,
0x73, 0xa6, 0x6e, 0x30, 0xac, 0xd5, 0x8f, 0x95, 0xf8, 0x2b, 0x00, 0x00, 0xff, 0xff, 0x54, 0x1a,
0x6d, 0xda, 0x79, 0x02, 0x00, 0x00,
// 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,
}

Ver ficheiro

@ -31,4 +31,6 @@ message DecryptedGroupMessage {
required bytes signature = 4;
required bytes signed_group_id = 5;
required bytes previous_message_sig =6;
// Used to prevent analysis on text length, length is 1024 - len(text)
required bytes padding = 7;
}

Ver ficheiro

@ -79,6 +79,12 @@ func (sg *Guard) ValidateChallenge(message []byte, spamguard []byte) bool {
if len(spamguard) != 24 {
return false
}
// If the message is too large just throw it away.
if len(message) > 2048 {
return false
}
solve := make([]byte, len(sg.nonce)+len(message)+len(spamguard))
copy(solve[0:], sg.nonce[:])
copy(solve[len(sg.nonce):], message[:])