Skip to content
This repository has been archived by the owner on Jul 22, 2024. It is now read-only.

Commit

Permalink
Merge pull request #25 from signal-golang/groupsv2
Browse files Browse the repository at this point in the history
Support for UUIDS
  • Loading branch information
nanu-c authored Jan 13, 2021
2 parents 0576dd9 + 7ef9a1c commit d374fd7
Show file tree
Hide file tree
Showing 15 changed files with 502 additions and 314 deletions.
32 changes: 32 additions & 0 deletions attachments.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
"net/http"
"strconv"

signalservice "github.com/signal-golang/textsecure/protobuf"
textsecure "github.com/signal-golang/textsecure/protobuf"
)

Expand Down Expand Up @@ -157,6 +158,37 @@ func handleSingleAttachment(a *textsecure.AttachmentPointer) (*Attachment, error

return &Attachment{bytes.NewReader(b), a.GetContentType(), a.GetFileName()}, nil
}
func handleProfileAvatar(profileAvatar *signalservice.ContactDetails_Avatar, key []byte) (*Attachment, error) {

loc, err := getProfileLocation(profileAvatar.String())
if err != nil {
return nil, err
}
r, err := getAttachment(loc)
if err != nil {
return nil, err
}
defer r.Close()

b, err := ioutil.ReadAll(r)
if err != nil {
return nil, err
}

l := len(b) - 16
if !verifyMAC(key[16:], b[:l], b[l:]) {
return nil, ErrInvalidMACForAttachment
}

b, err = aesDecrypt(key[:16], b[:l])
if err != nil {
return nil, err
}

// TODO: verify digest

return &Attachment{bytes.NewReader(b), profileAvatar.GetContentType(), ""}, nil
}

func handleAttachments(dm *textsecure.DataMessage) ([]*Attachment, error) {
atts := dm.GetAttachments()
Expand Down
5 changes: 2 additions & 3 deletions axolotl/session.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ import (
"errors"
"fmt"

"github.com/golang/protobuf/proto"
protobuf "github.com/signal-golang/textsecure/axolotl/protobuf"
"github.com/signal-golang/textsecure/curve25519sign"
"github.com/signal-golang/textsecure/protobuf"
"github.com/golang/protobuf/proto"
signalservice "github.com/signal-golang/textsecure/protobuf"
)

type sessionState struct {
Expand Down Expand Up @@ -658,7 +658,6 @@ func (ss *sessionState) decrypt(ciphertext *WhisperMessage) ([]byte, error) {
func (sc *SessionCipher) SessionDecryptWhisperMessage(ciphertext *WhisperMessage) ([]byte, error) {
sc.SessionStore.Lock()
defer sc.SessionStore.Unlock()

sr, err := sc.SessionStore.LoadSession(sc.RecipientID, sc.DeviceID)
if err != nil {
return nil, err
Expand Down
46 changes: 35 additions & 11 deletions config.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,45 @@ import (
"io/ioutil"

"github.com/go-yaml/yaml"
log "github.com/sirupsen/logrus"
)

// Config holds application configuration settings
type Config struct {
Tel string `yaml:"tel"` // Our telephone number
Server string `yaml:"server"` // The TextSecure server URL
RootCA string `yaml:"rootCA"` // The TLS signing certificate of the server we connect to
ProxyServer string `yaml:"proxy"` // HTTP Proxy URL if one is being used
VerificationType string `yaml:"verificationType"` // Code verification method during registration (SMS/VOICE/DEV)
StorageDir string `yaml:"storageDir"` // Directory for the persistent storage
UnencryptedStorage bool `yaml:"unencryptedStorage"` // Whether to store plaintext keys and session state (only for development)
StoragePassword string `yaml:"storagePassword"` // Password to the storage
LogLevel string `yaml:"loglevel"` // Verbosity of the logging messages
UserAgent string `yaml:"userAgent"` // Override for the default HTTP User Agent header field
AlwaysTrustPeerID bool `yaml:"alwaysTrustPeerID"` // Workaround until proper handling of peer reregistering with new ID.
Tel string `yaml:"tel"` // Our telephone number
UUID string `yaml:"uuid" default:"notset"`
Server string `yaml:"server"` // The TextSecure server URL
RootCA string `yaml:"rootCA"` // The TLS signing certificate of the server we connect to
ProxyServer string `yaml:"proxy"` // HTTP Proxy URL if one is being used
VerificationType string `yaml:"verificationType"` // Code verification method during registration (SMS/VOICE/DEV)
StorageDir string `yaml:"storageDir"` // Directory for the persistent storage
UnencryptedStorage bool `yaml:"unencryptedStorage"` // Whether to store plaintext keys and session state (only for development)
StoragePassword string `yaml:"storagePassword"` // Password to the storage
LogLevel string `yaml:"loglevel"` // Verbosity of the logging messages
UserAgent string `yaml:"userAgent"` // Override for the default HTTP User Agent header field
AlwaysTrustPeerID bool `yaml:"alwaysTrustPeerID"` // Workaround until proper handling of peer reregistering with new ID.
AccountCapabilities AccountCapabilities `yaml:"accountCapabilities"` // Account Attrributes are used in order to track the support of different function for signal
DiscoverableByPhoneNumber bool `yaml:"discoverableByPhoneNumber"` // If the user should be found by his phone number
}

// TODO: some race conditions to be solved
func checkUUID(cfg *Config) *Config {
defer func(cfg *Config) *Config {
log.Debugln("[textsecure] missing my uuid defer")
recover()
UUID, err := GetMyUUID()
if err != nil {
log.Debugln("[textsecure] missing my uuid", err)
return cfg
}
cfg.UUID = UUID
return cfg
}(cfg)
if cfg.UUID == "notset" {
log.Debugln("[textsecure] missing my uuid notset")
}
return cfg

}

// ReadConfig reads a YAML config file
Expand Down
116 changes: 55 additions & 61 deletions contacts.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,31 @@
package textsecure

import (
"bytes"
"io"
"io/ioutil"

"github.com/signal-golang/textsecure/protobuf"
signalservice "github.com/signal-golang/textsecure/protobuf"
log "github.com/sirupsen/logrus"

"gopkg.in/yaml.v2"
)

// Contact contains information about a contact.
type Contact struct {
Tel string
Uuid string
Name string
Color string
Avatar []byte
Blocked bool
ExpireTimer uint32
UUID string
Tel string
ProfileKey []byte
IdentityKey []byte
Name string
Username string
Avatar []byte
Color string
Blocked bool
Verified *signalservice.Verified
ExpireTimer uint32
InboxPosition uint32
Archived bool
}

type yamlContacts struct {
Expand All @@ -35,12 +43,13 @@ var (
// ReadContacts reads a YAML contacts file
func loadContacts(contactsYaml *yamlContacts) {
for _, c := range contactsYaml.Contacts {
contacts[c.Tel] = c
contacts[c.UUID] = c
}
}

var filePath string

// ReadContacts loads the contacts yaml file and pareses it
func ReadContacts(fileName string) ([]Contact, error) {
b, err := ioutil.ReadFile(fileName)
filePath = fileName
Expand All @@ -57,15 +66,16 @@ func ReadContacts(fileName string) ([]Contact, error) {
}

// WriteContacts saves a list of contacts to a file
func WriteContacts(filename string, contacts2 []Contact) error {
c := &yamlContacts{contacts2}
// func WriteContacts(filename string) error {
func WriteContacts(filename string, contacts []Contact) error {
c := &yamlContacts{contacts}
b, err := yaml.Marshal(c)
if err != nil {
return err
}
return ioutil.WriteFile(filename, b, 0600)
}

// WriteContactsToPath saves a list of contacts to a file at the standard location
func WriteContactsToPath() error {
c := contactsToYaml()
b, err := yaml.Marshal(c)
Expand All @@ -82,36 +92,39 @@ func contactsToYaml() *yamlContacts {
return c
}

// type AvatarDetail struct {
// Length
// }

func updateContact(c *signalservice.ContactDetails) error {
log.Debugln("[textsecure] updateContact ", c.GetName())

// var r io.Reader
// av := c.GetAvatar()
// buf := new(bytes.Buffer)
// if av != nil {
// att, err := handleSingleAttachment(av)
// if err != nil {
// return err
// }
// r = att.R
// buf.ReadFrom(r)
// }

contacts[c.GetNumber()] = Contact{
Tel: c.GetNumber(),
Uuid: c.GetUuid(),
Name: c.GetName(),
Color: c.GetColor(),
Avatar: []byte(""),
Blocked: c.GetBlocked(),
ExpireTimer: c.GetExpireTimer(),
log.Debugln("[textsecure] updateContact ", c.GetUuid())

var r io.Reader
av := c.GetAvatar()
buf := new(bytes.Buffer)
if av != nil {
att, err := handleProfileAvatar(av, c.GetProfileKey())
if err != nil {
return err
}
r = att.R
buf.ReadFrom(r)
}
avatar, _ := ioutil.ReadAll(buf)

contacts[c.GetUuid()] = Contact{
Tel: c.GetNumber(),
UUID: c.GetUuid(),
Name: c.GetName(),
Avatar: avatar,
Color: c.GetColor(),
Verified: c.GetVerified(),
ProfileKey: c.GetProfileKey(),
Blocked: c.GetBlocked(),
ExpireTimer: c.GetExpireTimer(),
InboxPosition: c.GetInboxPosition(),
Archived: c.GetArchived(),
}
log.Debugln(c.GetAvatar(), buf)
return WriteContactsToPath()
}

func handleContacts(src string, dm *signalservice.DataMessage) ([]*signalservice.DataMessage_Contact, error) {
cs := dm.GetContact()
if cs == nil {
Expand All @@ -122,32 +135,13 @@ func handleContacts(src string, dm *signalservice.DataMessage) ([]*signalservice

log.Debugln("[textsecure] handle Contact", c.GetName())
}
// switch c.GetType() {
// case signalservice.GroupContext_UPDATE:
// if err := updateGroup(gr); err != nil {
// return nil, err
// }
// groups[hexid].Flags = GroupUpdateFlag
// case signalservice.GroupContext_DELIVER:
// if _, ok := groups[hexid]; !ok {
// g, _ := newPartlyGroup(gr.GetId())
// RequestGroupInfo(g)
// setupGroups()
// return nil, UnknownGroupIDError{hexid}
// }
// groups[hexid].Flags = 0
// case signalservice.GroupContext_QUIT:
// if err := quitGroup(src, hexid); err != nil {
// return nil, err
// }
// groups[hexid].Flags = GroupLeaveFlag
// }

return nil, nil
}
func RequestContactInfo() error {

// SyncContacts syncs the contacts
func SyncContacts() error {
var t signalservice.SyncMessage_Request_Type
t = 1
t = signalservice.SyncMessage_Request_CONTACTS
omsg := &signalservice.SyncMessage{
Request: &signalservice.SyncMessage_Request{
Type: &t,
Expand Down
30 changes: 28 additions & 2 deletions crypto.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,10 @@ import (
"fmt"
"io"

"github.com/signal-golang/textsecure/axolotl"
"github.com/signal-golang/textsecure/protobuf"
"github.com/golang/protobuf/proto"
"github.com/signal-golang/textsecure/axolotl"
signalservice "github.com/signal-golang/textsecure/protobuf"
log "github.com/sirupsen/logrus"
"golang.org/x/crypto/curve25519"
)

Expand Down Expand Up @@ -87,6 +88,8 @@ func aesDecrypt(key, ciphertext []byte) ([]byte, error) {
}

if len(ciphertext)%aes.BlockSize != 0 {
length := len(ciphertext) % aes.BlockSize
log.Debugln("[textsecure] aesDecrypt ciphertext not multiple of AES blocksize", length)
return nil, errors.New("ciphertext not multiple of AES blocksize")
}

Expand All @@ -100,6 +103,29 @@ func aesDecrypt(key, ciphertext []byte) ([]byte, error) {
return ciphertext[aes.BlockSize : len(ciphertext)-int(pad)], nil
}

func aesCtrNoPaddingDecrypt(key, ciphertext []byte) ([]byte, error) {
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}

if len(ciphertext)%aes.BlockSize != 0 {
length := len(ciphertext) % aes.BlockSize
log.Debugln("[textsecure] aesDecrypt ciphertext not multiple of AES blocksize", length)
return nil, errors.New("ciphertext not multiple of AES blocksize")
}

iv := ciphertext[:aes.BlockSize]
mode := cipher.NewCBCDecrypter(block, iv)
// CryptBlocks can work in-place if the two arguments are the same.
mode.CryptBlocks(ciphertext, ciphertext)
// s := string(ciphertext[:])

return ciphertext, nil

// return ciphertext[aes.BlockSize : len(ciphertext)-int(pad)], nil
}

// ProvisioningCipher
func provisioningCipher(pm *signalservice.ProvisionMessage, theirPublicKey *axolotl.ECPublicKey) ([]byte, error) {
ourKeyPair := axolotl.GenerateIdentityKeyPair()
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ require (
golang.org/x/net v0.0.0-20200625001655-4c5254603344 // indirect
golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae // indirect
golang.org/x/text v0.3.2
google.golang.org/protobuf v1.25.0 // indirect
google.golang.org/protobuf v1.25.0
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect
gopkg.in/yaml.v2 v2.3.0
)
Loading

0 comments on commit d374fd7

Please sign in to comment.