diff --git a/app/cli/main.go b/app/cli/main.go index 3292315..3608968 100644 --- a/app/cli/main.go +++ b/app/cli/main.go @@ -6,6 +6,7 @@ import ( "github.com/c-bata/go-prompt" "strings" + "time" ) var app app2.Application @@ -38,7 +39,7 @@ var usages = map[string]string{ "peers": "", "contacts": "", "groups": "", - "info": "", + "info": "", "send": "send [groupid] [message]", "timeline": "timeline [groupid]", "accept-invite": "accept-invite [groupid]", @@ -46,8 +47,8 @@ var usages = map[string]string{ "invite-to-group": "invite-to-group [peerid] [groupid]", "new-group": "new-group [server]", "help": "", - "trust": "trust [peerid]", - "block": "block [peerid]", + "trust": "trust [peerid]", + "block": "block [peerid]", } func completer(d prompt.Document) []prompt.Suggest { @@ -326,6 +327,36 @@ func main() { for _, command := range suggestions { fmt.Printf("%-18s%-56s%s\n", command.Text, command.Description, usages[command.Text]) } + case "sendlots": + if len(commands) == 2 { + group := app.Peer.Profile.GetGroupByGroupId(commands[1]) + if group == nil { + fmt.Printf("Error: group does not exist\n") + } else { + for i := 0; i < 100; i++ { + fmt.Printf("Sending message: %v\n", i) + err := app.Peer.SendMessageToGroup(commands[1], fmt.Sprintf("this is message %v", i)) + if err != nil { + fmt.Printf("could not send message %v because %v", i, err) + } + } + fmt.Printf("Waiting 5 seconds for message to process...\n") + time.Sleep(time.Second * 5) + timeline := group.GetTimeline() + for i := 0; i < 100; i++ { + found := false + for _, m := range timeline.Messages { + if m.Message == fmt.Sprintf("this is message %v", i) { + found = true + } + } + + if !found { + fmt.Printf("message %v was never received\n", i) + } + } + } + } } } app.Peer.Save(profilefile) diff --git a/model/group.go b/model/group.go index 3c00219..6c94d39 100644 --- a/model/group.go +++ b/model/group.go @@ -8,8 +8,8 @@ import ( "github.com/s-rah/go-ricochet/utils" "golang.org/x/crypto/nacl/secretbox" "io" - "time" "sync" + "time" ) //Group defines and encapsulates Cwtch's conception of group chat. Which are sessions @@ -22,7 +22,7 @@ type Group struct { Timeline Timeline Accepted bool Owner string - lock sync.Mutex + lock sync.Mutex } // NewGroup initializes a new group associated with a given CwtchServer @@ -70,7 +70,7 @@ func (g *Group) AddMessage(message *protocol.DecryptedGroupMessage, verified boo timelineMessage := &Message{ Message: message.GetText(), Timestamp: time.Unix(int64(message.GetTimestamp()), 0), - Received: time.Now(), + Received: time.Now(), Signature: message.GetSignature(), Verified: verified, PeerID: message.GetOnion(), diff --git a/model/message.go b/model/message.go index b3580c7..1dfc634 100644 --- a/model/message.go +++ b/model/message.go @@ -14,7 +14,7 @@ type Timeline struct { // Message is a local representation of a given message sent over a group chat channel. type Message struct { Timestamp time.Time - Received time.Time + Received time.Time PeerID string Message string Signature []byte diff --git a/model/message_test.go b/model/message_test.go index 0ae1148..2710c24 100644 --- a/model/message_test.go +++ b/model/message_test.go @@ -13,8 +13,8 @@ func TestTranscriptConsistency(t *testing.T) { // Setup the Group sarah := GenerateNewProfile("Sarah") alice := GenerateNewProfile("Alice") - sarah.AddContact(alice.Onion, alice.PublicProfile) - alice.AddContact(sarah.Onion, sarah.PublicProfile) + sarah.AddContact(alice.Onion, &alice.PublicProfile) + alice.AddContact(sarah.Onion, &sarah.PublicProfile) gid, invite := alice.StartGroup("aaa.onion") gci := &protocol.CwtchPeerPacket{} @@ -23,21 +23,23 @@ func TestTranscriptConsistency(t *testing.T) { group := alice.GetGroupByGroupId(gid) - c1 := sarah.EncryptMessageToGroup("Hello World 1", group.GroupID) + t.Logf("group: %v, sarah %v", group, sarah) + + c1, _ := sarah.EncryptMessageToGroup("Hello World 1", group.GroupID) alice.AttemptDecryption(c1) - c2 := alice.EncryptMessageToGroup("Hello World 2", group.GroupID) + c2, _ := alice.EncryptMessageToGroup("Hello World 2", group.GroupID) alice.AttemptDecryption(c2) - c3 := alice.EncryptMessageToGroup("Hello World 3", group.GroupID) + c3, _ := alice.EncryptMessageToGroup("Hello World 3", group.GroupID) alice.AttemptDecryption(c3) time.Sleep(time.Second * 1) - c4 := alice.EncryptMessageToGroup("Hello World 4", group.GroupID) + c4, _ := alice.EncryptMessageToGroup("Hello World 4", group.GroupID) alice.AttemptDecryption(c4) - c5 := alice.EncryptMessageToGroup("Hello World 5", group.GroupID) + c5, _ := alice.EncryptMessageToGroup("Hello World 5", group.GroupID) _, m1 := sarah.AttemptDecryption(c1) _, m2 := sarah.AttemptDecryption(c2) diff --git a/model/profile.go b/model/profile.go index 0fe6c8c..15e9680 100644 --- a/model/profile.go +++ b/model/profile.go @@ -5,12 +5,12 @@ import ( "crypto/rsa" "encoding/asn1" "encoding/json" + "errors" "git.mascherari.press/cwtch/protocol" "github.com/golang/protobuf/proto" "github.com/s-rah/go-ricochet/utils" "golang.org/x/crypto/ed25519" "io/ioutil" - // "log" "strconv" "time" ) @@ -50,6 +50,7 @@ func GenerateNewProfile(name string) *Profile { p.Onion = utils.GetTorHostname(publicKeyBytes) p.Contacts = make(map[string]*PublicProfile) + p.Contacts[p.Onion] = &p.PublicProfile p.Groups = make(map[string]*Group) return p } @@ -106,10 +107,10 @@ func (p *Profile) SignMessage(message string) []byte { func (p *Profile) StartGroup(server string) (groupID string, invite []byte) { group := NewGroup(server) groupID = group.GroupID - signedGroupId := p.SignMessage(groupID) + signedGroupId := p.SignMessage(groupID + server) group.SignGroup(signedGroupId) invite = group.Invite() - p.AddGroup(group) + p.Groups[group.GroupID] = group return } @@ -133,8 +134,13 @@ func (p *Profile) ProcessInvite(gci *protocol.GroupChatInvite, peerHostname stri func (p *Profile) AddGroup(group *Group) { existingGroup, exists := p.Groups[group.GroupID] if !exists { - // owned := ed25519.Verify(p.Contacts[group.Owner].Ed25519PublicKey,[]byte(group.GroupID),group.SignedGroupID) - p.Groups[group.GroupID] = group + owner, ok := p.Contacts[group.Owner] + if ok { + valid := ed25519.Verify(owner.Ed25519PublicKey, []byte(group.GroupID+group.GroupServer), group.SignedGroupID) + if valid { + p.Groups[group.GroupID] = group + } + } } else if exists && existingGroup.Owner == group.Owner { p.Groups[group.GroupID] = group } @@ -161,26 +167,29 @@ func (p *Profile) AttemptDecryption(ciphertext []byte) (bool, *Message) { // 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) (ciphertext []byte) { +func (p *Profile) EncryptMessageToGroup(message string, groupID string) ([]byte, error) { group := p.Groups[groupID] - 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 - } else { - prevSig = []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + 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 + } else { + prevSig = []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + } + dm := &protocol.DecryptedGroupMessage{ + Onion: proto.String(p.Onion), + Text: proto.String(message), + SignedGroupId: group.SignedGroupID[:], + Timestamp: proto.Int32(int32(timestamp)), + Signature: signature, + PreviousMessageSig: prevSig, + } + ciphertext := group.EncryptMessage(dm) + return ciphertext, nil } - dm := &protocol.DecryptedGroupMessage{ - Onion: proto.String(p.Onion), - Text: proto.String(message), - SignedGroupId: group.SignedGroupID[:], - Timestamp: proto.Int32(int32(timestamp)), - Signature: signature, - PreviousMessageSig: prevSig, - } - ciphertext = group.EncryptMessage(dm) - return + return nil, errors.New("group does not exist") } // Save makes a opy of the profile in the given file diff --git a/model/profile_test b/model/profile_test index 6e5fe7f..0e8891d 100644 --- a/model/profile_test +++ b/model/profile_test @@ -1 +1 @@ -{"Name":"Sarah","Ed25519PublicKey":"Q6dF7nCKD6BfqgGLBk0FCCYBdWBLv7Ts8uqw2zOf02A=","Trusted":false,"Blocked":false,"Onion":"lrkqzljkc5cgzmpz","Contacts":{},"Ed25519PrivateKey":"Fy9HObWaw9EH8N3jXNQtD9UgL0Yd7feY5L+oR7uNnXdDp0XucIoPoF+qAYsGTQUIJgF1YEu/tOzy6rDbM5/TYA==","OnionPrivateKey":{"N":107498703462635665473764971520727195625141645315352207633904323688914544197828221612438071393137838030896432787991102883141045406182879952109587171872209559960156106354960716467157362368090179490551994133414470776568822115434428749245942446198318143880845039325380939873177604289430737365718905329111360343777,"E":65537,"D":66650934838346851867814606295271813891877956204037743640936696656474260172643727314338596411016111670467760958042487061561457482564584036102063950773690623873787097606677998053221231028080886156972583586531026258726212233434099244761970868656273357504083063877021130260355845678915219099393211715317011636225,"Primes":[10332071347522235902804485468145791866057055098286157383486988408098332066944447770996594012391982280205811088346484428102348931474084528799982497053772929,10404370996568393072795074320321443437318186756296376448713064693902356814671757730321014302625680493962881120033122151552975123796575551159729969846473313],"Precomputed":{"Dp":1495964493593519637482822872686198926057271401309753992582938386017746814520589360193275258000633533070981909720002300048265697403872439900865677625513089,"Dq":9954139888243813632868821504775543966969614535400447071284280168032892482669848809815187112454533967864971071413045943887011813741384006488948667765441249,"Qinv":9010750810541828585160172405562139672487565596169846634421581721158830598191896975588357263133581085970784950793654150830626201363086339113136601110542205,"CRTValues":[]}},"Groups":{}} \ No newline at end of file +{"Name":"Sarah","Ed25519PublicKey":"FH0bgqmhOuDPu/uXhm5ZT2BuA323JzPBd0Kf3B1YxZA=","Trusted":false,"Blocked":false,"Onion":"y6rv5psc5wruugyx","Contacts":{"y6rv5psc5wruugyx":{"Name":"Sarah","Ed25519PublicKey":"FH0bgqmhOuDPu/uXhm5ZT2BuA323JzPBd0Kf3B1YxZA=","Trusted":false,"Blocked":false,"Onion":"y6rv5psc5wruugyx"}},"Ed25519PrivateKey":"JMnZpsSi1hY6ziZqEaO2kk0ID9+XKm3nOiVoMJazbNIUfRuCqaE64M+7+5eGbllPYG4DfbcnM8F3Qp/cHVjFkA==","OnionPrivateKey":{"N":134057991576218556828017459230656270170181976065106440664426101908559409913157558701412664226096530310039819285641603796528668425856812146294423697678905284504161436672881228795123245277153307076066056625279711139065658846052615035565877781519956303024388960852968254724005382280308994893755778995867984769237,"E":65537,"D":119111293612512116271655044493966989822690945058076323906946181761988105028352909702660473288151745730711181119106925691927679973719306212959462470296819405321699089033715265196316348982251250275981258387949939751153694376595038421083397851309304042337114325061140172676796510776973712466297887452957497017473,"Primes":[11012092321802935235393019477644583097314933484252577291348472528127020714587871982369210353940819563472891086714033880185118457292396210254630513786328037,12173707562439882498035952564416877264727009547626505009495704590991075365448508893781170020376584913732483057163277808299913173595097515219539586115287601],"Precomputed":{"Dp":1484196888452100751243214383417529067528004142185376431854998822664235072889431515331297359603876576653738300028152971049562099779723449733420073062157797,"Dq":716821604337328632069224116851316498536422629114708986246607626480225824118677934923806935145539789463870059929400019259797746874337874959674737366966673,"Qinv":7022175560771039220943597791205895336996303269499099474897105311693825279448116080639519964317539885032301904250731793359527590562893328519648160444244943,"CRTValues":[]}},"Groups":{}} \ No newline at end of file diff --git a/model/profile_test.go b/model/profile_test.go index 1231e8b..b1cc3a1 100644 --- a/model/profile_test.go +++ b/model/profile_test.go @@ -40,8 +40,8 @@ func TestProfileIdentity(t *testing.T) { func TestProfileGroup(t *testing.T) { sarah := GenerateNewProfile("Sarah") alice := GenerateNewProfile("Alice") - sarah.AddContact(alice.Onion, alice.PublicProfile) - alice.AddContact(sarah.Onion, sarah.PublicProfile) + sarah.AddContact(alice.Onion, &alice.PublicProfile) + alice.AddContact(sarah.Onion, &sarah.PublicProfile) gid, invite := alice.StartGroup("aaa.onion") gci := &protocol.CwtchPeerPacket{} @@ -49,7 +49,7 @@ func TestProfileGroup(t *testing.T) { sarah.ProcessInvite(gci.GetGroupChatInvite(), alice.Onion) group := alice.GetGroupByGroupId(gid) - c := sarah.EncryptMessageToGroup("Hello World", group.GroupID) + c, _ := sarah.EncryptMessageToGroup("Hello World", group.GroupID) alice.AttemptDecryption(c) gid2, invite2 := alice.StartGroup("bbb.onion") @@ -57,20 +57,25 @@ func TestProfileGroup(t *testing.T) { proto.Unmarshal(invite2, gci2) sarah.ProcessInvite(gci2.GetGroupChatInvite(), alice.Onion) group2 := alice.GetGroupByGroupId(gid2) - c2 := sarah.EncryptMessageToGroup("Hello World", group2.GroupID) + c2, _ := sarah.EncryptMessageToGroup("Hello World", group2.GroupID) alice.AttemptDecryption(c2) bob := GenerateNewProfile("bob") + bob.AddContact(alice.Onion, &alice.PublicProfile) bob.ProcessInvite(gci2.GetGroupChatInvite(), alice.Onion) - c3 := bob.EncryptMessageToGroup("Bobs Message", group2.GroupID) - ok, message := alice.AttemptDecryption(c3) - 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) - } + c3, err := bob.EncryptMessageToGroup("Bobs Message", group2.GroupID) + if err == nil { + ok, message := alice.AttemptDecryption(c3) + 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) - if ok { - t.Errorf("Eves hould not be able to decrypt messages!") + eve := GenerateNewProfile("eve") + ok, _ = eve.AttemptDecryption(c3) + if ok { + t.Errorf("Eves hould not be able to decrypt messages!") + } + } else { + t.Errorf("Bob failed to encrypt a message to the group") } } diff --git a/model/threat_model_test.go b/model/threat_model_test.go deleted file mode 100644 index 4940981..0000000 --- a/model/threat_model_test.go +++ /dev/null @@ -1,18 +0,0 @@ -package model - -import ( - "testing" -) - -// Nothing in this file constitutes a cryptographic proof, but acts to prevent regressions in expected protocol -// behaviour. - -// When a new member joins the group, they should be unable to decrypt any past messages -func TestGroupForwardSecrecy(t *testing.T) { - t.Fatalf("Failed") -} - -// When a member leaves the group, they should be unable to decrypt any future messages. -func TestGroupBackwardSecrecy(t *testing.T) { - t.Fatalf("Failed") -} diff --git a/peer/connections/peerserverconnection.go b/peer/connections/peerserverconnection.go index 5e7949f..1df5f58 100644 --- a/peer/connections/peerserverconnection.go +++ b/peer/connections/peerserverconnection.go @@ -74,40 +74,39 @@ func (psc *PeerServerConnection) Break() error { return psc.connection.Break() } -func (psc *PeerServerConnection) SendGroupMessage(gm *protocol.GroupMessage) { - for psc.state != AUTHENTICATED { - time.Sleep(time.Second * 2) +func (psc *PeerServerConnection) SendGroupMessage(gm *protocol.GroupMessage) error { + if psc.state != AUTHENTICATED { + return errors.New("peer is not yet connected & authenticated to server cannot send message") } - log.Printf("Opening a Channel to Send") - psc.connection.Do(func() error { + + err := psc.connection.Do(func() error { psc.connection.RequestOpenChannel("im.cwtch.server.send", &send.CwtchPeerSendChannel{}) return nil }) - log.Printf("Waiting...") - // TODO We have to wait to receive the channel result before we can continue - // We should have a better mechanism for this kindof interaction - log.Printf("CWTCH PEER Sending...") -send: - time.Sleep(time.Second * 2) - err := psc.connection.Do(func() error { - channel := psc.connection.Channel("im.cwtch.server.send", channels.Outbound) - if channel == nil { - return errors.New("No Channel") - } - sendchannel, ok := channel.Handler.(*send.CwtchPeerSendChannel) - if ok { - sendchannel.SendGroupMessage(gm) + + errCount := 0 + for errCount < 5 { + time.Sleep(time.Second * 1) + err = psc.connection.Do(func() error { + channel := psc.connection.Channel("im.cwtch.server.send", channels.Outbound) + if channel == nil { + return errors.New("no channel found") + } + sendchannel, ok := channel.Handler.(*send.CwtchPeerSendChannel) + if ok { + return sendchannel.SendGroupMessage(gm) + } + return errors.New("channel is not a peer send channel (this should definitely not happen)") + }) + + if err != nil { + errCount++ } else { - return errors.New("Failed") + return nil } - return nil - }) - for err != nil { - log.Printf("CHANNEL ERROR %v", err) - goto send } - log.Printf("Done") + return err } func (psc *PeerServerConnection) HandleGroupMessage(gm *protocol.GroupMessage) { diff --git a/peer/cwtch_peer.go b/peer/cwtch_peer.go index 3187106..d73f437 100644 --- a/peer/cwtch_peer.go +++ b/peer/cwtch_peer.go @@ -71,7 +71,6 @@ func (cp *CwtchPeer) Save(profilefile string) error { return err } - func LoadCwtchPeer(profilefile string) (*CwtchPeer, error) { bytes, _ := ioutil.ReadFile(profilefile) cp := new(CwtchPeer) @@ -123,14 +122,17 @@ func (cp *CwtchPeer) SendMessageToGroup(groupid string, message string) error { } psc := cp.connectionsManager.GetPeerServerConnectionForOnion(group.GroupServer) if psc == nil { - return errors.New("could not find server to send message to") + return errors.New("could not find server connection to send message to") + } + ct, err := cp.Profile.EncryptMessageToGroup(message, groupid) + if err != nil { + return err } - ct := cp.Profile.EncryptMessageToGroup(message, groupid) gm := &protocol.GroupMessage{ Ciphertext: ct, } - psc.SendGroupMessage(gm) - return nil + err = psc.SendGroupMessage(gm) + return err } func (cp *CwtchPeer) GetPeers() map[string]connections.ConnectionState { @@ -142,7 +144,7 @@ func (cp *CwtchPeer) GetServers() map[string]connections.ConnectionState { } func (cp *CwtchPeer) TrustPeer(peer string) error { - _,ok := cp.Profile.Contacts[peer] + _, ok := cp.Profile.Contacts[peer] if !ok { return errors.New("peer does not exist") } @@ -152,7 +154,7 @@ func (cp *CwtchPeer) TrustPeer(peer string) error { } func (cp *CwtchPeer) BlockPeer(peer string) error { - _,ok := cp.Profile.Contacts[peer] + _, ok := cp.Profile.Contacts[peer] if !ok { return errors.New("peer does not exist") } diff --git a/peer/send/peer_send_channel.go b/peer/send/peer_send_channel.go index c1756cf..4a7e1dc 100644 --- a/peer/send/peer_send_channel.go +++ b/peer/send/peer_send_channel.go @@ -73,15 +73,20 @@ func (cplc *CwtchPeerSendChannel) OpenOutboundResult(err error, crm *Protocol_Da } // 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[:] - csp := &protocol.CwtchServerPacket{ - GroupMessage: gm, +func (cplc *CwtchPeerSendChannel) SendGroupMessage(gm *protocol.GroupMessage) error { + if cplc.channel.Pending == false { + sgsolve := cplc.spamGuard.SolveChallenge(cplc.challenge, gm.GetCiphertext()) + gm.Spamguard = sgsolve[:] + csp := &protocol.CwtchServerPacket{ + GroupMessage: gm, + } + packet, _ := proto.Marshal(csp) + cplc.channel.SendMessage(packet) + cplc.channel.CloseChannel() + } else { + return errors.New("channel isn't set up yet") } - packet, _ := proto.Marshal(csp) - cplc.channel.SendMessage(packet) - cplc.channel.CloseChannel() + return nil } // Packet should never be diff --git a/peer/test_profile b/peer/test_profile index e613e7c..38e2936 100644 --- a/peer/test_profile +++ b/peer/test_profile @@ -1 +1 @@ -{"Profile":{"Name":"alice","Ed25519PublicKey":"zjwuZF+0Op1KvzzOhqeHSbvXu0U5djPgTwKpAXU//7I=","Trusted":false,"Blocked":false,"Onion":"cgb6lexebisn6vpt","Contacts":{},"Ed25519PrivateKey":"2lHp48zadAzBVtVEjviPijgcVx4Djle0DJ4A5thMgSnOPC5kX7Q6nUq/PM6Gp4dJu9e7RTl2M+BPAqkBdT//sg==","OnionPrivateKey":{"N":147157004733998659199661812977704646877524902240221974034556056889821412558230773103992139173929507205012402066934484772524414251527816699766158278653365683529647303492589077999418406692030398982986134250109986822607454250083546220790801592188854654036322143842183727153411958706262869490046244589596814484207,"E":65537,"D":69165161921072992345197107361524577532819621949517943546186584988284007065187336984028409340899806375574057721100797022263294508290146601200802195055611675878933653952917037806259598451163914910457010547243954518097830998995842836616848924363378592869926704087730180750445525914371624821666069356678694847337,"Primes":[11763039476614882926577453250579526149631348162928663166529586678426982975960723170685888779927126269335313361708713193749880911707050422735813878237869163,12510117391559317555937472239718194296052069062441314136877360692383786524485845690577241127778855759836876789006855569037256017877501872991377132347214989],"Precomputed":{"Dp":1278485896393301662969180760545614916212583623976392995333784669887779418309782735627135599423545789652798222003618781437667298382430080124924886013829471,"Dq":8164208322581015485411991511554498528192425558091078408139596209976876415647033281749066985597474111543452099818777372899635929087702444540354302920340953,"Qinv":2274603529611181793096917499650639342446510507100204826932356686902897257746923946968375987728128727917910029163224849482139316568187669695882958003364055,"CRTValues":[]}},"Groups":{}}} \ No newline at end of file +{"Profile":{"Name":"alice","Ed25519PublicKey":"W6naGYWbCXL80XXDgpKE7V+siJo6o9bbGyTvUnUKILE=","Trusted":false,"Blocked":false,"Onion":"ycnqegkvvkz5gsvs","Contacts":{"ycnqegkvvkz5gsvs":{"Name":"alice","Ed25519PublicKey":"W6naGYWbCXL80XXDgpKE7V+siJo6o9bbGyTvUnUKILE=","Trusted":false,"Blocked":false,"Onion":"ycnqegkvvkz5gsvs"}},"Ed25519PrivateKey":"KvmZ7aWoB5RVmkloWri+316/wfA/CyGn0pcYS34WN7xbqdoZhZsJcvzRdcOCkoTtX6yImjqj1tsbJO9SdQogsQ==","OnionPrivateKey":{"N":138578445730948217399235853380745007937830927545752074120752000142489179414948896312808960302192046016583916437398543221534462954288785032720766262144773721364963084161409242148120269561063898622509706451288561156808651123385134272354840396173775759747294322189173896763873375202344132814058552323894612271379,"E":65537,"D":66260191577658320344575654997009713119915009011301814160670837488213389782059578785391177198063535925899470611750930777881256864604625902701343234975183920374575910046121511808611558969522048550963186520107773724296757371157728176877458332331908465537431591104876047516596838295433500859876997952335609406401,"Primes":[13275044288223673053268894137348396823019805659935753695111177485542609507887379320301691989583038422110723796993226398199751492392227091252491529012654327,10439019465560768307866940717986678867283694780656194070584524560148251882718648675994212565947390303977286149767780033032504469772695284927646948863796677],"Precomputed":{"Dp":5339834254331941789069908406682918611600288643166857483719438803635721376427469881773550883155897567537160699091130724771378745478796566513544740952921149,"Dq":6887615251084321564924765912178799470531367716104711656104878564862147484026383377308478349087250013492864037140982596218296928108413824489317205789392741,"Qinv":2094027238282876917718460475743388991144681081516298156361631729627217848136364125434066438976020876853031955793909233935538173930073006469995174800032241,"CRTValues":[]}},"Groups":{}}} \ No newline at end of file diff --git a/protocol/spam/spamguard.go b/protocol/spam/spamguard.go index f5c0eaf..2fcc3e9 100644 --- a/protocol/spam/spamguard.go +++ b/protocol/spam/spamguard.go @@ -8,6 +8,7 @@ import ( "github.com/s-rah/go-ricochet/utils" "github.com/s-rah/go-ricochet/wire/control" "io" + //"fmt" ) // Guard implements a spam protection mechanism for Cwtch Servers. @@ -69,6 +70,7 @@ func (sg *Guard) SolveChallenge(challenge []byte, message []byte) []byte { } } } + //fmt.Printf("[SOLVED] %x\n",sha256.Sum256(solve)) return spamguard[:] } diff --git a/server/app/main.go b/server/app/main.go index e02464a..f84d50a 100644 --- a/server/app/main.go +++ b/server/app/main.go @@ -2,20 +2,20 @@ package main import ( cwtchserver "git.mascherari.press/cwtch/server" - "log" - "os" "github.com/s-rah/go-ricochet/utils" "io/ioutil" + "log" + "os" ) const privateKeyFile = "./private_key" func checkAndGenPrivateKey(privateKeyFile string) { - if _, err := os.Stat(privateKeyFile); os.IsNotExist(err) { + if _, err := os.Stat(privateKeyFile); os.IsNotExist(err) { log.Printf("no private key found!") log.Printf("generating new private key...") pk, pk_err := utils.GeneratePrivateKey() - if pk_err != nil { + if pk_err != nil { log.Fatalf("error generating new private key: %v\n", err) } err := ioutil.WriteFile(privateKeyFile, []byte(utils.PrivateKeyToString(pk)), 0400) diff --git a/server/send/server_send_channel.go b/server/send/server_send_channel.go index a3c676f..01459bc 100644 --- a/server/send/server_send_channel.go +++ b/server/send/server_send_channel.go @@ -7,6 +7,7 @@ import ( "github.com/golang/protobuf/proto" "github.com/s-rah/go-ricochet/channels" "github.com/s-rah/go-ricochet/wire/control" + "log" ) // CwtchChannel implements the ChannelHandler interface for a channel of @@ -92,8 +93,12 @@ func (cc *CwtchServerSendChannel) Packet(data []byte) { ok := cc.spamguard.ValidateChallenge(gm.GetCiphertext(), gm.GetSpamguard()) if ok { cc.Handler.HandleGroupMessage(gm) + } else { + log.Printf("[ERROR] Failed to validate spamguard %v\n", gm) } } + } else { + log.Printf("[ERROR] Failed to decode packet on SEND channel %v\n", err) } cc.channel.CloseChannel() } diff --git a/server/server.go b/server/server.go index 233ffab..212eceb 100644 --- a/server/server.go +++ b/server/server.go @@ -9,7 +9,6 @@ import ( "github.com/s-rah/go-ricochet/channels" "github.com/s-rah/go-ricochet/utils" "log" - ) type Server struct { diff --git a/storage/message_store.go b/storage/message_store.go index e01740a..a701861 100644 --- a/storage/message_store.go +++ b/storage/message_store.go @@ -5,6 +5,7 @@ import ( "encoding/json" "fmt" "git.mascherari.press/cwtch/protocol" + "log" "os" "sync" ) @@ -61,7 +62,10 @@ func (ms *MessageStore) FetchMessages() (messages []*protocol.GroupMessage) { func (ms *MessageStore) AddMessage(gm protocol.GroupMessage) { ms.lock.Lock() ms.messages = append(ms.messages, &gm) - s, _ := json.Marshal(gm) + s, err := json.Marshal(gm) + if err != nil { + log.Printf("[ERROR] Failed to unmarshal group message %v\n", err) + } fmt.Fprintf(ms.file, "%s\n", s) ms.lock.Unlock() }