Add protocol version to bundle
This commit is contained in:
parent
cef7f367ab
commit
78ed35d2fe
|
@ -10,6 +10,7 @@
|
|||
// 1541164797_add_installations.up.sql
|
||||
// 1558084410_add_topic.down.sql
|
||||
// 1558084410_add_topic.up.sql
|
||||
// 1558588866_add_version.up.sql
|
||||
// static.go
|
||||
// DO NOT EDIT!
|
||||
|
||||
|
@ -278,6 +279,26 @@ func _1558084410_add_topicUpSql() (*asset, error) {
|
|||
return a, nil
|
||||
}
|
||||
|
||||
var __1558588866_add_versionUpSql = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x72\xf4\x09\x71\x0d\x52\x08\x71\x74\xf2\x71\x55\xc8\xcc\x2b\x2e\x49\xcc\xc9\x49\x2c\xc9\xcc\xcf\x2b\x56\x70\x74\x71\x51\x28\x4b\x2d\x2a\xce\xcc\xcf\x53\xf0\xf4\x0b\x71\x75\x77\x0d\x52\x70\x71\x75\x73\x0c\xf5\x09\x51\x30\xb0\xe6\x02\x04\x00\x00\xff\xff\x14\x7b\x07\xb5\x39\x00\x00\x00")
|
||||
|
||||
func _1558588866_add_versionUpSqlBytes() ([]byte, error) {
|
||||
return bindataRead(
|
||||
__1558588866_add_versionUpSql,
|
||||
"1558588866_add_version.up.sql",
|
||||
)
|
||||
}
|
||||
|
||||
func _1558588866_add_versionUpSql() (*asset, error) {
|
||||
bytes, err := _1558588866_add_versionUpSqlBytes()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1558588866_add_version.up.sql", size: 57, mode: os.FileMode(420), modTime: time.Unix(1558588995, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
||||
var _staticGo = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x54\xcc\x41\x6a\x03\x31\x0c\x46\xe1\xbd\x4f\xf1\x2f\x5b\xe8\x58\xfb\x9e\xa0\x94\x16\x0a\xcd\x05\x64\x8f\x90\xc5\x30\xf6\x60\x29\x21\xc7\xcf\x26\x21\x64\xf9\xe0\xf1\x11\xe1\x8f\xeb\xc6\x2a\xf0\xe0\xb0\x0a\xd9\x8b\xac\xfe\xa8\xb7\xef\xff\x0f\x7c\x9d\x7e\x7f\xde\x31\xc5\xc7\x79\x56\x71\x4c\xd3\x16\xb0\x1e\x03\xd1\x04\xc5\x3a\x4f\x13\x4f\xc7\x8b\x94\x12\x91\x8e\x4f\x95\x2e\x93\x43\xa0\x63\x29\xd6\x57\x0e\xc6\x72\x6c\x8a\xdd\x74\x72\xd8\xe8\x8e\x65\x20\x67\xca\x99\x5c\xe6\xc5\xaa\x38\x79\x6b\x72\x0d\xaa\x8d\x83\xd6\x42\xcf\x97\xee\x46\xd6\x81\x9c\x6e\x01\x00\x00\xff\xff\x6c\x21\xbf\x7a\xbf\x00\x00\x00")
|
||||
|
||||
func staticGoBytes() ([]byte, error) {
|
||||
|
@ -360,6 +381,7 @@ var _bindata = map[string]func() (*asset, error){
|
|||
"1541164797_add_installations.up.sql": _1541164797_add_installationsUpSql,
|
||||
"1558084410_add_topic.down.sql": _1558084410_add_topicDownSql,
|
||||
"1558084410_add_topic.up.sql": _1558084410_add_topicUpSql,
|
||||
"1558588866_add_version.up.sql": _1558588866_add_versionUpSql,
|
||||
"static.go": staticGo,
|
||||
}
|
||||
|
||||
|
@ -413,6 +435,7 @@ var _bintree = &bintree{nil, map[string]*bintree{
|
|||
"1541164797_add_installations.up.sql": &bintree{_1541164797_add_installationsUpSql, map[string]*bintree{}},
|
||||
"1558084410_add_topic.down.sql": &bintree{_1558084410_add_topicDownSql, map[string]*bintree{}},
|
||||
"1558084410_add_topic.up.sql": &bintree{_1558084410_add_topicUpSql, map[string]*bintree{}},
|
||||
"1558588866_add_version.up.sql": &bintree{_1558588866_add_versionUpSql, map[string]*bintree{}},
|
||||
"static.go": &bintree{staticGo, map[string]*bintree{}},
|
||||
}}
|
||||
|
||||
|
|
|
@ -135,14 +135,17 @@ func (s *EncryptionService) ConfirmMessagesProcessed(messageIDs [][]byte) error
|
|||
func (s *EncryptionService) CreateBundle(privateKey *ecdsa.PrivateKey) (*Bundle, error) {
|
||||
ourIdentityKeyC := ecrypto.CompressPubkey(&privateKey.PublicKey)
|
||||
|
||||
installationIDs, err := s.persistence.GetActiveInstallations(s.config.MaxInstallations-1, ourIdentityKeyC)
|
||||
installations, err := s.persistence.GetActiveInstallations(s.config.MaxInstallations-1, ourIdentityKeyC)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
installationIDs = append(installationIDs, s.config.InstallationID)
|
||||
installations = append(installations, &Installation{
|
||||
ID: s.config.InstallationID,
|
||||
Version: protocolCurrentVersion,
|
||||
})
|
||||
|
||||
bundleContainer, err := s.persistence.GetAnyPrivateBundle(ourIdentityKeyC, installationIDs)
|
||||
bundleContainer, err := s.persistence.GetAnyPrivateBundle(ourIdentityKeyC, installations)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -240,21 +243,24 @@ func (s *EncryptionService) ProcessPublicBundle(myIdentityKey *ecdsa.PrivateKey,
|
|||
}
|
||||
signedPreKeys := b.GetSignedPreKeys()
|
||||
var response []IdentityAndIDPair
|
||||
var installationIDs []string
|
||||
var installations []*Installation
|
||||
myIdentityStr := fmt.Sprintf("0x%x", ecrypto.FromECDSAPub(&myIdentityKey.PublicKey))
|
||||
|
||||
// Any device from other peers will be considered enabled, ours needs to
|
||||
// be explicitly enabled
|
||||
fromOurIdentity := identity != myIdentityStr
|
||||
|
||||
for installationID := range signedPreKeys {
|
||||
for installationID, signedPreKey := range signedPreKeys {
|
||||
if installationID != s.config.InstallationID {
|
||||
installationIDs = append(installationIDs, installationID)
|
||||
installations = append(installations, &Installation{
|
||||
ID: installationID,
|
||||
Version: signedPreKey.GetProtocolVersion(),
|
||||
})
|
||||
response = append(response, IdentityAndIDPair{identity, installationID})
|
||||
}
|
||||
}
|
||||
|
||||
if err = s.persistence.AddInstallations(b.GetIdentity(), b.GetTimestamp(), installationIDs, fromOurIdentity); err != nil {
|
||||
if err = s.persistence.AddInstallations(b.GetIdentity(), b.GetTimestamp(), installations, fromOurIdentity); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
@ -323,7 +329,7 @@ func (s *EncryptionService) DecryptPayload(myIdentityKey *ecdsa.PrivateKey, thei
|
|||
}
|
||||
|
||||
// Add installations with a timestamp of 0, as we don't have bundle informations
|
||||
if err = s.persistence.AddInstallations(theirIdentityKeyC, 0, []string{theirInstallationID}, true); err != nil {
|
||||
if err = s.persistence.AddInstallations(theirIdentityKeyC, 0, []*Installation{{ID: theirInstallationID, Version: 0}}, true); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
@ -502,12 +508,12 @@ func (s *EncryptionService) EncryptPayloadWithDH(theirIdentityKey *ecdsa.PublicK
|
|||
func (s *EncryptionService) GetPublicBundle(theirIdentityKey *ecdsa.PublicKey) (*Bundle, error) {
|
||||
theirIdentityKeyC := ecrypto.CompressPubkey(theirIdentityKey)
|
||||
|
||||
installationIDs, err := s.persistence.GetActiveInstallations(s.config.MaxInstallations, theirIdentityKeyC)
|
||||
installations, err := s.persistence.GetActiveInstallations(s.config.MaxInstallations, theirIdentityKeyC)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return s.persistence.GetPublicBundle(theirIdentityKey, installationIDs)
|
||||
return s.persistence.GetPublicBundle(theirIdentityKey, installations)
|
||||
}
|
||||
|
||||
// EncryptPayload returns a new DirectMessageProtocol with a given payload encrypted, given a recipient's public key and the sender private identity key
|
||||
|
@ -522,24 +528,25 @@ func (s *EncryptionService) EncryptPayload(theirIdentityKey *ecdsa.PublicKey, my
|
|||
theirIdentityKeyC := ecrypto.CompressPubkey(theirIdentityKey)
|
||||
|
||||
// Get their installationIds
|
||||
installationIds, err := s.persistence.GetActiveInstallations(s.config.MaxInstallations, theirIdentityKeyC)
|
||||
installations, err := s.persistence.GetActiveInstallations(s.config.MaxInstallations, theirIdentityKeyC)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// We don't have any, send a message with DH
|
||||
if installationIds == nil && !bytes.Equal(theirIdentityKeyC, ecrypto.CompressPubkey(&myIdentityKey.PublicKey)) {
|
||||
if installations == nil && !bytes.Equal(theirIdentityKeyC, ecrypto.CompressPubkey(&myIdentityKey.PublicKey)) {
|
||||
return s.EncryptPayloadWithDH(theirIdentityKey, payload)
|
||||
}
|
||||
|
||||
response := make(map[string]*DirectMessageProtocol)
|
||||
|
||||
for _, installationID := range installationIds {
|
||||
for _, installation := range installations {
|
||||
installationID := installation.ID
|
||||
s.log.Debug("Processing installation", "installationID", installationID)
|
||||
if s.config.InstallationID == installationID {
|
||||
continue
|
||||
}
|
||||
bundle, err := s.persistence.GetPublicBundle(theirIdentityKey, []string{installationID})
|
||||
bundle, err := s.persistence.GetPublicBundle(theirIdentityKey, []*Installation{installation})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@ const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
|
|||
type SignedPreKey struct {
|
||||
SignedPreKey []byte `protobuf:"bytes,1,opt,name=signed_pre_key,json=signedPreKey,proto3" json:"signed_pre_key,omitempty"`
|
||||
Version uint32 `protobuf:"varint,2,opt,name=version,proto3" json:"version,omitempty"`
|
||||
ProtocolVersion uint32 `protobuf:"varint,3,opt,name=protocol_version,json=protocolVersion,proto3" json:"protocol_version,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
|
@ -67,6 +68,13 @@ func (m *SignedPreKey) GetVersion() uint32 {
|
|||
return 0
|
||||
}
|
||||
|
||||
func (m *SignedPreKey) GetProtocolVersion() uint32 {
|
||||
if m != nil {
|
||||
return m.ProtocolVersion
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// X3DH prekey bundle
|
||||
type Bundle struct {
|
||||
// Identity key
|
||||
|
@ -416,9 +424,7 @@ type ProtocolMessage struct {
|
|||
// One to one message, encrypted, indexed by installation_id
|
||||
DirectMessage map[string]*DirectMessageProtocol `protobuf:"bytes,101,rep,name=direct_message,json=directMessage,proto3" json:"direct_message,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
|
||||
// Public chats, not encrypted
|
||||
PublicMessage []byte `protobuf:"bytes,102,opt,name=public_message,json=publicMessage,proto3" json:"public_message,omitempty"`
|
||||
// Version of the protocol
|
||||
Version uint32 `protobuf:"varint,103,opt,name=version,proto3" json:"version,omitempty"`
|
||||
PublicMessage []byte `protobuf:"bytes,102,opt,name=public_message,json=publicMessage,proto3" json:"public_message,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
|
@ -484,13 +490,6 @@ func (m *ProtocolMessage) GetPublicMessage() []byte {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (m *ProtocolMessage) GetVersion() uint32 {
|
||||
if m != nil {
|
||||
return m.Version
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterType((*SignedPreKey)(nil), "chat.SignedPreKey")
|
||||
proto.RegisterType((*Bundle)(nil), "chat.Bundle")
|
||||
|
@ -507,40 +506,41 @@ func init() {
|
|||
func init() { proto.RegisterFile("encryption.proto", fileDescriptor_8293a649ce9418c6) }
|
||||
|
||||
var fileDescriptor_8293a649ce9418c6 = []byte{
|
||||
// 553 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x54, 0x5d, 0x8b, 0xd3, 0x40,
|
||||
0x14, 0x25, 0x49, 0x77, 0xb7, 0xbd, 0x4d, 0xd3, 0x32, 0xa2, 0x84, 0xba, 0x60, 0x09, 0xab, 0x06,
|
||||
0x84, 0xc2, 0xb6, 0x3e, 0x88, 0x8f, 0x5a, 0xb1, 0xae, 0xa8, 0xcb, 0xe8, 0x83, 0x2f, 0x12, 0xa6,
|
||||
0xcd, 0xd8, 0x1d, 0x4c, 0x27, 0x61, 0x32, 0x2d, 0xf4, 0xcf, 0xf9, 0xbf, 0x7c, 0x52, 0x32, 0x93,
|
||||
0x69, 0x27, 0xdd, 0x5d, 0xf0, 0xad, 0xf7, 0x63, 0xce, 0x3d, 0xf7, 0xdc, 0x9c, 0xc2, 0x80, 0xf2,
|
||||
0xa5, 0xd8, 0x15, 0x92, 0xe5, 0x7c, 0x5c, 0x88, 0x5c, 0xe6, 0xa8, 0xb5, 0xbc, 0x21, 0x32, 0xfa,
|
||||
0x0c, 0xfe, 0x57, 0xb6, 0xe2, 0x34, 0xbd, 0x16, 0xf4, 0x23, 0xdd, 0xa1, 0x0b, 0x08, 0x4a, 0x15,
|
||||
0x27, 0x85, 0xa0, 0xc9, 0x2f, 0xba, 0x0b, 0x9d, 0x91, 0x13, 0xfb, 0xd8, 0x2f, 0xed, 0xae, 0x10,
|
||||
0xce, 0xb6, 0x54, 0x94, 0x2c, 0xe7, 0xa1, 0x3b, 0x72, 0xe2, 0x1e, 0x36, 0x61, 0xf4, 0xd7, 0x81,
|
||||
0xd3, 0x37, 0x1b, 0x9e, 0x66, 0x14, 0x0d, 0xa1, 0xcd, 0x52, 0xca, 0x25, 0x93, 0x06, 0x64, 0x1f,
|
||||
0xa3, 0xf7, 0xd0, 0x6f, 0x8e, 0x29, 0x43, 0x77, 0xe4, 0xc5, 0xdd, 0xc9, 0x93, 0x71, 0x45, 0x6b,
|
||||
0xac, 0x21, 0xc6, 0x36, 0xb5, 0xf2, 0x1d, 0x97, 0x62, 0x87, 0x7b, 0x36, 0x91, 0x12, 0x9d, 0x43,
|
||||
0xa7, 0x4a, 0x10, 0xb9, 0x11, 0x34, 0x6c, 0xa9, 0x29, 0x87, 0x44, 0x55, 0x95, 0x6c, 0x4d, 0x4b,
|
||||
0x49, 0xd6, 0x45, 0x78, 0x32, 0x72, 0x62, 0x0f, 0x1f, 0x12, 0xc3, 0x6f, 0x80, 0x6e, 0x0f, 0x40,
|
||||
0x03, 0xf0, 0xcc, 0xda, 0x1d, 0x5c, 0xfd, 0x44, 0x31, 0x9c, 0x6c, 0x49, 0xb6, 0xa1, 0x6a, 0xd7,
|
||||
0xee, 0x04, 0x69, 0x8a, 0xf6, 0x53, 0xac, 0x1b, 0x5e, 0xbb, 0xaf, 0x9c, 0x48, 0x40, 0x5f, 0xb3,
|
||||
0x7f, 0x9b, 0x73, 0x49, 0x18, 0xa7, 0x02, 0x5d, 0xc0, 0xe9, 0x42, 0xa5, 0x14, 0x6a, 0x77, 0xe2,
|
||||
0xdb, 0x4b, 0xe2, 0xba, 0x86, 0xa6, 0xf0, 0xa8, 0x10, 0x6c, 0x4b, 0x24, 0x4d, 0x8e, 0x4e, 0xe0,
|
||||
0xaa, 0xbd, 0x1e, 0xd4, 0x55, 0x7b, 0xf0, 0x55, 0xab, 0xed, 0x0d, 0x5a, 0xd1, 0x15, 0xb4, 0x67,
|
||||
0x78, 0x4e, 0x49, 0x4a, 0x85, 0xcd, 0xdf, 0xd7, 0xfc, 0x7d, 0x70, 0xcc, 0x9d, 0x1c, 0x8e, 0x02,
|
||||
0x70, 0x0b, 0x1e, 0x7a, 0x2a, 0x74, 0x0b, 0x15, 0xb3, 0xb4, 0x96, 0xce, 0x65, 0x69, 0x74, 0x0e,
|
||||
0xed, 0xd9, 0xfc, 0x3e, 0xac, 0xe8, 0x25, 0xc0, 0xf7, 0xe9, 0xfd, 0xf5, 0x63, 0xb4, 0x9a, 0xdf,
|
||||
0x6f, 0x07, 0x1e, 0xce, 0x98, 0xa0, 0x4b, 0xf9, 0x89, 0x96, 0x25, 0x59, 0xd1, 0xeb, 0xea, 0x13,
|
||||
0x5c, 0xe6, 0x19, 0xba, 0x84, 0x6e, 0x85, 0x97, 0xdc, 0x28, 0xc0, 0x5a, 0x9f, 0x81, 0xd6, 0xe7,
|
||||
0x30, 0x08, 0xdb, 0x43, 0x5f, 0x40, 0x67, 0x86, 0xcd, 0x03, 0x7d, 0x92, 0x40, 0x3f, 0x30, 0x1a,
|
||||
0xe0, 0x83, 0x1a, 0x55, 0xf3, 0x1e, 0x9d, 0x36, 0x9a, 0xe7, 0xfb, 0x66, 0x83, 0x1c, 0xc2, 0x59,
|
||||
0x41, 0x76, 0x59, 0x4e, 0x52, 0xa5, 0x8f, 0x8f, 0x4d, 0x18, 0xfd, 0x71, 0xa1, 0x6f, 0x38, 0xd7,
|
||||
0x2b, 0xfc, 0xe7, 0x55, 0x9f, 0x43, 0x9f, 0xf1, 0x52, 0x92, 0x2c, 0x23, 0x95, 0xf9, 0x12, 0x96,
|
||||
0x2a, 0xce, 0x1d, 0x1c, 0xd8, 0xe9, 0x0f, 0x29, 0x7a, 0x06, 0x67, 0xfa, 0x49, 0x19, 0x7a, 0xca,
|
||||
0x0a, 0x4d, 0x3c, 0x53, 0x44, 0x5f, 0x20, 0x48, 0x95, 0x94, 0xc9, 0x5a, 0x13, 0x09, 0xa9, 0x6a,
|
||||
0x8f, 0x75, 0xfb, 0x11, 0xcb, 0x71, 0x43, 0xf6, 0xda, 0x42, 0xa9, 0x9d, 0x43, 0x4f, 0x21, 0x28,
|
||||
0x36, 0x8b, 0x8c, 0x2d, 0xf7, 0x80, 0x3f, 0xd5, 0xf2, 0x3d, 0x9d, 0x35, 0x6d, 0x96, 0xe7, 0x57,
|
||||
0x0d, 0xcf, 0x0f, 0x7f, 0x00, 0xba, 0x3d, 0xe5, 0x0e, 0x1f, 0x5d, 0x36, 0x7d, 0xf4, 0xb8, 0xbe,
|
||||
0xc3, 0x5d, 0xdf, 0x85, 0x65, 0xa8, 0xc5, 0xa9, 0xfa, 0xbf, 0x9a, 0xfe, 0x0b, 0x00, 0x00, 0xff,
|
||||
0xff, 0x53, 0xcb, 0xc9, 0xb7, 0xc3, 0x04, 0x00, 0x00,
|
||||
// 562 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x54, 0x61, 0x8b, 0xd3, 0x4c,
|
||||
0x10, 0x26, 0x49, 0xef, 0xda, 0x4e, 0xd3, 0xb4, 0xec, 0xcb, 0x2b, 0xa1, 0x1e, 0x58, 0xc2, 0xa9,
|
||||
0x11, 0xa1, 0x70, 0xad, 0x1f, 0xc4, 0x8f, 0x5a, 0xb1, 0x9e, 0x88, 0xc7, 0x2a, 0xe2, 0x17, 0x09,
|
||||
0xdb, 0x66, 0xbd, 0x5b, 0x4c, 0x93, 0xb0, 0xbb, 0x2d, 0xe4, 0xcf, 0xf9, 0x57, 0xfc, 0x29, 0x4a,
|
||||
0x76, 0xb3, 0xed, 0xb6, 0x77, 0x07, 0x7e, 0xeb, 0xcc, 0x3c, 0xfb, 0xcc, 0x33, 0xcf, 0x74, 0x02,
|
||||
0x43, 0x9a, 0xaf, 0x78, 0x55, 0x4a, 0x56, 0xe4, 0x93, 0x92, 0x17, 0xb2, 0x40, 0xad, 0xd5, 0x0d,
|
||||
0x91, 0x51, 0x05, 0xfe, 0x67, 0x76, 0x9d, 0xd3, 0xf4, 0x8a, 0xd3, 0x0f, 0xb4, 0x42, 0xe7, 0x10,
|
||||
0x08, 0x15, 0x27, 0x25, 0xa7, 0xc9, 0x4f, 0x5a, 0x85, 0xce, 0xd8, 0x89, 0x7d, 0xec, 0x0b, 0x1b,
|
||||
0x15, 0x42, 0x7b, 0x4b, 0xb9, 0x60, 0x45, 0x1e, 0xba, 0x63, 0x27, 0xee, 0x63, 0x13, 0xa2, 0x67,
|
||||
0x30, 0x54, 0xf4, 0xab, 0x22, 0x4b, 0x0c, 0xc4, 0x53, 0x90, 0x81, 0xc9, 0x7f, 0xd5, 0xe9, 0xe8,
|
||||
0x8f, 0x03, 0xa7, 0xaf, 0x37, 0x79, 0x9a, 0x51, 0x34, 0x82, 0x0e, 0x4b, 0x69, 0x2e, 0x99, 0x34,
|
||||
0xfd, 0x76, 0x31, 0x7a, 0x07, 0x83, 0x43, 0x45, 0x22, 0x74, 0xc7, 0x5e, 0xdc, 0x9b, 0x3e, 0x9a,
|
||||
0xd4, 0x13, 0x4c, 0x34, 0xc5, 0xc4, 0x9e, 0x42, 0xbc, 0xcd, 0x25, 0xaf, 0x70, 0xdf, 0xd6, 0x2c,
|
||||
0xd0, 0x19, 0x74, 0xeb, 0x04, 0x91, 0x1b, 0x4e, 0xc3, 0x96, 0xea, 0xb2, 0x4f, 0xd4, 0x55, 0xc9,
|
||||
0xd6, 0x54, 0x48, 0xb2, 0x2e, 0xc3, 0x93, 0xb1, 0x13, 0x7b, 0x78, 0x9f, 0x18, 0x7d, 0x01, 0x74,
|
||||
0xbb, 0x01, 0x1a, 0x82, 0x67, 0x1c, 0xea, 0xe2, 0xfa, 0x27, 0x8a, 0xe1, 0x64, 0x4b, 0xb2, 0x0d,
|
||||
0x55, 0xb6, 0xf4, 0xa6, 0x48, 0x4b, 0xb4, 0x9f, 0x62, 0x0d, 0x78, 0xe5, 0xbe, 0x74, 0x22, 0x0e,
|
||||
0x03, 0xad, 0xfe, 0x4d, 0x91, 0x4b, 0xc2, 0x72, 0xca, 0xd1, 0x39, 0x9c, 0x2e, 0x55, 0x4a, 0xb1,
|
||||
0xf6, 0xa6, 0xbe, 0x3d, 0x24, 0x6e, 0x6a, 0x68, 0x06, 0x0f, 0x4a, 0xce, 0xb6, 0x44, 0xd2, 0xe4,
|
||||
0x68, 0x5b, 0xae, 0x9a, 0xeb, 0xbf, 0xa6, 0x6a, 0x37, 0xbe, 0x6c, 0x75, 0xbc, 0x61, 0x2b, 0xba,
|
||||
0x84, 0xce, 0x1c, 0x2f, 0x28, 0x49, 0x29, 0xb7, 0xf5, 0xfb, 0x5a, 0xbf, 0x0f, 0x8e, 0x59, 0xa9,
|
||||
0x93, 0xa3, 0x00, 0xdc, 0xd2, 0xac, 0xcf, 0x2d, 0x55, 0xcc, 0xd2, 0xc6, 0x3a, 0x97, 0xa5, 0xd1,
|
||||
0x19, 0x74, 0xe6, 0x8b, 0xfb, 0xb8, 0xa2, 0x17, 0x00, 0xdf, 0x66, 0xf7, 0xd7, 0x8f, 0xd9, 0x1a,
|
||||
0x7d, 0xbf, 0x1c, 0xf8, 0x7f, 0xce, 0x38, 0x5d, 0xc9, 0x8f, 0x54, 0x08, 0x72, 0x4d, 0xaf, 0x9a,
|
||||
0xbf, 0x0d, 0xba, 0x80, 0x5e, 0xcd, 0x97, 0xdc, 0x28, 0xc2, 0xc6, 0x9f, 0xa1, 0xf6, 0x67, 0xdf,
|
||||
0x08, 0xdb, 0x4d, 0x9f, 0x43, 0x77, 0x8e, 0xcd, 0x03, 0xbd, 0x92, 0x40, 0x3f, 0x30, 0x1e, 0xe0,
|
||||
0xbd, 0x1b, 0x35, 0x78, 0xc7, 0x4e, 0x0f, 0xc0, 0x8b, 0x1d, 0xd8, 0x30, 0x87, 0xd0, 0x2e, 0x49,
|
||||
0x95, 0x15, 0x24, 0x55, 0xfe, 0xf8, 0xd8, 0x84, 0xd1, 0x6f, 0x17, 0x06, 0x46, 0x73, 0x33, 0xc2,
|
||||
0x3f, 0x6e, 0xf5, 0x29, 0x0c, 0x58, 0x2e, 0x24, 0xc9, 0x32, 0x52, 0xdf, 0x69, 0xc2, 0x52, 0xa5,
|
||||
0xb9, 0x8b, 0x03, 0x3b, 0xfd, 0x3e, 0x45, 0x4f, 0xa0, 0xad, 0x9f, 0x88, 0xd0, 0x53, 0xa7, 0x70,
|
||||
0xc8, 0x67, 0x8a, 0xe8, 0x13, 0x04, 0xa9, 0xb2, 0x32, 0x59, 0x6b, 0x21, 0x21, 0x55, 0xf0, 0x58,
|
||||
0xc3, 0x8f, 0x54, 0x4e, 0x0e, 0x6c, 0x6f, 0x4e, 0x28, 0xb5, 0x73, 0xe8, 0x31, 0x04, 0xe5, 0x66,
|
||||
0x99, 0xb1, 0xd5, 0x8e, 0xf0, 0x87, 0x1a, 0xbe, 0xaf, 0xb3, 0x0d, 0x6c, 0xf4, 0x1d, 0xd0, 0x6d,
|
||||
0xae, 0x3b, 0xae, 0xe5, 0xe2, 0xf0, 0x5a, 0x1e, 0x36, 0x6e, 0xdf, 0xb5, 0x7d, 0xeb, 0x6c, 0x96,
|
||||
0xa7, 0xea, 0x4b, 0x32, 0xfb, 0x1b, 0x00, 0x00, 0xff, 0xff, 0x9e, 0x75, 0x6d, 0x59, 0xd4, 0x04,
|
||||
0x00, 0x00,
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ package chat;
|
|||
message SignedPreKey {
|
||||
bytes signed_pre_key = 1;
|
||||
uint32 version = 2;
|
||||
uint32 protocol_version = 3;
|
||||
}
|
||||
|
||||
// X3DH prekey bundle
|
||||
|
@ -77,7 +78,4 @@ message ProtocolMessage {
|
|||
|
||||
// Public chats, not encrypted
|
||||
bytes public_message = 102;
|
||||
|
||||
// Version of the protocol
|
||||
uint32 version = 103;
|
||||
}
|
||||
|
|
|
@ -6,6 +6,11 @@ import (
|
|||
dr "github.com/status-im/doubleratchet"
|
||||
)
|
||||
|
||||
type Installation struct {
|
||||
ID string
|
||||
Version uint32
|
||||
}
|
||||
|
||||
// RatchetInfo holds the current ratchet state
|
||||
type RatchetInfo struct {
|
||||
ID []byte
|
||||
|
@ -26,12 +31,12 @@ type PersistenceService interface {
|
|||
GetSessionStorage() dr.SessionStorage
|
||||
|
||||
// GetPublicBundle retrieves an existing Bundle for the specified public key & installationIDs.
|
||||
GetPublicBundle(*ecdsa.PublicKey, []string) (*Bundle, error)
|
||||
GetPublicBundle(*ecdsa.PublicKey, []*Installation) (*Bundle, error)
|
||||
// AddPublicBundle persists a specified Bundle
|
||||
AddPublicBundle(*Bundle) error
|
||||
|
||||
// GetAnyPrivateBundle retrieves any bundle for our identity & installationIDs
|
||||
GetAnyPrivateBundle([]byte, []string) (*BundleContainer, error)
|
||||
GetAnyPrivateBundle([]byte, []*Installation) (*BundleContainer, error)
|
||||
// GetPrivateKeyBundle retrieves a BundleContainer with the specified signed prekey.
|
||||
GetPrivateKeyBundle([]byte) ([]byte, error)
|
||||
// AddPrivateBundle persists a BundleContainer.
|
||||
|
@ -50,9 +55,9 @@ type PersistenceService interface {
|
|||
RatchetInfoConfirmed([]byte, []byte, string) error
|
||||
|
||||
// GetActiveInstallations returns the active installations for a given identity.
|
||||
GetActiveInstallations(maxInstallations int, identity []byte) ([]string, error)
|
||||
GetActiveInstallations(maxInstallations int, identity []byte) ([]*Installation, error)
|
||||
// AddInstallations adds the installations for a given identity.
|
||||
AddInstallations(identity []byte, timestamp int64, installationIDs []string, enabled bool) error
|
||||
AddInstallations(identity []byte, timestamp int64, installations []*Installation, enabled bool) error
|
||||
// EnableInstallation enables the installation.
|
||||
EnableInstallation(identity []byte, installationID string) error
|
||||
// DisableInstallation disable the installation.
|
||||
|
|
|
@ -58,7 +58,6 @@ func (p *ProtocolService) BuildPublicMessage(myIdentityKey *ecdsa.PrivateKey, pa
|
|||
protocolMessage := &ProtocolMessage{
|
||||
InstallationId: p.encryption.config.InstallationID,
|
||||
PublicMessage: payload,
|
||||
Version: protocolCurrentVersion,
|
||||
}
|
||||
|
||||
return p.addBundle(myIdentityKey, protocolMessage, false)
|
||||
|
@ -77,7 +76,6 @@ func (p *ProtocolService) BuildDirectMessage(myIdentityKey *ecdsa.PrivateKey, pu
|
|||
protocolMessage := &ProtocolMessage{
|
||||
InstallationId: p.encryption.config.InstallationID,
|
||||
DirectMessage: encryptionResponse,
|
||||
Version: protocolCurrentVersion,
|
||||
}
|
||||
|
||||
msg, err := p.addBundle(myIdentityKey, protocolMessage, true)
|
||||
|
@ -109,9 +107,8 @@ func (p *ProtocolService) BuildDirectMessage(myIdentityKey *ecdsa.PrivateKey, pu
|
|||
|
||||
if agreed {
|
||||
return msg, sharedSecret.Key, nil
|
||||
} else {
|
||||
return msg, nil, nil
|
||||
}
|
||||
return msg, nil, nil
|
||||
}
|
||||
|
||||
// BuildDHMessage builds a message with DH encryption so that it can be decrypted by any other device.
|
||||
|
@ -127,7 +124,6 @@ func (p *ProtocolService) BuildDHMessage(myIdentityKey *ecdsa.PrivateKey, destin
|
|||
protocolMessage := &ProtocolMessage{
|
||||
InstallationId: p.encryption.config.InstallationID,
|
||||
DirectMessage: encryptionResponse,
|
||||
Version: protocolCurrentVersion,
|
||||
}
|
||||
|
||||
msg, err := p.addBundle(myIdentityKey, protocolMessage, true)
|
||||
|
@ -211,7 +207,8 @@ func (p *ProtocolService) HandleMessage(myIdentityKey *ecdsa.PrivateKey, theirPu
|
|||
|
||||
p.log.Info("Checking version")
|
||||
// Handle protocol negotiation for compatible clients
|
||||
if protocolMessage.Version >= topicNegotiationVersion {
|
||||
version := getProtocolVersion(protocolMessage.GetBundles(), protocolMessage.GetInstallationId())
|
||||
if version >= topicNegotiationVersion {
|
||||
p.log.Info("Version greater than 1 negotianting")
|
||||
sharedSecret, err := p.topic.Receive(myIdentityKey, theirPublicKey, protocolMessage.GetInstallationId())
|
||||
if err != nil {
|
||||
|
@ -227,3 +224,25 @@ func (p *ProtocolService) HandleMessage(myIdentityKey *ecdsa.PrivateKey, theirPu
|
|||
// Return error
|
||||
return nil, errors.New("no payload")
|
||||
}
|
||||
|
||||
func getProtocolVersion(bundles []*Bundle, installationID string) uint32 {
|
||||
if installationID == "" {
|
||||
return 0
|
||||
}
|
||||
|
||||
for _, bundle := range bundles {
|
||||
signedPreKeys := bundle.GetSignedPreKeys()
|
||||
if signedPreKeys == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
signedPreKey := signedPreKeys[installationID]
|
||||
if signedPreKey == nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
return signedPreKey.GetProtocolVersion()
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
|
|
@ -39,7 +39,7 @@ func (s *ProtocolServiceTestSuite) SetupTest() {
|
|||
}
|
||||
|
||||
addedBundlesHandler := func(addedBundles []IdentityAndIDPair) {}
|
||||
onNewTopicHandler := func(topic [][]byte) {}
|
||||
onNewTopicHandler := func(topic []*topic.Secret) {}
|
||||
|
||||
s.alice = NewProtocolService(
|
||||
NewEncryptionService(alicePersistence, DefaultEncryptionServiceConfig("1")),
|
||||
|
|
|
@ -203,12 +203,13 @@ func (s *SQLLitePersistence) AddPublicBundle(b *Bundle) error {
|
|||
}
|
||||
|
||||
// GetAnyPrivateBundle retrieves any bundle from the database containing a private key
|
||||
func (s *SQLLitePersistence) GetAnyPrivateBundle(myIdentityKey []byte, installationIDs []string) (*BundleContainer, error) {
|
||||
func (s *SQLLitePersistence) GetAnyPrivateBundle(myIdentityKey []byte, installations []*Installation) (*BundleContainer, error) {
|
||||
|
||||
versions := make(map[string]uint32)
|
||||
/* #nosec */
|
||||
statement := `SELECT identity, private_key, signed_pre_key, installation_id, timestamp, version
|
||||
FROM bundles
|
||||
WHERE expired = 0 AND identity = ? AND installation_id IN (?` + strings.Repeat(",?", len(installationIDs)-1) + ")"
|
||||
WHERE expired = 0 AND identity = ? AND installation_id IN (?` + strings.Repeat(",?", len(installations)-1) + ")"
|
||||
stmt, err := s.db.Prepare(statement)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -220,10 +221,13 @@ func (s *SQLLitePersistence) GetAnyPrivateBundle(myIdentityKey []byte, installat
|
|||
var privateKey []byte
|
||||
var version uint32
|
||||
|
||||
args := make([]interface{}, len(installationIDs)+1)
|
||||
args := make([]interface{}, len(installations)+1)
|
||||
args[0] = myIdentityKey
|
||||
for i, installationID := range installationIDs {
|
||||
args[i+1] = installationID
|
||||
for i, installation := range installations {
|
||||
// Lookup up map for versions
|
||||
versions[installation.ID] = installation.Version
|
||||
|
||||
args[i+1] = installation.ID
|
||||
}
|
||||
|
||||
rows, err := stmt.Query(args...)
|
||||
|
@ -263,7 +267,11 @@ func (s *SQLLitePersistence) GetAnyPrivateBundle(myIdentityKey []byte, installat
|
|||
bundle.Timestamp = timestamp
|
||||
}
|
||||
|
||||
bundle.SignedPreKeys[installationID] = &SignedPreKey{SignedPreKey: signedPreKey, Version: version}
|
||||
bundle.SignedPreKeys[installationID] = &SignedPreKey{
|
||||
SignedPreKey: signedPreKey,
|
||||
Version: version,
|
||||
ProtocolVersion: versions[installationID],
|
||||
}
|
||||
bundle.Identity = identity
|
||||
}
|
||||
|
||||
|
@ -315,18 +323,19 @@ func (s *SQLLitePersistence) MarkBundleExpired(identity []byte) error {
|
|||
}
|
||||
|
||||
// GetPublicBundle retrieves an existing Bundle for the specified public key from the database
|
||||
func (s *SQLLitePersistence) GetPublicBundle(publicKey *ecdsa.PublicKey, installationIDs []string) (*Bundle, error) {
|
||||
func (s *SQLLitePersistence) GetPublicBundle(publicKey *ecdsa.PublicKey, installations []*Installation) (*Bundle, error) {
|
||||
|
||||
if len(installationIDs) == 0 {
|
||||
if len(installations) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
versions := make(map[string]uint32)
|
||||
identity := crypto.CompressPubkey(publicKey)
|
||||
|
||||
/* #nosec */
|
||||
statement := `SELECT signed_pre_key,installation_id, version
|
||||
FROM bundles
|
||||
WHERE expired = 0 AND identity = ? AND installation_id IN (?` + strings.Repeat(",?", len(installationIDs)-1) + `)
|
||||
WHERE expired = 0 AND identity = ? AND installation_id IN (?` + strings.Repeat(",?", len(installations)-1) + `)
|
||||
ORDER BY version DESC`
|
||||
stmt, err := s.db.Prepare(statement)
|
||||
if err != nil {
|
||||
|
@ -334,10 +343,12 @@ func (s *SQLLitePersistence) GetPublicBundle(publicKey *ecdsa.PublicKey, install
|
|||
}
|
||||
defer stmt.Close()
|
||||
|
||||
args := make([]interface{}, len(installationIDs)+1)
|
||||
args := make([]interface{}, len(installations)+1)
|
||||
args[0] = identity
|
||||
for i, installationID := range installationIDs {
|
||||
args[i+1] = installationID
|
||||
for i, installation := range installations {
|
||||
// Lookup up map for versions
|
||||
versions[installation.ID] = installation.Version
|
||||
args[i+1] = installation.ID
|
||||
}
|
||||
|
||||
rows, err := stmt.Query(args...)
|
||||
|
@ -369,8 +380,9 @@ func (s *SQLLitePersistence) GetPublicBundle(publicKey *ecdsa.PublicKey, install
|
|||
}
|
||||
|
||||
bundle.SignedPreKeys[installationID] = &SignedPreKey{
|
||||
SignedPreKey: signedPreKey,
|
||||
Version: version,
|
||||
SignedPreKey: signedPreKey,
|
||||
Version: version,
|
||||
ProtocolVersion: versions[installationID],
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -743,8 +755,8 @@ func (s *SQLLiteSessionStorage) Load(id []byte) (*dr.State, error) {
|
|||
}
|
||||
|
||||
// GetActiveInstallations returns the active installations for a given identity
|
||||
func (s *SQLLitePersistence) GetActiveInstallations(maxInstallations int, identity []byte) ([]string, error) {
|
||||
stmt, err := s.db.Prepare(`SELECT installation_id
|
||||
func (s *SQLLitePersistence) GetActiveInstallations(maxInstallations int, identity []byte) ([]*Installation, error) {
|
||||
stmt, err := s.db.Prepare(`SELECT installation_id, version
|
||||
FROM installations
|
||||
WHERE enabled = 1 AND identity = ?
|
||||
ORDER BY timestamp DESC
|
||||
|
@ -753,7 +765,7 @@ func (s *SQLLitePersistence) GetActiveInstallations(maxInstallations int, identi
|
|||
return nil, err
|
||||
}
|
||||
|
||||
var installations []string
|
||||
var installations []*Installation
|
||||
rows, err := stmt.Query(identity, maxInstallations)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -761,13 +773,19 @@ func (s *SQLLitePersistence) GetActiveInstallations(maxInstallations int, identi
|
|||
|
||||
for rows.Next() {
|
||||
var installationID string
|
||||
var version uint32
|
||||
err = rows.Scan(
|
||||
&installationID,
|
||||
&version,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
installations = append(installations, installationID)
|
||||
installations = append(installations, &Installation{
|
||||
ID: installationID,
|
||||
Version: version,
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
return installations, nil
|
||||
|
@ -775,14 +793,14 @@ func (s *SQLLitePersistence) GetActiveInstallations(maxInstallations int, identi
|
|||
}
|
||||
|
||||
// AddInstallations adds the installations for a given identity, maintaining the enabled flag
|
||||
func (s *SQLLitePersistence) AddInstallations(identity []byte, timestamp int64, installationIDs []string, defaultEnabled bool) error {
|
||||
func (s *SQLLitePersistence) AddInstallations(identity []byte, timestamp int64, installations []*Installation, defaultEnabled bool) error {
|
||||
tx, err := s.db.Begin()
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, installationID := range installationIDs {
|
||||
stmt, err := tx.Prepare(`SELECT enabled
|
||||
for _, installation := range installations {
|
||||
stmt, err := tx.Prepare(`SELECT enabled, version
|
||||
FROM installations
|
||||
WHERE identity = ? AND installation_id = ?
|
||||
LIMIT 1`)
|
||||
|
@ -792,16 +810,24 @@ func (s *SQLLitePersistence) AddInstallations(identity []byte, timestamp int64,
|
|||
defer stmt.Close()
|
||||
|
||||
var oldEnabled bool
|
||||
// We don't override version once we saw one
|
||||
var oldVersion uint32
|
||||
latestVersion := installation.Version
|
||||
|
||||
err = stmt.QueryRow(identity, installationID).Scan(&oldEnabled)
|
||||
err = stmt.QueryRow(identity, installation.ID).Scan(&oldEnabled, &oldVersion)
|
||||
if err != nil && err != sql.ErrNoRows {
|
||||
return err
|
||||
}
|
||||
|
||||
// We update timestamp if present without changing enabled, only if this is a new bundle
|
||||
// and we set the version to the latest we ever saw
|
||||
if err != sql.ErrNoRows {
|
||||
if oldVersion > installation.Version {
|
||||
latestVersion = oldVersion
|
||||
}
|
||||
|
||||
stmt, err = tx.Prepare(`UPDATE installations
|
||||
SET timestamp = ?, enabled = ?
|
||||
SET timestamp = ?, enabled = ?, version = ?
|
||||
WHERE identity = ?
|
||||
AND installation_id = ?
|
||||
AND timestamp < ?`)
|
||||
|
@ -812,8 +838,9 @@ func (s *SQLLitePersistence) AddInstallations(identity []byte, timestamp int64,
|
|||
_, err = stmt.Exec(
|
||||
timestamp,
|
||||
oldEnabled,
|
||||
latestVersion,
|
||||
identity,
|
||||
installationID,
|
||||
installation.ID,
|
||||
timestamp,
|
||||
)
|
||||
if err != nil {
|
||||
|
@ -822,17 +849,18 @@ func (s *SQLLitePersistence) AddInstallations(identity []byte, timestamp int64,
|
|||
defer stmt.Close()
|
||||
|
||||
} else {
|
||||
stmt, err = tx.Prepare(`INSERT INTO installations(identity, installation_id, timestamp, enabled)
|
||||
VALUES (?, ?, ?, ?)`)
|
||||
stmt, err = tx.Prepare(`INSERT INTO installations(identity, installation_id, timestamp, enabled, version)
|
||||
VALUES (?, ?, ?, ?, ?)`)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = stmt.Exec(
|
||||
identity,
|
||||
installationID,
|
||||
installation.ID,
|
||||
timestamp,
|
||||
defaultEnabled,
|
||||
latestVersion,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
|
@ -53,7 +53,7 @@ func (s *SQLLitePersistenceTestSuite) TestPrivateBundle() {
|
|||
s.Require().NoError(err, "Error was not returned even though bundle is not there")
|
||||
s.Nil(actualKey)
|
||||
|
||||
anyPrivateBundle, err := s.service.GetAnyPrivateBundle([]byte("non-existing-id"), []string{installationID})
|
||||
anyPrivateBundle, err := s.service.GetAnyPrivateBundle([]byte("non-existing-id"), []*Installation{{ID: installationID, Version: 1}})
|
||||
s.Require().NoError(err)
|
||||
s.Nil(anyPrivateBundle)
|
||||
|
||||
|
@ -70,7 +70,7 @@ func (s *SQLLitePersistenceTestSuite) TestPrivateBundle() {
|
|||
s.Equal(bundle.GetPrivateSignedPreKey(), actualKey, "It returns the same key")
|
||||
|
||||
identity := crypto.CompressPubkey(&key.PublicKey)
|
||||
anyPrivateBundle, err = s.service.GetAnyPrivateBundle(identity, []string{installationID})
|
||||
anyPrivateBundle, err = s.service.GetAnyPrivateBundle(identity, []*Installation{{ID: installationID, Version: 1}})
|
||||
s.Require().NoError(err)
|
||||
s.NotNil(anyPrivateBundle)
|
||||
s.Equal(bundle.GetBundle().GetSignedPreKeys()[installationID].SignedPreKey, anyPrivateBundle.GetBundle().GetSignedPreKeys()[installationID].SignedPreKey, "It returns the same bundle")
|
||||
|
@ -80,7 +80,7 @@ func (s *SQLLitePersistenceTestSuite) TestPublicBundle() {
|
|||
key, err := crypto.GenerateKey()
|
||||
s.Require().NoError(err)
|
||||
|
||||
actualBundle, err := s.service.GetPublicBundle(&key.PublicKey, []string{"1"})
|
||||
actualBundle, err := s.service.GetPublicBundle(&key.PublicKey, []*Installation{{ID: "1", Version: 1}})
|
||||
s.Require().NoError(err, "Error was not returned even though bundle is not there")
|
||||
s.Nil(actualBundle)
|
||||
|
||||
|
@ -91,7 +91,7 @@ func (s *SQLLitePersistenceTestSuite) TestPublicBundle() {
|
|||
err = s.service.AddPublicBundle(bundle)
|
||||
s.Require().NoError(err)
|
||||
|
||||
actualBundle, err = s.service.GetPublicBundle(&key.PublicKey, []string{"1"})
|
||||
actualBundle, err = s.service.GetPublicBundle(&key.PublicKey, []*Installation{{ID: "1", Version: 1}})
|
||||
s.Require().NoError(err)
|
||||
s.Equal(bundle.GetIdentity(), actualBundle.GetIdentity(), "It sets the right identity")
|
||||
s.Equal(bundle.GetSignedPreKeys(), actualBundle.GetSignedPreKeys(), "It sets the right prekeys")
|
||||
|
@ -101,7 +101,7 @@ func (s *SQLLitePersistenceTestSuite) TestUpdatedBundle() {
|
|||
key, err := crypto.GenerateKey()
|
||||
s.Require().NoError(err)
|
||||
|
||||
actualBundle, err := s.service.GetPublicBundle(&key.PublicKey, []string{"1"})
|
||||
actualBundle, err := s.service.GetPublicBundle(&key.PublicKey, []*Installation{{ID: "1", Version: 1}})
|
||||
s.Require().NoError(err, "Error was not returned even though bundle is not there")
|
||||
s.Nil(actualBundle)
|
||||
|
||||
|
@ -123,7 +123,7 @@ func (s *SQLLitePersistenceTestSuite) TestUpdatedBundle() {
|
|||
err = s.service.AddPublicBundle(bundle)
|
||||
s.Require().NoError(err)
|
||||
|
||||
actualBundle, err = s.service.GetPublicBundle(&key.PublicKey, []string{"1"})
|
||||
actualBundle, err = s.service.GetPublicBundle(&key.PublicKey, []*Installation{{ID: "1", Version: 1}})
|
||||
s.Require().NoError(err)
|
||||
s.Equal(bundle.GetIdentity(), actualBundle.GetIdentity(), "It sets the right identity")
|
||||
s.Equal(bundle.GetSignedPreKeys(), actualBundle.GetSignedPreKeys(), "It sets the right prekeys")
|
||||
|
@ -133,7 +133,7 @@ func (s *SQLLitePersistenceTestSuite) TestOutOfOrderBundles() {
|
|||
key, err := crypto.GenerateKey()
|
||||
s.Require().NoError(err)
|
||||
|
||||
actualBundle, err := s.service.GetPublicBundle(&key.PublicKey, []string{"1"})
|
||||
actualBundle, err := s.service.GetPublicBundle(&key.PublicKey, []*Installation{{ID: "1", Version: 1}})
|
||||
s.Require().NoError(err, "Error was not returned even though bundle is not there")
|
||||
s.Nil(actualBundle)
|
||||
|
||||
|
@ -160,7 +160,7 @@ func (s *SQLLitePersistenceTestSuite) TestOutOfOrderBundles() {
|
|||
err = s.service.AddPublicBundle(bundle1)
|
||||
s.Require().NoError(err)
|
||||
|
||||
actualBundle, err = s.service.GetPublicBundle(&key.PublicKey, []string{"1"})
|
||||
actualBundle, err = s.service.GetPublicBundle(&key.PublicKey, []*Installation{{ID: "1", Version: 1}})
|
||||
s.Require().NoError(err)
|
||||
s.Equal(bundle2.GetIdentity(), actualBundle.GetIdentity(), "It sets the right identity")
|
||||
s.Equal(bundle2.GetSignedPreKeys()["1"].GetVersion(), uint32(1))
|
||||
|
@ -171,7 +171,7 @@ func (s *SQLLitePersistenceTestSuite) TestMultiplePublicBundle() {
|
|||
key, err := crypto.GenerateKey()
|
||||
s.Require().NoError(err)
|
||||
|
||||
actualBundle, err := s.service.GetPublicBundle(&key.PublicKey, []string{"1"})
|
||||
actualBundle, err := s.service.GetPublicBundle(&key.PublicKey, []*Installation{{ID: "1", Version: 1}})
|
||||
s.Require().NoError(err, "Error was not returned even though bundle is not there")
|
||||
s.Nil(actualBundle)
|
||||
|
||||
|
@ -197,7 +197,7 @@ func (s *SQLLitePersistenceTestSuite) TestMultiplePublicBundle() {
|
|||
s.Require().NoError(err)
|
||||
|
||||
// Returns the most recent bundle
|
||||
actualBundle, err = s.service.GetPublicBundle(&key.PublicKey, []string{"1"})
|
||||
actualBundle, err = s.service.GetPublicBundle(&key.PublicKey, []*Installation{{ID: "1", Version: 1}})
|
||||
s.Require().NoError(err)
|
||||
|
||||
s.Equal(bundle.GetIdentity(), actualBundle.GetIdentity(), "It sets the identity")
|
||||
|
@ -209,7 +209,7 @@ func (s *SQLLitePersistenceTestSuite) TestMultiDevicePublicBundle() {
|
|||
key, err := crypto.GenerateKey()
|
||||
s.Require().NoError(err)
|
||||
|
||||
actualBundle, err := s.service.GetPublicBundle(&key.PublicKey, []string{"1"})
|
||||
actualBundle, err := s.service.GetPublicBundle(&key.PublicKey, []*Installation{{ID: "1", Version: 1}})
|
||||
s.Require().NoError(err, "Error was not returned even though bundle is not there")
|
||||
s.Nil(actualBundle)
|
||||
|
||||
|
@ -233,7 +233,11 @@ func (s *SQLLitePersistenceTestSuite) TestMultiDevicePublicBundle() {
|
|||
s.Require().NoError(err)
|
||||
|
||||
// Returns the most recent bundle
|
||||
actualBundle, err = s.service.GetPublicBundle(&key.PublicKey, []string{"1", "2"})
|
||||
actualBundle, err = s.service.GetPublicBundle(&key.PublicKey,
|
||||
[]*Installation{
|
||||
{ID: "1", Version: 1},
|
||||
{ID: "2", Version: 1},
|
||||
})
|
||||
s.Require().NoError(err)
|
||||
|
||||
s.Equal(bundle.GetIdentity(), actualBundle.GetIdentity(), "It sets the identity")
|
||||
|
@ -345,7 +349,10 @@ func (s *SQLLitePersistenceTestSuite) TestRatchetInfoNoBundle() {
|
|||
|
||||
func (s *SQLLitePersistenceTestSuite) TestAddInstallations() {
|
||||
identity := []byte("alice")
|
||||
installations := []string{"alice-1", "alice-2"}
|
||||
installations := []*Installation{
|
||||
{ID: "alice-1", Version: 1},
|
||||
{ID: "alice-2", Version: 2},
|
||||
}
|
||||
err := s.service.AddInstallations(
|
||||
identity,
|
||||
1,
|
||||
|
@ -361,10 +368,50 @@ func (s *SQLLitePersistenceTestSuite) TestAddInstallations() {
|
|||
s.Require().Equal(installations, enabledInstallations)
|
||||
}
|
||||
|
||||
func (s *SQLLitePersistenceTestSuite) TestAddInstallationVersions() {
|
||||
identity := []byte("alice")
|
||||
installations := []*Installation{
|
||||
{ID: "alice-1", Version: 1},
|
||||
}
|
||||
err := s.service.AddInstallations(
|
||||
identity,
|
||||
1,
|
||||
installations,
|
||||
true,
|
||||
)
|
||||
|
||||
s.Require().NoError(err)
|
||||
|
||||
enabledInstallations, err := s.service.GetActiveInstallations(5, identity)
|
||||
s.Require().NoError(err)
|
||||
|
||||
s.Require().Equal(installations, enabledInstallations)
|
||||
|
||||
installationsWithDowngradedVersion := []*Installation{
|
||||
{ID: "alice-1", Version: 0},
|
||||
}
|
||||
|
||||
err = s.service.AddInstallations(
|
||||
identity,
|
||||
3,
|
||||
installationsWithDowngradedVersion,
|
||||
true,
|
||||
)
|
||||
s.Require().NoError(err)
|
||||
|
||||
enabledInstallations, err = s.service.GetActiveInstallations(5, identity)
|
||||
s.Require().NoError(err)
|
||||
s.Require().Equal(installations, enabledInstallations)
|
||||
}
|
||||
|
||||
func (s *SQLLitePersistenceTestSuite) TestAddInstallationsLimit() {
|
||||
identity := []byte("alice")
|
||||
|
||||
installations := []string{"alice-1", "alice-2"}
|
||||
installations := []*Installation{
|
||||
{ID: "alice-1", Version: 1},
|
||||
{ID: "alice-2", Version: 2},
|
||||
}
|
||||
|
||||
err := s.service.AddInstallations(
|
||||
identity,
|
||||
1,
|
||||
|
@ -373,7 +420,11 @@ func (s *SQLLitePersistenceTestSuite) TestAddInstallationsLimit() {
|
|||
)
|
||||
s.Require().NoError(err)
|
||||
|
||||
installations = []string{"alice-2", "alice-3"}
|
||||
installations = []*Installation{
|
||||
{ID: "alice-1", Version: 1},
|
||||
{ID: "alice-3", Version: 3},
|
||||
}
|
||||
|
||||
err = s.service.AddInstallations(
|
||||
identity,
|
||||
2,
|
||||
|
@ -382,7 +433,12 @@ func (s *SQLLitePersistenceTestSuite) TestAddInstallationsLimit() {
|
|||
)
|
||||
s.Require().NoError(err)
|
||||
|
||||
installations = []string{"alice-2", "alice-3", "alice-4"}
|
||||
installations = []*Installation{
|
||||
{ID: "alice-2", Version: 2},
|
||||
{ID: "alice-3", Version: 3},
|
||||
{ID: "alice-4", Version: 4},
|
||||
}
|
||||
|
||||
err = s.service.AddInstallations(
|
||||
identity,
|
||||
3,
|
||||
|
@ -394,13 +450,17 @@ func (s *SQLLitePersistenceTestSuite) TestAddInstallationsLimit() {
|
|||
enabledInstallations, err := s.service.GetActiveInstallations(3, identity)
|
||||
s.Require().NoError(err)
|
||||
|
||||
s.Require().Equal([]string{"alice-2", "alice-3", "alice-4"}, enabledInstallations)
|
||||
s.Require().Equal(installations, enabledInstallations)
|
||||
}
|
||||
|
||||
func (s *SQLLitePersistenceTestSuite) TestAddInstallationsDisabled() {
|
||||
identity := []byte("alice")
|
||||
|
||||
installations := []string{"alice-1", "alice-2"}
|
||||
installations := []*Installation{
|
||||
{ID: "alice-1", Version: 1},
|
||||
{ID: "alice-2", Version: 2},
|
||||
}
|
||||
|
||||
err := s.service.AddInstallations(
|
||||
identity,
|
||||
1,
|
||||
|
@ -418,7 +478,11 @@ func (s *SQLLitePersistenceTestSuite) TestAddInstallationsDisabled() {
|
|||
func (s *SQLLitePersistenceTestSuite) TestDisableInstallation() {
|
||||
identity := []byte("alice")
|
||||
|
||||
installations := []string{"alice-1", "alice-2"}
|
||||
installations := []*Installation{
|
||||
{ID: "alice-1", Version: 1},
|
||||
{ID: "alice-2", Version: 2},
|
||||
}
|
||||
|
||||
err := s.service.AddInstallations(
|
||||
identity,
|
||||
1,
|
||||
|
@ -431,7 +495,11 @@ func (s *SQLLitePersistenceTestSuite) TestDisableInstallation() {
|
|||
s.Require().NoError(err)
|
||||
|
||||
// We add the installations again
|
||||
installations = []string{"alice-1", "alice-2"}
|
||||
installations = []*Installation{
|
||||
{ID: "alice-1", Version: 1},
|
||||
{ID: "alice-2", Version: 2},
|
||||
}
|
||||
|
||||
err = s.service.AddInstallations(
|
||||
identity,
|
||||
1,
|
||||
|
@ -443,13 +511,18 @@ func (s *SQLLitePersistenceTestSuite) TestDisableInstallation() {
|
|||
actualInstallations, err := s.service.GetActiveInstallations(3, identity)
|
||||
s.Require().NoError(err)
|
||||
|
||||
s.Require().Equal([]string{"alice-2"}, actualInstallations)
|
||||
expected := []*Installation{{ID: "alice-2", Version: 2}}
|
||||
s.Require().Equal(expected, actualInstallations)
|
||||
}
|
||||
|
||||
func (s *SQLLitePersistenceTestSuite) TestEnableInstallation() {
|
||||
identity := []byte("alice")
|
||||
|
||||
installations := []string{"alice-1", "alice-2"}
|
||||
installations := []*Installation{
|
||||
{ID: "alice-1", Version: 1},
|
||||
{ID: "alice-2", Version: 2},
|
||||
}
|
||||
|
||||
err := s.service.AddInstallations(
|
||||
identity,
|
||||
1,
|
||||
|
@ -464,7 +537,8 @@ func (s *SQLLitePersistenceTestSuite) TestEnableInstallation() {
|
|||
actualInstallations, err := s.service.GetActiveInstallations(3, identity)
|
||||
s.Require().NoError(err)
|
||||
|
||||
s.Require().Equal([]string{"alice-2"}, actualInstallations)
|
||||
expected := []*Installation{{ID: "alice-2", Version: 2}}
|
||||
s.Require().Equal(expected, actualInstallations)
|
||||
|
||||
err = s.service.EnableInstallation(identity, "alice-1")
|
||||
s.Require().NoError(err)
|
||||
|
@ -472,7 +546,11 @@ func (s *SQLLitePersistenceTestSuite) TestEnableInstallation() {
|
|||
actualInstallations, err = s.service.GetActiveInstallations(3, identity)
|
||||
s.Require().NoError(err)
|
||||
|
||||
s.Require().Equal([]string{"alice-1", "alice-2"}, actualInstallations)
|
||||
expected = []*Installation{
|
||||
{ID: "alice-1", Version: 1},
|
||||
{ID: "alice-2", Version: 2},
|
||||
}
|
||||
s.Require().Equal(expected, actualInstallations)
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -96,7 +96,10 @@ func NewBundleContainer(identity *ecdsa.PrivateKey, installationID string) (*Bun
|
|||
|
||||
encodedPreKey := crypto.FromECDSA(preKey)
|
||||
signedPreKeys := make(map[string]*SignedPreKey)
|
||||
signedPreKeys[installationID] = &SignedPreKey{SignedPreKey: compressedPreKey}
|
||||
signedPreKeys[installationID] = &SignedPreKey{
|
||||
ProtocolVersion: protocolCurrentVersion,
|
||||
SignedPreKey: compressedPreKey,
|
||||
}
|
||||
|
||||
bundle := Bundle{
|
||||
Timestamp: time.Now().UnixNano(),
|
||||
|
|
|
@ -37,10 +37,10 @@ func chatIDToPartitionedTopic(identity string) (string, error) {
|
|||
|
||||
partition.Mod(publicKey.X, nPartitions)
|
||||
|
||||
return fmt.Sprintf("contact-discovery-%d", partition), nil
|
||||
return fmt.Sprintf("contact-discovery-%d", partition.Int64()), nil
|
||||
}
|
||||
|
||||
type FilterAndTopic struct {
|
||||
type Filter struct {
|
||||
FilterID string
|
||||
Topic []byte
|
||||
SymKeyID string
|
||||
|
@ -143,7 +143,9 @@ func (s *Service) Init(chats []*Chat) error {
|
|||
}
|
||||
|
||||
for _, secret := range secrets {
|
||||
s.ProcessNegotiatedSecret(secret)
|
||||
if err := s.ProcessNegotiatedSecret(secret); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -215,7 +217,7 @@ func (s *Service) LoadOneToOne(myKey *ecdsa.PrivateKey, identity string, listen
|
|||
return nil
|
||||
}
|
||||
|
||||
func (s *Service) AddSymmetric(chatID string) (*FilterAndTopic, error) {
|
||||
func (s *Service) AddSymmetric(chatID string) (*Filter, error) {
|
||||
var symKey []byte
|
||||
|
||||
topic := toTopic(chatID)
|
||||
|
@ -244,14 +246,14 @@ func (s *Service) AddSymmetric(chatID string) (*FilterAndTopic, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
return &FilterAndTopic{
|
||||
return &Filter{
|
||||
FilterID: id,
|
||||
SymKeyID: symKeyID,
|
||||
Topic: topic,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *Service) AddAsymmetricFilter(keyAsym *ecdsa.PrivateKey, chatID string, listen bool) (*FilterAndTopic, error) {
|
||||
func (s *Service) AddAsymmetricFilter(keyAsym *ecdsa.PrivateKey, chatID string, listen bool) (*Filter, error) {
|
||||
var err error
|
||||
var pow float64
|
||||
|
||||
|
@ -278,7 +280,7 @@ func (s *Service) AddAsymmetricFilter(keyAsym *ecdsa.PrivateKey, chatID string,
|
|||
return nil, err
|
||||
}
|
||||
|
||||
return &FilterAndTopic{FilterID: id, Topic: topic}, nil
|
||||
return &Filter{FilterID: id, Topic: topic}, nil
|
||||
}
|
||||
|
||||
func (s *Service) LoadPublic(chat *Chat) error {
|
||||
|
|
|
@ -101,10 +101,10 @@ func (s *ServiceTestSuite) TestDiscoveryAndPartitionedTopic() {
|
|||
|
||||
func (s *ServiceTestSuite) TestPublicAndOneToOneChats() {
|
||||
chats := []*Chat{
|
||||
&Chat{
|
||||
{
|
||||
ChatID: "status",
|
||||
},
|
||||
&Chat{
|
||||
{
|
||||
ChatID: s.keys[1].PublicKeyString(),
|
||||
Identity: s.keys[1].PublicKeyString(),
|
||||
OneToOne: true,
|
||||
|
|
|
@ -308,7 +308,12 @@ func (s *Service) Stop() error {
|
|||
s.requestsRegistry.Clear()
|
||||
s.envelopesMonitor.Stop()
|
||||
s.mailMonitor.Stop()
|
||||
s.filter.Stop()
|
||||
if s.filter != nil {
|
||||
if err := s.filter.Stop(); err != nil {
|
||||
log.Error("Failed to stop filter service with error", "err", err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
ALTER TABLE installations ADD version INTEGER DEFAULT 0;
|
Loading…
Reference in New Issue