diff --git a/encryptoapi/routing/changes.go b/encryptoapi/routing/changes.go new file mode 100644 index 000000000..0ed33beb0 --- /dev/null +++ b/encryptoapi/routing/changes.go @@ -0,0 +1,55 @@ +// Copyright 2019 Sumukha PK +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package routing + +import ( + "net/http" + + "github.com/matrix-org/dendrite/encryptoapi/storage" + "github.com/matrix-org/dendrite/encryptoapi/types" + "github.com/matrix-org/util" +) + +// ChangesInKeys returns the changes in the keys after last sync +// each user maintains a chain of the changes when provided by FED +func ChangesInKeys( + req *http.Request, + encryptionDB *storage.Database, +) util.JSONResponse { + // assuming federation has added keys to the DB, + // extracting from the DB here + + // get from FED/Req + var readID int + var userID string + keyChanges, err := encryptionDB.GetKeyChanges(req.Context(), readID, userID) + if err != nil { + return util.JSONResponse{ + Code: http.StatusInternalServerError, + JSON: struct{}{}, + } + } + + changesRes := types.ChangesResponse{} + changesRes.Changed = keyChanges.Changed + changesRes.Left = keyChanges.Left + + // delete the extracted keys from the DB + + return util.JSONResponse{ + Code: http.StatusOK, + JSON: changesRes, + } +} diff --git a/encryptoapi/routing/claim.go b/encryptoapi/routing/claim.go new file mode 100644 index 000000000..6a280be67 --- /dev/null +++ b/encryptoapi/routing/claim.go @@ -0,0 +1,77 @@ +// Copyright 2019 Sumukha PK +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package routing + +import ( + "net/http" + "time" + + "github.com/matrix-org/dendrite/clientapi/httputil" + "github.com/matrix-org/dendrite/encryptoapi/storage" + "github.com/matrix-org/dendrite/encryptoapi/types" + "github.com/matrix-org/util" +) + +// ClaimOneTimeKeys enables user to claim one time keys for sessions. +func ClaimOneTimeKeys( + req *http.Request, + encryptionDB *storage.Database, +) util.JSONResponse { + var claimRq types.ClaimRequest + claimRes := types.ClaimResponse{} + claimRes.Failures = make(map[string]interface{}) + claimRes.OneTimeKeys = make(map[string]map[string]map[string]interface{}) + if reqErr := httputil.UnmarshalJSONRequest(req, &claimRq); reqErr != nil { + return *reqErr + } + + var obtainedFromFed types.QueryResponse + obtainedKeysFromFed := obtainedFromFed.DeviceKeys + claimRes.OneTimeKeys = obtainedKeysFromFed + + // not sure what FED should return here + /* + federation consideration: when user id is in federation, a query is needed to ask fed for keys + domain --------+ fed (keys) + domain +--tout-- timer + */ + // todo: Add federation processing at specific userID. + if false /*federation judgement*/ { + tout := claimRq.Timeout + stimuCh := make(chan int) + go func() { + time.Sleep(time.Duration(tout) * 1000 * 1000) + close(stimuCh) + }() + select { + case <-stimuCh: + claimRes.Failures = make(map[string]interface{}) + // todo: key in this map is restricted to username at the end, yet a mocked one. + claimRes.Failures["@alice:localhost"] = "ran out of offered time" + case <-make(chan interface{}): + // todo : here goes federation chan , still a mocked one + } + // probably some other better error to tell it timed out in FED + return util.JSONResponse{ + Code: http.StatusInternalServerError, + JSON: struct{}{}, + } + } + + return util.JSONResponse{ + Code: http.StatusOK, + JSON: claimRes, + } +} diff --git a/encryptoapi/routing/keys.go b/encryptoapi/routing/keys.go index 9aced0d6e..82c1227d8 100644 --- a/encryptoapi/routing/keys.go +++ b/encryptoapi/routing/keys.go @@ -1,4 +1,4 @@ -// Copyright 2018 Vector Creations Ltd +// Copyright 2019 Sumukha PK // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -15,21 +15,8 @@ package routing import ( - "context" - "encoding/json" - "fmt" - "net/http" - "strings" - "time" - "github.com/Shopify/sarama" - "github.com/matrix-org/dendrite/clientapi/auth/storage/devices" - "github.com/matrix-org/dendrite/clientapi/httputil" "github.com/matrix-org/dendrite/common/basecomponent" - "github.com/matrix-org/dendrite/encryptoapi/storage" - "github.com/matrix-org/dendrite/encryptoapi/types" - "github.com/matrix-org/util" - "github.com/pkg/errors" ) const ( @@ -59,406 +46,13 @@ type KeyNotifier struct { var keyProducer = &KeyNotifier{} -// UploadPKeys enables the user to upload his device -// and one time keys with limit at 50 set as default -func UploadPKeys( - req *http.Request, - encryptionDB *storage.Database, - userID, deviceID string, -) util.JSONResponse { - var keybody types.UploadEncrypt - if reqErr := httputil.UnmarshalJSONRequest(req, &keybody); reqErr != nil { - return *reqErr - } - keySpecific := turnSpecific(keybody) - // persist keys into encryptionDB - err := persistKeys( - req.Context(), - encryptionDB, - &keySpecific, - userID, deviceID) - // numMap is algorithm-num map - // this gets the number of unclaimed OTkeys - numMap, ok := (queryOneTimeKeys( - req.Context(), - TYPESUM, - userID, - deviceID, - encryptionDB)).(map[string]int) - if !ok { - return util.JSONResponse{ - Code: http.StatusInternalServerError, - JSON: struct{}{}, - } - } - if err != nil { - return util.JSONResponse{ - Code: http.StatusBadGateway, - JSON: types.UploadResponse{ - Count: numMap, - }, - } - } - return util.JSONResponse{ - Code: http.StatusOK, - JSON: types.UploadResponse{ - Count: numMap, - }, - } -} - -// QueryPKeys returns the public identity keys -// and supported algorithms of "intended user" -// This just forwards the request to the Federation, -// and waits/checks for timeouts and failures. Response -// of the FedSenderAPI is bundled with the failures and returned. -func QueryPKeys( - req *http.Request, - encryptionDB *storage.Database, - deviceID string, - deviceDB *devices.Database, -) util.JSONResponse { - var err error - var queryRq types.QueryRequest - if reqErr := httputil.UnmarshalJSONRequest(req, &queryRq); reqErr != nil { - return *reqErr - } - queryRp := types.QueryResponse{} - - // sendDKToFed := queryRq.DeviceKeys - - var obtainedFromFed types.QueryResponse - obtainedKeysFromFed := obtainedFromFed.DeviceKeys - queryRp.DeviceKeys = obtainedKeysFromFed - - queryRp.Failure = make(map[string]interface{}) - // FED must return the keys from the other user - /* - federation consideration: when user id is in federation, a - query is needed to ask fed for keys. - domain --------+ fed (keys) - domain +--tout-- timer - */ - // todo: Add federation processing at specific userID. - if false /*federation judgement*/ { - tout := queryRq.Timeout - if tout == 0 { - tout = int64(10 * time.Second) - } - stimuCh := make(chan int) - go func() { - time.Sleep(time.Duration(tout) * 1000 * 1000) - close(stimuCh) - }() - select { - case <-stimuCh: - queryRp.Failure = make(map[string]interface{}) - // todo: key in this map is restricted to username at the end, yet a mocked one. - queryRp.Failure["@alice:localhost"] = "ran out of offered time" - case <-make(chan interface{}): - // todo : here goes federation chan , still a mocked one - } - // probably some other better error to tell it timed out in FED - return util.JSONResponse{ - Code: http.StatusInternalServerError, - JSON: struct{}{}, - } - } - - // - // - // - // - // Forward the request to the federation server and get the required info - - return util.JSONResponse{ - Code: http.StatusOK, - JSON: queryRp, - } -} - -// ClaimOneTimeKeys enables user to claim one time keys for sessions. -func ClaimOneTimeKeys( - req *http.Request, - encryptionDB *storage.Database, -) util.JSONResponse { - var claimRq types.ClaimRequest - claimRes := types.ClaimResponse{} - claimRes.Failures = make(map[string]interface{}) - claimRes.OneTimeKeys = make(map[string]map[string]map[string]interface{}) - if reqErr := httputil.UnmarshalJSONRequest(req, &claimRq); reqErr != nil { - return *reqErr - } - - var obtainedFromFed types.QueryResponse - obtainedKeysFromFed := obtainedFromFed.DeviceKeys - claimRes.OneTimeKeys = obtainedKeysFromFed - - // not sure what FED should return here - /* - federation consideration: when user id is in federation, a query is needed to ask fed for keys - domain --------+ fed (keys) - domain +--tout-- timer - */ - // todo: Add federation processing at specific userID. - if false /*federation judgement*/ { - tout := claimRq.Timeout - stimuCh := make(chan int) - go func() { - time.Sleep(time.Duration(tout) * 1000 * 1000) - close(stimuCh) - }() - select { - case <-stimuCh: - claimRes.Failures = make(map[string]interface{}) - // todo: key in this map is restricted to username at the end, yet a mocked one. - claimRes.Failures["@alice:localhost"] = "ran out of offered time" - case <-make(chan interface{}): - // todo : here goes federation chan , still a mocked one - } - // probably some other better error to tell it timed out in FED - return util.JSONResponse{ - Code: http.StatusInternalServerError, - JSON: struct{}{}, - } - } - - return util.JSONResponse{ - Code: http.StatusOK, - JSON: claimRes, - } -} - -// ChangesInKeys returns the changes in the keys after last sync -// each user maintains a chain of the changes when provided by FED -func ChangesInKeys( - req *http.Request, - encryptionDB *storage.Database, -) util.JSONResponse { - // assuming federation has added keys to the DB, - // extracting from the DB here - - // get from FED/Req - var readID int - var userID string - keyChanges, err := encryptionDB.GetKeyChanges(req.Context(), readID, userID) - if err != nil { - return util.JSONResponse{ - Code: http.StatusInternalServerError, - JSON: struct{}{}, - } - } - - changesRes := types.ChangesResponse{} - changesRes.Changed = keyChanges.Changed - changesRes.Left = keyChanges.Left - - // delete the extracted keys from the DB - - return util.JSONResponse{ - Code: http.StatusOK, - JSON: changesRes, - } -} - -// todo: check through interface for duplicate and what type of request should it be -// whether device or one time or both of them -func checkUpload(req *types.UploadEncryptSpecific, typ int) bool { - if typ == BODYDEVICEKEY { - devicekey := req.DeviceKeys - if devicekey.UserID == "" { - return false - } - } - if typ == BODYONETIMEKEY { - if req.OneTimeKey.KeyString == nil || req.OneTimeKey.KeyObject == nil { - return false - } - } - return true -} - -// queryOneTimeKeys todo: complete this field through claim type -func queryOneTimeKeys( - ctx context.Context, - typ int, - userID, deviceID string, - encryptionDB *storage.Database, -) interface{} { - if typ == TYPESUM { - res, _ := encryptionDB.SelectOneTimeKeyCount(ctx, deviceID, userID) - return res - } - return nil -} - // ClearUnused when web client sign out, a clean should be processed, cause all keys would never been used from then on. // todo: complete this function and invoke through sign out extension or some scenarios else those matter func ClearUnused() {} -// persist both device keys and one time keys -func persistKeys( - ctx context.Context, - database *storage.Database, - body *types.UploadEncryptSpecific, - userID, - deviceID string, -) (err error) { - // in order to persist keys , a check, - // filtering the duplicates should be processed. - // true stands for counterparts are in request - // situation 1: only device keys - // situation 2: both device keys and one time keys - // situation 3: only one time keys - if checkUpload(body, BODYDEVICEKEY) { - deviceKeys := body.DeviceKeys - al := deviceKeys.Algorithm - err = persistAl(ctx, *database, userID, deviceID, al) - if err != nil { - return - } - if checkUpload(body, BODYONETIMEKEY) { - if err = persistBothKeys(ctx, body, userID, deviceID, database, deviceKeys); err != nil { - return - } - } else { - if err = persistDeviceKeys(ctx, userID, deviceID, database, deviceKeys); err != nil { - return - } - } - // notifier to sync server - upnotify(userID) - } else { - if checkUpload(body, BODYONETIMEKEY) { - if err = persistOneTimeKeys(ctx, body, userID, deviceID, database); err != nil { - return - } - } else { - return errors.New("failed to persist keys") - } - } - return err -} - -// make keys instantiated to specific struct from keybody interface{} -func turnSpecific( - cont types.UploadEncrypt, -) (spec types.UploadEncryptSpecific) { - // both device keys are coordinate - spec.DeviceKeys = cont.DeviceKeys - spec.OneTimeKey.KeyString = make(map[string]string) - spec.OneTimeKey.KeyObject = make(map[string]types.KeyObject) - mapStringInterface := cont.OneTimeKey - for key, val := range mapStringInterface { - value, ok := val.(string) - if ok { - spec.OneTimeKey.KeyString[key] = value - } else { - valueObject := types.KeyObject{} - target, _ := json.Marshal(val) - err := json.Unmarshal(target, &valueObject) - if err != nil { - continue - } - spec.OneTimeKey.KeyObject[key] = valueObject - } - } - return -} - -func persistAl( - ctx context.Context, - encryptDB storage.Database, - uid, device string, - al []string, -) (err error) { - err = encryptDB.InsertAl(ctx, uid, device, al) - return -} - -func upnotify(userID string) { - m := sarama.ProducerMessage{ - Topic: "keyUpdate", - Key: sarama.StringEncoder("key"), - Value: sarama.StringEncoder(userID), - } - keyProducer.ch.Input() <- &m -} - // InitNotifier initialize kafka notifier func InitNotifier(base *basecomponent.BaseDendrite) { keyProducer.base = base pro, _ := sarama.NewAsyncProducer(base.Cfg.Kafka.Addresses, nil) keyProducer.ch = pro } - -func persistBothKeys( - ctx context.Context, - body *types.UploadEncryptSpecific, - userID, deviceID string, - database *storage.Database, - deviceKeys types.DeviceKeys, -) (err error) { - // insert one time keys - err = persistOneTimeKeys(ctx, body, userID, deviceID, database) - if err != nil { - return - } - // insert device keys - err = persistDeviceKeys(ctx, userID, deviceID, database, deviceKeys) - if err != nil { - return - } - return -} - -func persistDeviceKeys( - ctx context.Context, - userID, deviceID string, - database *storage.Database, - deviceKeys types.DeviceKeys, -) (err error) { - keys := deviceKeys.Keys - sigs := deviceKeys.Signature - for alDevice, key := range keys { - al := (strings.Split(alDevice, ":"))[0] - keyTyp := DEVICEKEYSTR - keyInfo := key - keyID := "" - sig := sigs[userID][fmt.Sprintf("%s:%s", "ed25519", deviceID)] - err = database.InsertKey(ctx, deviceID, userID, keyID, keyTyp, keyInfo, al, sig) - } - return -} - -func persistOneTimeKeys( - ctx context.Context, - body *types.UploadEncryptSpecific, - userID, deviceID string, - database *storage.Database, -) (err error) { - onetimeKeys := body.OneTimeKey - for alKeyID, val := range onetimeKeys.KeyString { - al := (strings.Split(alKeyID, ":"))[0] - keyID := (strings.Split(alKeyID, ":"))[1] - keyInfo := val - oneTimeKeyStringTyp := ONETIMEKEYSTR - sig := "" - err = database.InsertKey(ctx, deviceID, userID, keyID, oneTimeKeyStringTyp, keyInfo, al, sig) - if err != nil { - return - } - } - for alKeyID, val := range onetimeKeys.KeyObject { - al := (strings.Split(alKeyID, ":"))[0] - keyID := (strings.Split(alKeyID, ":"))[1] - keyInfo := val.Key - oneTimeKeyObjectTyp := ONETIMEKEYSTR - sig := val.Signature[userID][fmt.Sprintf("%s:%s", "ed25519", deviceID)] - err = database.InsertKey(ctx, deviceID, userID, keyID, oneTimeKeyObjectTyp, keyInfo, al, sig) - if err != nil { - return - } - } - return -} diff --git a/encryptoapi/routing/query.go b/encryptoapi/routing/query.go new file mode 100644 index 000000000..e235d75a6 --- /dev/null +++ b/encryptoapi/routing/query.go @@ -0,0 +1,96 @@ +// Copyright 2019 Sumukha PK +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package routing + +import ( + "net/http" + "time" + + "github.com/matrix-org/dendrite/clientapi/auth/storage/devices" + "github.com/matrix-org/dendrite/clientapi/httputil" + "github.com/matrix-org/dendrite/encryptoapi/storage" + "github.com/matrix-org/dendrite/encryptoapi/types" + "github.com/matrix-org/util" +) + +// QueryPKeys returns the public identity keys +// and supported algorithms of "intended user" +// This just forwards the request to the Federation, +// and waits/checks for timeouts and failures. Response +// of the FedSenderAPI is bundled with the failures and returned. +func QueryPKeys( + req *http.Request, + encryptionDB *storage.Database, + deviceID string, + deviceDB *devices.Database, +) util.JSONResponse { + var err error + var queryRq types.QueryRequest + if reqErr := httputil.UnmarshalJSONRequest(req, &queryRq); reqErr != nil { + return *reqErr + } + queryRp := types.QueryResponse{} + + // sendDKToFed := queryRq.DeviceKeys + + var obtainedFromFed types.QueryResponse + obtainedKeysFromFed := obtainedFromFed.DeviceKeys + queryRp.DeviceKeys = obtainedKeysFromFed + + queryRp.Failure = make(map[string]interface{}) + // FED must return the keys from the other user + /* + federation consideration: when user id is in federation, a + query is needed to ask fed for keys. + domain --------+ fed (keys) + domain +--tout-- timer + */ + // todo: Add federation processing at specific userID. + if false /*federation judgement*/ { + tout := queryRq.Timeout + if tout == 0 { + tout = int64(10 * time.Second) + } + stimuCh := make(chan int) + go func() { + time.Sleep(time.Duration(tout) * 1000 * 1000) + close(stimuCh) + }() + select { + case <-stimuCh: + queryRp.Failure = make(map[string]interface{}) + // todo: key in this map is restricted to username at the end, yet a mocked one. + queryRp.Failure["@alice:localhost"] = "ran out of offered time" + case <-make(chan interface{}): + // todo : here goes federation chan , still a mocked one + } + // probably some other better error to tell it timed out in FED + return util.JSONResponse{ + Code: http.StatusInternalServerError, + JSON: struct{}{}, + } + } + + // + // + // + // + // Forward the request to the federation server and get the required info + + return util.JSONResponse{ + Code: http.StatusOK, + JSON: queryRp, + } +} diff --git a/encryptoapi/routing/upload.go b/encryptoapi/routing/upload.go new file mode 100644 index 000000000..9b7493032 --- /dev/null +++ b/encryptoapi/routing/upload.go @@ -0,0 +1,269 @@ +// Copyright 2019 Sumukha PK +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package routing + +import ( + "context" + "encoding/json" + "fmt" + "net/http" + "strings" + + "github.com/Shopify/sarama" + "github.com/matrix-org/dendrite/clientapi/httputil" + "github.com/matrix-org/dendrite/encryptoapi/storage" + "github.com/matrix-org/dendrite/encryptoapi/types" + "github.com/matrix-org/util" + "github.com/pkg/errors" +) + +// UploadPKeys enables the user to upload his device +// and one time keys with limit at 50 set as default +func UploadPKeys( + req *http.Request, + encryptionDB *storage.Database, + userID, deviceID string, +) util.JSONResponse { + var keybody types.UploadEncrypt + if reqErr := httputil.UnmarshalJSONRequest(req, &keybody); reqErr != nil { + return *reqErr + } + keySpecific := turnSpecific(keybody) + // persist keys into encryptionDB + err := persistKeys( + req.Context(), + encryptionDB, + &keySpecific, + userID, deviceID) + // numMap is algorithm-num map + // this gets the number of unclaimed OTkeys + numMap, ok := (queryOneTimeKeys( + req.Context(), + TYPESUM, + userID, + deviceID, + encryptionDB)).(map[string]int) + if !ok { + return util.JSONResponse{ + Code: http.StatusInternalServerError, + JSON: struct{}{}, + } + } + if err != nil { + return util.JSONResponse{ + Code: http.StatusBadGateway, + JSON: types.UploadResponse{ + Count: numMap, + }, + } + } + return util.JSONResponse{ + Code: http.StatusOK, + JSON: types.UploadResponse{ + Count: numMap, + }, + } +} + +// make keys instantiated to specific struct from keybody interface{} +func turnSpecific( + cont types.UploadEncrypt, +) (spec types.UploadEncryptSpecific) { + // both device keys are coordinate + spec.DeviceKeys = cont.DeviceKeys + spec.OneTimeKey.KeyString = make(map[string]string) + spec.OneTimeKey.KeyObject = make(map[string]types.KeyObject) + mapStringInterface := cont.OneTimeKey + for key, val := range mapStringInterface { + value, ok := val.(string) + if ok { + spec.OneTimeKey.KeyString[key] = value + } else { + valueObject := types.KeyObject{} + target, _ := json.Marshal(val) + err := json.Unmarshal(target, &valueObject) + if err != nil { + continue + } + spec.OneTimeKey.KeyObject[key] = valueObject + } + } + return +} + +// persist both device keys and one time keys +func persistKeys( + ctx context.Context, + database *storage.Database, + body *types.UploadEncryptSpecific, + userID, + deviceID string, +) (err error) { + // in order to persist keys , a check, + // filtering the duplicates should be processed. + // true stands for counterparts are in request + // situation 1: only device keys + // situation 2: both device keys and one time keys + // situation 3: only one time keys + if checkUpload(body, BODYDEVICEKEY) { + deviceKeys := body.DeviceKeys + al := deviceKeys.Algorithm + err = persistAlgo(ctx, *database, userID, deviceID, al) + if err != nil { + return + } + if checkUpload(body, BODYONETIMEKEY) { + if err = persistBothKeys(ctx, body, userID, deviceID, database, deviceKeys); err != nil { + return + } + } else { + if err = persistDeviceKeys(ctx, userID, deviceID, database, deviceKeys); err != nil { + return + } + } + // notifier to sync server + upnotify(userID) + } else { + if checkUpload(body, BODYONETIMEKEY) { + if err = persistOneTimeKeys(ctx, body, userID, deviceID, database); err != nil { + return + } + } else { + return errors.New("failed to persist keys") + } + } + return err +} + +// todo: check through interface for duplicate and what type of request should it be +// whether device or one time or both of them +func checkUpload(req *types.UploadEncryptSpecific, typ int) bool { + if typ == BODYDEVICEKEY { + devicekey := req.DeviceKeys + if devicekey.UserID == "" { + return false + } + } + if typ == BODYONETIMEKEY { + if req.OneTimeKey.KeyString == nil || req.OneTimeKey.KeyObject == nil { + return false + } + } + return true +} + +func persistAlgo( + ctx context.Context, + encryptDB storage.Database, + uid, device string, + al []string, +) (err error) { + err = encryptDB.InsertAl(ctx, uid, device, al) + return +} + +// queryOneTimeKeys todo: complete this field through claim type +func queryOneTimeKeys( + ctx context.Context, + typ int, + userID, deviceID string, + encryptionDB *storage.Database, +) interface{} { + if typ == TYPESUM { + res, _ := encryptionDB.SelectOneTimeKeyCount(ctx, deviceID, userID) + return res + } + return nil +} + +func upnotify(userID string) { + m := sarama.ProducerMessage{ + Topic: "keyUpdate", + Key: sarama.StringEncoder("key"), + Value: sarama.StringEncoder(userID), + } + keyProducer.ch.Input() <- &m +} + +func persistBothKeys( + ctx context.Context, + body *types.UploadEncryptSpecific, + userID, deviceID string, + database *storage.Database, + deviceKeys types.DeviceKeys, +) (err error) { + // insert one time keys + err = persistOneTimeKeys(ctx, body, userID, deviceID, database) + if err != nil { + return + } + // insert device keys + err = persistDeviceKeys(ctx, userID, deviceID, database, deviceKeys) + if err != nil { + return + } + return +} + +func persistDeviceKeys( + ctx context.Context, + userID, deviceID string, + database *storage.Database, + deviceKeys types.DeviceKeys, +) (err error) { + keys := deviceKeys.Keys + sigs := deviceKeys.Signature + for alDevice, key := range keys { + al := (strings.Split(alDevice, ":"))[0] + keyTyp := DEVICEKEYSTR + keyInfo := key + keyID := "" + sig := sigs[userID][fmt.Sprintf("%s:%s", "ed25519", deviceID)] + err = database.InsertKey(ctx, deviceID, userID, keyID, keyTyp, keyInfo, al, sig) + } + return +} + +func persistOneTimeKeys( + ctx context.Context, + body *types.UploadEncryptSpecific, + userID, deviceID string, + database *storage.Database, +) (err error) { + onetimeKeys := body.OneTimeKey + for alKeyID, val := range onetimeKeys.KeyString { + al := (strings.Split(alKeyID, ":"))[0] + keyID := (strings.Split(alKeyID, ":"))[1] + keyInfo := val + oneTimeKeyStringTyp := ONETIMEKEYSTR + sig := "" + err = database.InsertKey(ctx, deviceID, userID, keyID, oneTimeKeyStringTyp, keyInfo, al, sig) + if err != nil { + return + } + } + for alKeyID, val := range onetimeKeys.KeyObject { + al := (strings.Split(alKeyID, ":"))[0] + keyID := (strings.Split(alKeyID, ":"))[1] + keyInfo := val.Key + oneTimeKeyObjectTyp := ONETIMEKEYSTR + sig := val.Signature[userID][fmt.Sprintf("%s:%s", "ed25519", deviceID)] + err = database.InsertKey(ctx, deviceID, userID, keyID, oneTimeKeyObjectTyp, keyInfo, al, sig) + if err != nil { + return + } + } + return +} diff --git a/encryptoapi/storage/storage.go b/encryptoapi/storage/storage.go index bfc1172d8..8898e6f2c 100644 --- a/encryptoapi/storage/storage.go +++ b/encryptoapi/storage/storage.go @@ -1,4 +1,4 @@ -// Copyright 2018 Vector Creations Ltd +// Copyright 2019 Sumukha PK // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/encryptoapi/types/claim.go b/encryptoapi/types/claim.go index b2ac69578..cecdc0869 100644 --- a/encryptoapi/types/claim.go +++ b/encryptoapi/types/claim.go @@ -1,4 +1,4 @@ -// Copyright 2018 Vector Creations Ltd +// Copyright 2019 Sumukha PK // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/encryptoapi/types/upload.go b/encryptoapi/types/upload.go index d30f0719f..36acacabc 100644 --- a/encryptoapi/types/upload.go +++ b/encryptoapi/types/upload.go @@ -1,4 +1,4 @@ -// Copyright 2018 Vector Creations Ltd +// Copyright 2019 Sumukha PK // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License.