diff --git a/client/fetch/peer_fetch_channel_test.go b/client/fetch/peer_fetch_channel_test.go index f1ab5fa..ebf1e13 100644 --- a/client/fetch/peer_fetch_channel_test.go +++ b/client/fetch/peer_fetch_channel_test.go @@ -50,7 +50,7 @@ func TestPeerFetchChannelOpenInbound(t *testing.T) { func TestPeerFetchChannel(t *testing.T) { pfc := new(CwtchPeerFetchChannel) - th := new(TestHandler) + th := new(TestHandler) pfc.Handler = th channel := new(channels.Channel) channel.ID = 3 @@ -69,11 +69,9 @@ func TestPeerFetchChannel(t *testing.T) { t.Errorf("once opened channel should no longer be pending") } - - csp := &protocol.CwtchServerPacket{ GroupMessages: []*protocol.GroupMessage{ - {Ciphertext: []byte("hello"),Spamguard: []byte{},}, + {Ciphertext: []byte("hello"), Spamguard: []byte{}}, }, } packet, _ := proto.Marshal(csp) @@ -83,7 +81,7 @@ func TestPeerFetchChannel(t *testing.T) { if th.Received != true { t.Errorf("group message should not have been received") } - + pfc.Closed(nil) } diff --git a/client/listen/peer_listen_channel_test.go b/client/listen/peer_listen_channel_test.go index 8cd1497..d7c4a02 100644 --- a/client/listen/peer_listen_channel_test.go +++ b/client/listen/peer_listen_channel_test.go @@ -50,7 +50,7 @@ func TestPeerListenChannelOpenInbound(t *testing.T) { func TestPeerListenChannel(t *testing.T) { pfc := new(CwtchPeerListenChannel) - th := new(TestHandler) + th := new(TestHandler) pfc.Handler = th channel := new(channels.Channel) channel.ID = 3 @@ -69,10 +69,8 @@ func TestPeerListenChannel(t *testing.T) { t.Errorf("once opened channel should no longer be pending") } - - csp := &protocol.CwtchServerPacket{ - GroupMessage: &protocol.GroupMessage{Ciphertext: []byte("hello"),Spamguard: []byte{},}, + GroupMessage: &protocol.GroupMessage{Ciphertext: []byte("hello"), Spamguard: []byte{}}, } packet, _ := proto.Marshal(csp) @@ -81,7 +79,7 @@ func TestPeerListenChannel(t *testing.T) { if th.Received != true { t.Errorf("group message should not have been received") } - + pfc.Closed(nil) } diff --git a/client/send/peer_send_channel.go b/client/send/peer_send_channel.go index a526843..2cce769 100644 --- a/client/send/peer_send_channel.go +++ b/client/send/peer_send_channel.go @@ -12,7 +12,7 @@ import ( // CwtchPeerSendChannel is the peer implementation of im.cwtch.server.send type CwtchPeerSendChannel struct { - channel *channels.Channel + channel *channels.Channel spamGuard spam.SpamGuard challenge []byte } @@ -52,9 +52,9 @@ func (cc *CwtchPeerSendChannel) OpenInbound(channel *channels.Channel, raw *Prot return nil, errors.New("client does not receive inbound listen channels") } -// OpenOutbound is used to set up a new send channel and initialize spamguard +// OpenOutbound is used to set up a new send channel and initialize spamguard func (cplc *CwtchPeerSendChannel) OpenOutbound(channel *channels.Channel) ([]byte, error) { - cplc.spamGuard.Difficulty = 2 + cplc.spamGuard.Difficulty = 2 cplc.channel = channel messageBuilder := new(utils.MessageBuilder) return messageBuilder.OpenChannel(channel.ID, cplc.Type()), nil @@ -66,16 +66,15 @@ func (cplc *CwtchPeerSendChannel) OpenOutboundResult(err error, crm *Protocol_Da if crm.GetOpened() { cplc.channel.Pending = false ce, _ := proto.GetExtension(crm, protocol.E_ServerNonce) - cplc.challenge = ce.([]byte)[:] + cplc.challenge = ce.([]byte)[:] } } } - // SendGroupMessage performs the spamguard proof of work and sends a message. func (cplc *CwtchPeerSendChannel) SendGroupMessage(gm *protocol.GroupMessage) { - sgsolve := cplc.spamGuard.SolveChallenge(cplc.challenge, gm.GetCiphertext()) - gm.Spamguard = sgsolve + sgsolve := cplc.spamGuard.SolveChallenge(cplc.challenge, gm.GetCiphertext()) + gm.Spamguard = sgsolve csp := &protocol.CwtchServerPacket{ GroupMessage: gm, } @@ -83,7 +82,7 @@ func (cplc *CwtchPeerSendChannel) SendGroupMessage(gm *protocol.GroupMessage) { cplc.channel.SendMessage(packet) } -// Packet should never be called +// Packet should never be func (cc *CwtchPeerSendChannel) Packet(data []byte) { // If we receive a packet on this channel, close the connection cc.channel.CloseChannel() diff --git a/client/send/peer_send_channel_test.go b/client/send/peer_send_channel_test.go index 9018594..e09535c 100644 --- a/client/send/peer_send_channel_test.go +++ b/client/send/peer_send_channel_test.go @@ -2,10 +2,10 @@ package listen import ( "git.mascherari.press/cwtch/protocol" + "git.mascherari.press/cwtch/protocol/spam" "github.com/golang/protobuf/proto" "github.com/s-rah/go-ricochet/channels" "github.com/s-rah/go-ricochet/wire/control" - "git.mascherari.press/cwtch/protocol/spam" "testing" ) @@ -50,20 +50,19 @@ func TestPeerSendChannelOpenInbound(t *testing.T) { } } - func TestPeerSendChannelClosesOnPacket(t *testing.T) { pfc := new(CwtchPeerSendChannel) channel := new(channels.Channel) closed := false - channel.CloseChannel = func () { - closed = true + channel.CloseChannel = func() { + closed = true } - pfc.OpenOutbound(channel) - pfc.Packet([]byte{}) - if !closed { - t.Errorf("send channel should close if server attempts to send packets") - } + pfc.OpenOutbound(channel) + pfc.Packet([]byte{}) + if !closed { + t.Errorf("send channel should close if server attempts to send packets") + } } func TestPeerSendChannel(t *testing.T) { @@ -72,26 +71,24 @@ func TestPeerSendChannel(t *testing.T) { channel := new(channels.Channel) channel.ID = 3 success := false - + var sg spam.SpamGuard sg.Difficulty = 2 - + channel.SendMessage = func(message []byte) { - packet := new(protocol.CwtchServerPacket) - proto.Unmarshal(message[:], packet) - if packet.GetGroupMessage() != nil { - success = sg.ValidateChallenge(packet.GetGroupMessage().GetCiphertext(), packet.GetGroupMessage().GetSpamguard()) - } + packet := new(protocol.CwtchServerPacket) + proto.Unmarshal(message[:], packet) + if packet.GetGroupMessage() != nil { + success = sg.ValidateChallenge(packet.GetGroupMessage().GetCiphertext(), packet.GetGroupMessage().GetSpamguard()) + } } - result, err := pfc.OpenOutbound(channel) + result, err := pfc.OpenOutbound(channel) if err != nil { t.Errorf("expected result but also got non-nil error: result:%v, err: %v", result, err) } - - challenge := sg.GenerateChallenge(3) - control := new(Protocol_Data_Control.Packet) + control := new(Protocol_Data_Control.Packet) proto.Unmarshal(challenge[:], control) pfc.OpenOutboundResult(nil, control.GetChannelResult()) @@ -99,13 +96,12 @@ func TestPeerSendChannel(t *testing.T) { t.Errorf("once opened channel should no longer be pending") } + gm := &protocol.GroupMessage{Ciphertext: []byte("hello")} + pfc.SendGroupMessage(gm) + if !success { + t.Errorf("send channel should have successfully sent a valid group message") + } - gm := &protocol.GroupMessage{Ciphertext: []byte("hello"),} - pfc.SendGroupMessage(gm) - if !success { - t.Errorf("send channel should have successfully sent a valid group message") - } - pfc.Closed(nil) } diff --git a/protocol/group_message.pb.go b/protocol/group_message.pb.go index 1da1699..e9fb144 100644 --- a/protocol/group_message.pb.go +++ b/protocol/group_message.pb.go @@ -20,9 +20,9 @@ type CwtchServerPacket struct { XXX_unrecognized []byte `json:"-"` } -func (m *CwtchServerPacket) Reset() { *m = CwtchServerPacket{} } -func (m *CwtchServerPacket) String() string { return proto.CompactTextString(m) } -func (*CwtchServerPacket) ProtoMessage() {} +func (m *CwtchServerPacket) Reset() { *m = CwtchServerPacket{} } +func (m *CwtchServerPacket) String() string { return proto.CompactTextString(m) } +func (*CwtchServerPacket) ProtoMessage() {} func (m *CwtchServerPacket) GetGroupMessage() *GroupMessage { if m != nil { @@ -49,9 +49,9 @@ type FetchMessage struct { XXX_unrecognized []byte `json:"-"` } -func (m *FetchMessage) Reset() { *m = FetchMessage{} } -func (m *FetchMessage) String() string { return proto.CompactTextString(m) } -func (*FetchMessage) ProtoMessage() {} +func (m *FetchMessage) Reset() { *m = FetchMessage{} } +func (m *FetchMessage) String() string { return proto.CompactTextString(m) } +func (*FetchMessage) ProtoMessage() {} type GroupMessage struct { Ciphertext []byte `protobuf:"bytes,1,req,name=ciphertext" json:"ciphertext,omitempty"` @@ -59,10 +59,9 @@ type GroupMessage struct { XXX_unrecognized []byte `json:"-"` } -func (m *GroupMessage) Reset() { *m = GroupMessage{} } -func (m *GroupMessage) String() string { return proto.CompactTextString(m) } -func (*GroupMessage) ProtoMessage() {} - +func (m *GroupMessage) Reset() { *m = GroupMessage{} } +func (m *GroupMessage) String() string { return proto.CompactTextString(m) } +func (*GroupMessage) ProtoMessage() {} func (m *GroupMessage) GetCiphertext() []byte { if m != nil { @@ -88,9 +87,9 @@ type DecryptedGroupMessage struct { XXX_unrecognized []byte `json:"-"` } -func (m *DecryptedGroupMessage) Reset() { *m = DecryptedGroupMessage{} } -func (m *DecryptedGroupMessage) String() string { return proto.CompactTextString(m) } -func (*DecryptedGroupMessage) ProtoMessage() {} +func (m *DecryptedGroupMessage) Reset() { *m = DecryptedGroupMessage{} } +func (m *DecryptedGroupMessage) String() string { return proto.CompactTextString(m) } +func (*DecryptedGroupMessage) ProtoMessage() {} func (m *DecryptedGroupMessage) GetOnion() string { if m != nil && m.Onion != nil { diff --git a/protocol/spam/spamguard.go b/protocol/spam/spamguard.go index d7399c1..534da09 100644 --- a/protocol/spam/spamguard.go +++ b/protocol/spam/spamguard.go @@ -15,6 +15,8 @@ type SpamGuard struct { nonce [24]byte } + +//GenerateChallenge returns a channel result packet with a spamguard challenge nonce func (sg *SpamGuard) GenerateChallenge(channelID int32) []byte { cr := &Protocol_Data_Control.ChannelResult{ @@ -38,6 +40,9 @@ func (sg *SpamGuard) GenerateChallenge(channelID int32) []byte { return ret } +// SolveChallenge takes in a challenge and a message and returns a solution +// The solution is a 24 byte nonce which when hashed with the challenge and the message +// produces a sha256 hash with Difficulty leading 0s func (sg *SpamGuard) SolveChallenge(challenge []byte, message []byte) []byte { solved := false var spamguard [24]byte @@ -67,8 +72,11 @@ func (sg *SpamGuard) SolveChallenge(challenge []byte, message []byte) []byte { return spamguard[:] } +// ValidateChallenge returns true if the message and spamguard pass the challenge func (sg *SpamGuard) ValidateChallenge(message []byte, spamguard []byte) bool { - //log.Printf("%v %v\n", sg.nonce[:], spamguard[:]) + if len(spamguard) != 24 { + return false + } solve := make([]byte, len(sg.nonce)+len(message)+len(spamguard)) copy(solve[0:], sg.nonce[:]) copy(solve[len(sg.nonce):], message[:])