diff --git a/client/identity.go b/client/identity.go index 0259b0f..34f42cd 100644 --- a/client/identity.go +++ b/client/identity.go @@ -1,9 +1,11 @@ package client import ( + "crypto/rand" + "encoding/base64" "encoding/json" "errors" - "math/rand" + mrand "math/rand" "os" "path/filepath" "strings" @@ -20,7 +22,7 @@ const maxHiddenCount = 30 // Package-level random number generator with mutex for thread-safe access var ( rngMu sync.Mutex - rng = rand.New(rand.NewSource(time.Now().UnixNano())) + rng = mrand.New(mrand.NewSource(time.Now().UnixNano())) ) type Identity struct { @@ -96,6 +98,11 @@ func (id *Identity) InvitePeer(MyName string, ContactName string, MessageServerU } peer.Name = ContactName peer.InvitationId = uuid.New().String() // todo as param to identify then update url + symKeyBytes := make([]byte, 32) + if _, err = rand.Read(symKeyBytes); err != nil { + return nil, err + } + peer.MySymKey = base64.StdEncoding.EncodeToString(symKeyBytes) /* if id.MessageServers.Servers == nil { return nil, errors.New("no message servers defined in your identity") } @@ -161,6 +168,7 @@ func (id *Identity) AnswerInvitation(MyName string, ContactName string, MessageS peer.ContactEncryption = ReceivedContact.EncryptionPublicKey peer.ContactLookupKey = ReceivedContact.LookupPublicKey peer.ContactPublicKey = ReceivedContact.ContactPublicKey + peer.MySymKey = ReceivedContact.SymetricKey peer.InvitationId = ReceivedContact.InvitationId peer.InvitationMessage = ReceivedContact.InvitationMessage for srv := range ReceivedContact.PullServers { diff --git a/client/peer.go b/client/peer.go index 10536f7..c2d993e 100644 --- a/client/peer.go +++ b/client/peer.go @@ -73,6 +73,7 @@ func (p *Peer) GetMyContact() *meowlib.ContactCard { c.InvitationId = p.InvitationId c.InvitationMessage = p.InvitationMessage c.Name = p.MyName + c.SymetricKey = p.MySymKey return &c } @@ -199,6 +200,24 @@ func (p *Peer) DeserializeUserMessage(data []byte) (*meowlib.UserMessage, error) return &msg, nil } +// SymEncryptPayload applies the shared symmetric key over already-encrypted data. +// If MySymKey is empty, data is returned unchanged (peer has no symkey configured). +func (p *Peer) SymEncryptPayload(data []byte) ([]byte, error) { + if p.MySymKey == "" { + return data, nil + } + return meowlib.SymEncrypt(p.MySymKey, data) +} + +// SymDecryptPayload removes the outer symmetric encryption layer. +// If MySymKey is empty, data is returned unchanged. +func (p *Peer) SymDecryptPayload(data []byte) ([]byte, error) { + if p.MySymKey == "" { + return data, nil + } + return meowlib.SymDecrypt(p.MySymKey, data) +} + // AsymEncryptMessage prepares a message to send to a specific peer contact func (p *Peer) AsymEncryptMessage(Message []byte) (*meowlib.EncryptedMessage, error) { var enc *meowlib.EncryptedMessage @@ -259,19 +278,29 @@ func (p *Peer) ProcessOutboundUserMessage(usermessage *meowlib.UserMessage) (*me if err != nil { return nil, err } - // Encrypting it + // Asymmetric encryption + signature (inner layer) enc, err := p.AsymEncryptMessage(serializedMessage) if err != nil { return nil, err } + // Symmetric encryption (outer layer, if symkey is configured) + symEncrypted, err := p.SymEncryptPayload(enc.Data) + if err != nil { + return nil, err + } // Packing it - packedMsg := p.PackUserMessage(enc.Data, enc.Signature) + packedMsg := p.PackUserMessage(symEncrypted, enc.Signature) return packedMsg, nil } // ProcessInboundUserMessage is a helper function that decrypts and deserializes a user message func (p *Peer) ProcessInboundUserMessage(message []byte, signature []byte) (*meowlib.UserMessage, error) { - dec, err := p.AsymDecryptMessage(message, signature) + // Symmetric decryption (outer layer, if symkey is configured) + symDecrypted, err := p.SymDecryptPayload(message) + if err != nil { + return nil, err + } + dec, err := p.AsymDecryptMessage(symDecrypted, signature) if err != nil { return nil, err } diff --git a/client/peerstorage.go b/client/peerstorage.go index 28e159d..34f67ef 100644 --- a/client/peerstorage.go +++ b/client/peerstorage.go @@ -238,6 +238,9 @@ func (ps *PeerStorage) FinalizeInvitation(ReceivedContact *meowlib.ContactCard) ps.cache[i].ContactEncryption = ReceivedContact.EncryptionPublicKey ps.cache[i].ContactLookupKey = ReceivedContact.LookupPublicKey ps.cache[i].ContactPublicKey = ReceivedContact.ContactPublicKey + if ps.cache[i].MySymKey == "" { + ps.cache[i].MySymKey = ReceivedContact.SymetricKey + } srvs := []string{} for srv := range ReceivedContact.PullServers { srvs = append(srvs, ReceivedContact.PullServers[srv].GetUid())