diff --git a/src/github.com/matrix-org/dendrite/cmd/dendrite-monolith-server/main.go b/src/github.com/matrix-org/dendrite/cmd/dendrite-monolith-server/main.go index 301de9c9b..e0433d748 100644 --- a/src/github.com/matrix-org/dendrite/cmd/dendrite-monolith-server/main.go +++ b/src/github.com/matrix-org/dendrite/cmd/dendrite-monolith-server/main.go @@ -32,9 +32,9 @@ import ( "github.com/matrix-org/dendrite/roomserver" "github.com/matrix-org/dendrite/syncapi" + "github.com/matrix-org/dendrite/encryptoapi" "github.com/prometheus/client_golang/prometheus/promhttp" "github.com/sirupsen/logrus" - "github.com/matrix-org/dendrite/encryptoapi" ) var ( @@ -57,7 +57,7 @@ func main() { alias, input, query := roomserver.SetupRoomServerComponent(base) - encryptoapi.SetupEcryptoapi(base, accountDB, deviceDB) + encryptoapi.SetupEcryptoapi(base, deviceDB) clientapi.SetupClientAPIComponent( base, deviceDB, accountDB, diff --git a/src/github.com/matrix-org/dendrite/encryptoapi/encryptoapi.go b/src/github.com/matrix-org/dendrite/encryptoapi/encryptoapi.go index e391ecc12..d4529a27c 100644 --- a/src/github.com/matrix-org/dendrite/encryptoapi/encryptoapi.go +++ b/src/github.com/matrix-org/dendrite/encryptoapi/encryptoapi.go @@ -15,10 +15,9 @@ package encryptoapi import ( - "github.com/matrix-org/dendrite/common/basecomponent" - "github.com/matrix-org/dendrite/clientapi/auth/storage/accounts" - "github.com/matrix-org/dendrite/encryptoapi/routing" "github.com/matrix-org/dendrite/clientapi/auth/storage/devices" + "github.com/matrix-org/dendrite/common/basecomponent" + "github.com/matrix-org/dendrite/encryptoapi/routing" "github.com/matrix-org/dendrite/encryptoapi/storage" "github.com/sirupsen/logrus" ) @@ -27,9 +26,10 @@ import ( // , CMD should involve this invoke into main function // , a setup need an assemble of i.e configs as base and // accountDB and deviceDB + +// SetupEcryptoapi set up to servers func SetupEcryptoapi( base *basecomponent.BaseDendrite, - accountsDB *accounts.Database, deviceDB *devices.Database, ) { encryptionDB, err := storage.NewDatabase(string(base.Cfg.Database.EncryptAPI)) @@ -38,9 +38,7 @@ func SetupEcryptoapi( } routing.Setup( base.APIMux, - *base.Cfg, encryptionDB, - accountsDB, deviceDB, ) routing.InitNotifier(base) diff --git a/src/github.com/matrix-org/dendrite/encryptoapi/routing/keys.go b/src/github.com/matrix-org/dendrite/encryptoapi/routing/keys.go index 6a1889219..60a8bfa41 100644 --- a/src/github.com/matrix-org/dendrite/encryptoapi/routing/keys.go +++ b/src/github.com/matrix-org/dendrite/encryptoapi/routing/keys.go @@ -15,33 +15,43 @@ package routing import ( - "github.com/matrix-org/util" - "github.com/matrix-org/dendrite/encryptoapi/storage" - "net/http" - "github.com/matrix-org/dendrite/clientapi/httputil" - "github.com/matrix-org/dendrite/encryptoapi/types" "context" - "github.com/pkg/errors" - "strings" - "fmt" "encoding/json" - "time" - "github.com/matrix-org/dendrite/clientapi/auth/storage/devices" - "github.com/matrix-org/gomatrixserverlib" - "github.com/matrix-org/dendrite/common/basecomponent" + "fmt" "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/gomatrixserverlib" + "github.com/matrix-org/util" + "github.com/pkg/errors" + "net/http" + "strings" + "time" ) const ( - TYPESUM = iota - TYPECLAIM - TYPEVAL + // TYPESUM sum type + TYPESUM = iota + // BODYDEVICEKEY device key body BODYDEVICEKEY + // BODYONETIMEKEY one time key BODYONETIMEKEY + // ONETIMEKEYSTRING key string ONETIMEKEYSTRING + // ONETIMEKEYOBJECT key object ONETIMEKEYOBJECT ) +// ONETIMEKEYSTR stands for storage string property +const ONETIMEKEYSTR = "one_time_key" + +// DEVICEKEYSTR stands for storage string property +const DEVICEKEYSTR = "device_key" + +// KeyNotifier kafka notifier type KeyNotifier struct { base *basecomponent.BaseDendrite ch sarama.AsyncProducer @@ -49,32 +59,30 @@ type KeyNotifier struct { var keyProducer = &KeyNotifier{} -// this function is for user upload his device key, and one-time-key -// to a limit at 50 set as default +// UploadPKeys this function is for user upload his device key, and one-time-key to a 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 { + if reqErr := httputil.UnmarshalJSONRequest(req, &keybody); reqErr != nil { return *reqErr } keySpecific := turnSpecific(keybody) // persist keys into encryptionDB err := persistKeys( - encryptionDB, req.Context(), + encryptionDB, &keySpecific, userID, deviceID) // numMap is algorithm-num map numMap := (QueryOneTimeKeys( + req.Context(), TYPESUM, userID, deviceID, - encryptionDB, - req.Context())).(map[string]int) + encryptionDB)).(map[string]int) if err != nil { return util.JSONResponse{ Code: http.StatusBadGateway, @@ -91,19 +99,19 @@ func UploadPKeys( } } -// this function is for user query other's device key +// QueryPKeys this function is for user query other's device key func QueryPKeys( req *http.Request, encryptionDB *storage.Database, - userID, deviceID string, + deviceID string, deviceDB *devices.Database, ) util.JSONResponse { + var err error var queryRq types.QueryRequest queryRp := types.QueryResponse{} queryRp.Failure = make(map[string]interface{}) queryRp.DeviceKeys = make(map[string]map[string]types.DeviceKeysQuery) - if reqErr := httputil.UnmarshalJSONRequest(req, &queryRq); - reqErr != nil { + if reqErr := httputil.UnmarshalJSONRequest(req, &queryRq); reqErr != nil { return *reqErr } @@ -129,6 +137,8 @@ func QueryPKeys( 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 } } @@ -139,50 +149,35 @@ func QueryPKeys( // backward compatible to old interface midArr := []string{} // figure out device list from devices described as device which is actually deviceID - for device, _ := range arr.(map[string]interface{}) { + for device := range arr.(map[string]interface{}) { midArr = append(midArr, device) } // all device keys dkeys, _ := encryptionDB.QueryInRange(req.Context(), uid, midArr) // build response for them - for _, key := range dkeys { - // preset for complicated nested map struct - if _, ok := deviceKeysQueryMap[key.Device_id]; !ok { - // make consistency - deviceKeysQueryMap[key.Device_id] = types.DeviceKeysQuery{} - } - if deviceKeysQueryMap[key.Device_id].Signature == nil { - mid := make(map[string]map[string]string) - midmap := deviceKeysQueryMap[key.Device_id] - midmap.Signature = mid - deviceKeysQueryMap[key.Device_id] = midmap - } - if deviceKeysQueryMap[key.Device_id].Keys == nil { - mid := make(map[string]string) - midmap := deviceKeysQueryMap[key.Device_id] - midmap.Keys = mid - deviceKeysQueryMap[key.Device_id] = midmap - } - if _, ok := deviceKeysQueryMap[key.Device_id].Signature[uid]; !ok { - // make consistency - deviceKeysQueryMap[key.Device_id].Signature[uid] = make(map[string]string) - } - // load for accomplishment - single := deviceKeysQueryMap[key.Device_id] - resKey := fmt.Sprintf("@%s:%s", key.Key_algorithm, key.Device_id) + for _, key := range dkeys { + + deviceKeysQueryMap = presetDeviceKeysQueryMap(deviceKeysQueryMap, uid, key) + // load for accomplishment + single := deviceKeysQueryMap[key.DeviceID] + resKey := fmt.Sprintf("@%s:%s", key.KeyAlgorithm, key.DeviceID) resBody := key.Key - if _, ok := single.Keys[resKey]; !ok { - } single.Keys[resKey] = resBody - single.DeviceId = key.Device_id - single.UserId = key.User_id - single.Signature[uid][fmt.Sprintf("@%s:%s", "ed25519", key.Device_id)] = key.Signature - single.Algorithm, _ = takeAL(*encryptionDB, req.Context(), key.User_id, key.Device_id) + single.DeviceID = key.DeviceID + single.UserID = key.UserID + single.Signature[uid][fmt.Sprintf("@%s:%s", "ed25519", key.DeviceID)] = key.Signature + single.Algorithm, err = takeAL(req.Context(), *encryptionDB, key.UserID, key.DeviceID) localpart, _, _ := gomatrixserverlib.SplitID('@', uid) device, _ := deviceDB.GetDeviceByID(req.Context(), localpart, deviceID) single.Unsigned.Info = device.DisplayName - deviceKeysQueryMap[key.Device_id] = single + deviceKeysQueryMap[key.DeviceID] = single + } + } + if err != nil { + return util.JSONResponse{ + Code: http.StatusInternalServerError, + JSON: queryRp, } } return util.JSONResponse{ @@ -191,12 +186,10 @@ func QueryPKeys( } } -// claim for one time key that may be used in session exchange in olm encryption +// ClaimOneTimeKeys claim for one time key that may be used in session exchange in olm encryption func ClaimOneTimeKeys( req *http.Request, encryptionDB *storage.Database, - userID, deviceID string, - deviceDB *devices.Database, ) util.JSONResponse { var claimRq types.ClaimRequest claimRp := types.ClaimResponse{} @@ -224,6 +217,8 @@ func ClaimOneTimeKeys( claimRp.Failures = make(map[string]interface{}) // todo: key in this map is restricted to username at the end, yet a mocked one. claimRp.Failures["@alice:localhost"] = "ran out of offered time" + case <-make(chan interface{}): + // todo : here goes federation chan , still a mocked one } } @@ -236,21 +231,24 @@ func ClaimOneTimeKeys( } else { alTyp = ONETIMEKEYSTRING } - key, err := pickOne(*encryptionDB, req.Context(), uid, deviceID, al) + key, err := pickOne(req.Context(), *encryptionDB, uid, deviceID, al) if err != nil { claimRp.Failures[uid] = fmt.Sprintf("%s:%s", "fail to get keys for device ", deviceID) } claimRp.ClaimBody[uid] = make(map[string]map[string]interface{}) - keymap := claimRp.ClaimBody[uid][deviceID] - keymap = make(map[string]interface{}) + keyPreMap := claimRp.ClaimBody[uid] + keymap := keyPreMap[deviceID] + if keymap == nil { + keymap = make(map[string]interface{}) + } switch alTyp { case ONETIMEKEYSTRING: - keymap[fmt.Sprintf("%s:%s", al, key.Key_id)] = key.Key + keymap[fmt.Sprintf("%s:%s", al, key.KeyID)] = key.Key case ONETIMEKEYOBJECT: sig := make(map[string]map[string]string) sig[uid] = make(map[string]string) sig[uid][fmt.Sprintf("%s:%s", "ed25519", deviceID)] = key.Signature - keymap[fmt.Sprintf("%s:%s", al, key.Key_id)] = types.KeyObject{Key: key.Key, Signature: sig} + keymap[fmt.Sprintf("%s:%s", al, key.KeyID)] = types.KeyObject{Key: key.Key, Signature: sig} } claimRp.ClaimBody[uid][deviceID] = keymap } @@ -261,19 +259,12 @@ func ClaimOneTimeKeys( } } -func LookUpChangedPKeys() util.JSONResponse { - return util.JSONResponse{ - Code: http.StatusOK, - JSON: struct{}{}, - } -} - // 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 == "" { + if devicekey.UserID == "" { return false } } @@ -285,12 +276,12 @@ func checkUpload(req *types.UploadEncryptSpecific, typ int) bool { return true } -// todo: complete this field through claim type +// QueryOneTimeKeys todo: complete this field through claim type func QueryOneTimeKeys( + ctx context.Context, typ int, userID, deviceID string, encryptionDB *storage.Database, - ctx context.Context, ) interface{} { if typ == TYPESUM { res, _ := encryptionDB.SelectOneTimeKeyCount(ctx, deviceID, userID) @@ -299,14 +290,14 @@ func QueryOneTimeKeys( 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 -// when web client sign out, a clean should be processed, cause all keys would never been used from then on. func ClearUnused() {} // persist both device keys and one time keys func persistKeys( - database *storage.Database, ctx context.Context, + database *storage.Database, body *types.UploadEncryptSpecific, userID, deviceID string, @@ -319,73 +310,28 @@ func persistKeys( if checkUpload(body, BODYDEVICEKEY) { deviceKeys := body.DeviceKeys al := deviceKeys.Algorithm - err = persistAl(*database, ctx, userID, deviceID, al) + err = persistAl(ctx, *database, userID, deviceID, al) + if err != nil { + return + } if checkUpload(body, BODYONETIMEKEY) { - // insert one time keys firstly - onetimeKeys := body.OneTimeKey - for al_keyID, val := range onetimeKeys.KeyString { - al := (strings.Split(al_keyID, ":"))[0] - keyID := (strings.Split(al_keyID, ":"))[1] - keyInfo := val - keyTyp := "one_time_key" - sig := "" - database.InsertKey(ctx, deviceID, userID, keyID, keyTyp, keyInfo, al, sig) - } - for al_keyID, val := range onetimeKeys.KeyObject { - al := (strings.Split(al_keyID, ":"))[0] - keyID := (strings.Split(al_keyID, ":"))[1] - keyInfo := val.Key - keyTyp := "one_time_key" - sig := val.Signature[userID][fmt.Sprintf("%s:%s", "ed25519", deviceID)] - database.InsertKey(ctx, deviceID, userID, keyID, keyTyp, keyInfo, al, sig) - } - // insert device keys - keys := deviceKeys.Keys - sigs := deviceKeys.Signature - for al_device, key := range keys { - al := (strings.Split(al_device, ":"))[0] - keyTyp := "device_key" - keyInfo := key - keyID := "" - sig := sigs[userID][fmt.Sprintf("%s:%s", "ed25519", deviceID)] - database.InsertKey( - ctx, deviceID, userID, keyID, keyTyp, keyInfo, al, sig) + if err = bothKeyProcess(ctx, body, userID, deviceID, database, deviceKeys); err != nil { + return } } else { - keys := deviceKeys.Keys - sigs := deviceKeys.Signature - for al_device, key := range keys { - al := (strings.Split(al_device, ":"))[0] - keyTyp := "device_key" - keyInfo := key - keyID := "" - sig := sigs[userID][fmt.Sprintf("%s:%s", "ed25519", deviceID)] - database.InsertKey(ctx, deviceID, userID, keyID, keyTyp, keyInfo, al, sig) + if err = dkeyProcess(ctx, userID, deviceID, database, deviceKeys); err != nil { + return } } // notifier to sync server upnotify(userID) } else { if checkUpload(body, BODYONETIMEKEY) { - onetimeKeys := body.OneTimeKey - for al_keyID, val := range onetimeKeys.KeyString { - al := (strings.Split(al_keyID, ":"))[0] - keyID := (strings.Split(al_keyID, ":"))[1] - keyInfo := val - keyTyp := "one_time_key" - sig := "" - database.InsertKey(ctx, deviceID, userID, keyID, keyTyp, keyInfo, al, sig) - } - for al_keyID, val := range onetimeKeys.KeyObject { - al := (strings.Split(al_keyID, ":"))[0] - keyID := (strings.Split(al_keyID, ":"))[1] - keyInfo := val.Key - keyTyp := "one_time_key" - sig := val.Signature[userID][fmt.Sprintf("%s:%s", "ed25519", deviceID)] - database.InsertKey(ctx, deviceID, userID, keyID, keyTyp, keyInfo, al, sig) + if err = otmKeyProcess(ctx, body, userID, deviceID, database); err != nil { + return } } else { - return errors.New("Fail to touch keys !") + return errors.New("failed to touch keys") } } return err @@ -407,7 +353,10 @@ func turnSpecific( } else { valueObject := types.KeyObject{} target, _ := json.Marshal(val) - json.Unmarshal(target, &valueObject) + err := json.Unmarshal(target, &valueObject) + if err != nil { + continue + } spec.OneTimeKey.KeyObject[key] = valueObject } } @@ -415,8 +364,8 @@ func turnSpecific( } func persistAl( - encryptDB storage.Database, ctx context.Context, + encryptDB storage.Database, uid, device string, al []string, ) (err error) { @@ -425,8 +374,8 @@ func persistAl( } func takeAL( - encryptDB storage.Database, ctx context.Context, + encryptDB storage.Database, uid, device string, ) (al []string, err error) { al, err = encryptDB.SelectAl(ctx, uid, device) @@ -434,12 +383,12 @@ func takeAL( } func pickOne( - encryptDB storage.Database, ctx context.Context, + encryptDB storage.Database, uid, device, al string, ) (key types.KeyHolder, err error) { -key, err = encryptDB.SelectOneTimeKeySingle(ctx, uid, device, al) -return + key, err = encryptDB.SelectOneTimeKeySingle(ctx, uid, device, al) + return } func upnotify(userID string) { @@ -451,8 +400,138 @@ func upnotify(userID string) { 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 presetDeviceKeysQueryMap( + deviceKeysQueryMap map[string]types.DeviceKeysQuery, + uid string, + key types.KeyHolder, +) map[string]types.DeviceKeysQuery { + // preset for complicated nested map struct + if _, ok := deviceKeysQueryMap[key.DeviceID]; !ok { + // make consistency + deviceKeysQueryMap[key.DeviceID] = types.DeviceKeysQuery{} + } + if deviceKeysQueryMap[key.DeviceID].Signature == nil { + mid := make(map[string]map[string]string) + midmap := deviceKeysQueryMap[key.DeviceID] + midmap.Signature = mid + deviceKeysQueryMap[key.DeviceID] = midmap + } + if deviceKeysQueryMap[key.DeviceID].Keys == nil { + mid := make(map[string]string) + midmap := deviceKeysQueryMap[key.DeviceID] + midmap.Keys = mid + deviceKeysQueryMap[key.DeviceID] = midmap + } + if _, ok := deviceKeysQueryMap[key.DeviceID].Signature[uid]; !ok { + // make consistency + deviceKeysQueryMap[key.DeviceID].Signature[uid] = make(map[string]string) + } + return deviceKeysQueryMap +} + +func bothKeyProcess( + ctx context.Context, + body *types.UploadEncryptSpecific, + userID, deviceID string, + database *storage.Database, + deviceKeys types.DeviceKeys, +) (err error) { + // insert one time keys firstly + onetimeKeys := body.OneTimeKey + for alKeyID, val := range onetimeKeys.KeyString { + al := (strings.Split(alKeyID, ":"))[0] + keyID := (strings.Split(alKeyID, ":"))[1] + keyInfo := val + keyStringTyp := ONETIMEKEYSTR + sig := "" + err = database.InsertKey(ctx, deviceID, userID, keyID, keyStringTyp, 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 + keyObjectTyp := ONETIMEKEYSTR + sig := val.Signature[userID][fmt.Sprintf("%s:%s", "ed25519", deviceID)] + err = database.InsertKey(ctx, deviceID, userID, keyID, keyObjectTyp, keyInfo, al, sig) + if err != nil { + return + } + } + // insert device keys + 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) + if err != nil { + return + } + } + return +} + +func dkeyProcess( + 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 otmKeyProcess( + 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/src/github.com/matrix-org/dendrite/encryptoapi/routing/routing.go b/src/github.com/matrix-org/dendrite/encryptoapi/routing/routing.go index a8a5eb592..4ec1b184d 100644 --- a/src/github.com/matrix-org/dendrite/encryptoapi/routing/routing.go +++ b/src/github.com/matrix-org/dendrite/encryptoapi/routing/routing.go @@ -19,26 +19,21 @@ import ( "github.com/gorilla/mux" "github.com/matrix-org/dendrite/clientapi/auth/authtypes" - "github.com/matrix-org/dendrite/clientapi/auth/storage/accounts" "github.com/matrix-org/dendrite/clientapi/auth/storage/devices" "github.com/matrix-org/dendrite/common" - "github.com/matrix-org/dendrite/common/config" "github.com/matrix-org/dendrite/encryptoapi/storage" "github.com/matrix-org/util" ) -const pathPrefixR0 = "/_matrix/client/r0" const pathPrefixUnstable = "/_matrix/client/unstable" +// Setup works for setting up encryption api server func Setup( apiMux *mux.Router, - cfg config.Dendrite, encryptionDB *storage.Database, - accountDB *accounts.Database, deviceDB *devices.Database, ) { - //r0mux := apiMux.PathPrefix(pathPrefixR0).Subrouter() unstablemux := apiMux.PathPrefix(pathPrefixUnstable).Subrouter() unstablemux.Handle("/keys/upload/{deviceID}", @@ -56,16 +51,14 @@ func Setup( unstablemux.Handle("/keys/query", common.MakeAuthAPI("query keys", deviceDB, func(req *http.Request, device *authtypes.Device) util.JSONResponse { //vars := mux.Vars(req) - return QueryPKeys(req, encryptionDB, device.UserID, device.ID, deviceDB) + return QueryPKeys(req, encryptionDB, device.ID, deviceDB) }), ).Methods(http.MethodPost, http.MethodOptions) unstablemux.Handle("/keys/claim", common.MakeAuthAPI("claim keys", deviceDB, func(req *http.Request, device *authtypes.Device) util.JSONResponse { - //vars := mux.Vars(req) - return ClaimOneTimeKeys(req, encryptionDB, device.UserID, device.ID, deviceDB) + return ClaimOneTimeKeys(req, encryptionDB) }), ).Methods(http.MethodPost, http.MethodOptions) - } diff --git a/src/github.com/matrix-org/dendrite/encryptoapi/storage/encrypt_algorithm.go b/src/github.com/matrix-org/dendrite/encryptoapi/storage/encrypt_algorithm.go index d243028c6..0e230a9f9 100644 --- a/src/github.com/matrix-org/dendrite/encryptoapi/storage/encrypt_algorithm.go +++ b/src/github.com/matrix-org/dendrite/encryptoapi/storage/encrypt_algorithm.go @@ -15,8 +15,8 @@ package storage import ( - "database/sql" "context" + "database/sql" "github.com/matrix-org/dendrite/common" "github.com/matrix-org/dendrite/encryptoapi/types" ) @@ -59,29 +59,29 @@ func (s *alStatements) prepare(db *sql.DB) (err error) { } // persist algorithms -func (ks *alStatements) insertAl( +func (s *alStatements) insertAl( ctx context.Context, txn *sql.Tx, userID, deviceID, algorithms string, ) error { - stmt := common.TxStmt(txn, ks.insertAlStmt) + stmt := common.TxStmt(txn, s.insertAlStmt) _, err := stmt.ExecContext(ctx, deviceID, userID, algorithms) return err } // select algorithms -func (ks *alStatements) selectAl( +func (s *alStatements) selectAl( ctx context.Context, txn *sql.Tx, - userID, deviceID string, + userID, deviceID string, ) (holder types.AlHolder, err error) { - stmt := common.TxStmt(txn, ks.selectAlStmt) + stmt := common.TxStmt(txn, s.selectAlStmt) row := stmt.QueryRowContext(ctx, userID, deviceID) single := types.AlHolder{} err = row.Scan( - &single.User_id, - &single.Device_id, - &single.Supported_algorithm, + &single.UserID, + &single.DeviceID, + &single.SupportedAlgorithm, ) return single, err } diff --git a/src/github.com/matrix-org/dendrite/encryptoapi/storage/encrypt_keys_table.go b/src/github.com/matrix-org/dendrite/encryptoapi/storage/encrypt_keys_table.go index c3c7ed469..af30301ff 100644 --- a/src/github.com/matrix-org/dendrite/encryptoapi/storage/encrypt_keys_table.go +++ b/src/github.com/matrix-org/dendrite/encryptoapi/storage/encrypt_keys_table.go @@ -15,11 +15,11 @@ package storage import ( - "database/sql" "context" + "database/sql" + "github.com/lib/pq" "github.com/matrix-org/dendrite/common" "github.com/matrix-org/dendrite/encryptoapi/types" - "github.com/lib/pq" ) const keysSchema = ` @@ -96,104 +96,106 @@ func (s *keyStatements) prepare(db *sql.DB) (err error) { } // insert keys -func (ks *keyStatements) insertKey( +func (s *keyStatements) insertKey( ctx context.Context, txn *sql.Tx, deviceID, userID, keyID, keyTyp, keyInfo, algorithm, signature string, ) error { - stmt := common.TxStmt(txn, ks.insertKeyStmt) + stmt := common.TxStmt(txn, s.insertKeyStmt) _, err := stmt.ExecContext(ctx, deviceID, userID, keyID, keyTyp, keyInfo, algorithm, signature) return err } // select by user and device -func (ks *keyStatements) selectKey( +func (s *keyStatements) selectKey( ctx context.Context, txn *sql.Tx, deviceID, userID string, -) (holders []types.KeyHolder, err error) { - stmt := common.TxStmt(txn, ks.selectKeyStmt) +) ([]types.KeyHolder, error) { + holders := []types.KeyHolder{} + stmt := common.TxStmt(txn, s.selectKeyStmt) rows, err := stmt.QueryContext(ctx, userID, deviceID) - defer rows.Close() if err != nil { return nil, err } for rows.Next() { single := &types.KeyHolder{} - if err := rows.Scan( - &single.User_id, - &single.Device_id, - &single.Key_id, - &single.Key_type, + if err = rows.Scan( + &single.UserID, + &single.DeviceID, + &single.KeyID, + &single.KeyType, &single.Key, - &single.Key_algorithm, + &single.KeyAlgorithm, &single.Signature, ); err != nil { return nil, err } holders = append(holders, *single) } + err = rows.Close() return holders, err } // select single one for claim usage -func (ks *keyStatements) selectSingleKey( +func (s *keyStatements) selectSingleKey( ctx context.Context, userID, deviceID, algorithm string, ) (holder types.KeyHolder, err error) { - stmt := ks.selectSingleKeyStmt + stmt := s.selectSingleKeyStmt row := stmt.QueryRowContext(ctx, userID, deviceID, algorithm) if err != nil { return holder, err } - if err := row.Scan( - &holder.User_id, - &holder.Device_id, - &holder.Key_id, - &holder.Key_type, + if err = row.Scan( + &holder.UserID, + &holder.DeviceID, + &holder.KeyID, + &holder.KeyType, &holder.Key, - &holder.Key_algorithm, + &holder.KeyAlgorithm, &holder.Signature, ); err != nil { - deleteStmt := ks.deleteSingleKeyStmt - deleteStmt.ExecContext(ctx, userID, deviceID, algorithm, holder.Key_id) + deleteStmt := s.deleteSingleKeyStmt + _, err = deleteStmt.ExecContext(ctx, userID, deviceID, algorithm, holder.KeyID) return holder, err } return holder, err } // select details by given an array of devices -func (ks *keyStatements) selectInKeys( +func (s *keyStatements) selectInKeys( ctx context.Context, userID string, arr []string, ) (holders []types.KeyHolder, err error) { - rows := &sql.Rows{} - defer rows.Close() - stmt := ks.selectAllKeyStmt + rows := sql.Rows{} + rowsP := &rows + stmt := s.selectAllKeyStmt if len(arr) == 0 { - rows, err = stmt.QueryContext(ctx, userID, "device_key") + rowsP, err = stmt.QueryContext(ctx, userID, "device_key") } else { - stmt = ks.selectInKeysStmt + stmt = s.selectInKeysStmt list := pq.Array(arr) - rows, err = stmt.QueryContext(ctx, userID, list) + rowsP, err = stmt.QueryContext(ctx, userID, list) } if err != nil { return nil, err } for rows.Next() { single := &types.KeyHolder{} - if err := rows.Scan( - &single.User_id, - &single.Device_id, - &single.Key_id, - &single.Key_type, + if err = rows.Scan( + &single.UserID, + &single.DeviceID, + &single.KeyID, + &single.KeyType, &single.Key, - &single.Key_algorithm, + &single.KeyAlgorithm, &single.Signature, ); err != nil { return nil, err } holders = append(holders, *single) } + err = rowsP.Close() return holders, err } diff --git a/src/github.com/matrix-org/dendrite/encryptoapi/storage/storage.go b/src/github.com/matrix-org/dendrite/encryptoapi/storage/storage.go index 40e4c1fe2..2ed567a7d 100644 --- a/src/github.com/matrix-org/dendrite/encryptoapi/storage/storage.go +++ b/src/github.com/matrix-org/dendrite/encryptoapi/storage/storage.go @@ -15,9 +15,9 @@ package storage import ( + "context" "database/sql" "github.com/matrix-org/dendrite/common" - "context" "github.com/matrix-org/dendrite/encryptoapi/types" "strings" ) @@ -47,7 +47,7 @@ func NewDatabase(dataSourceName string) (*Database, error) { return &Database{db: db, keyStatements: keyStatement, alStatements: alStatement}, nil } -// insert device key +// InsertKey insert device key func (d *Database) InsertKey( ctx context.Context, deviceID, userID, keyID, keyTyp, keyInfo, al, sig string, @@ -58,7 +58,7 @@ func (d *Database) InsertKey( return } -// for key upload response usage a map from key algorithm to sum to counterpart +// SelectOneTimeKeyCount for key upload response usage a map from key algorithm to sum to counterpart func (d *Database) SelectOneTimeKeyCount( ctx context.Context, deviceID, userID string, @@ -67,11 +67,11 @@ func (d *Database) SelectOneTimeKeyCount( err = common.WithTransaction(d.db, func(txn *sql.Tx) error { elems, err := d.keyStatements.selectKey(ctx, txn, deviceID, userID) for _, val := range elems { - if _, ok := m[val.Key_algorithm]; !ok { - m[val.Key_algorithm] = 0 + if _, ok := m[val.KeyAlgorithm]; !ok { + m[val.KeyAlgorithm] = 0 } - if val.Key_type == "one_time_key" { - m[val.Key_algorithm] += 1 + if val.KeyType == "one_time_key" { + m[val.KeyAlgorithm]++ } } return err @@ -79,7 +79,7 @@ func (d *Database) SelectOneTimeKeyCount( return } -// query keys in a range of devices +// QueryInRange query keys in a range of devices func (d *Database) QueryInRange( ctx context.Context, userID string, @@ -89,30 +89,30 @@ func (d *Database) QueryInRange( return } -// persist algorithms +// InsertAl persist algorithms func (d *Database) InsertAl( ctx context.Context, uid, device string, al []string, ) (err error) { err = common.WithTransaction(d.db, func(txn *sql.Tx) (err error) { - d.alStatements.insertAl(ctx, txn, uid, device, strings.Join(al, ",")) + err = d.alStatements.insertAl(ctx, txn, uid, device, strings.Join(al, ",")) return }) return } -// select algorithms +// SelectAl select algorithms func (d *Database) SelectAl( ctx context.Context, uid, device string, ) (res []string, err error) { err = common.WithTransaction(d.db, func(txn *sql.Tx) (err error) { holder, err := d.alStatements.selectAl(ctx, txn, uid, device) - res = strings.Split(holder.Supported_algorithm, ",") + res = strings.Split(holder.SupportedAlgorithm, ",") return }) return } -// claim for one time key one for once +// SelectOneTimeKeySingle claim for one time key one for once func (d *Database) SelectOneTimeKeySingle( ctx context.Context, userID, deviceID, algorithm string, diff --git a/src/github.com/matrix-org/dendrite/encryptoapi/types/claim.go b/src/github.com/matrix-org/dendrite/encryptoapi/types/claim.go index 80a786d20..858696f1e 100644 --- a/src/github.com/matrix-org/dendrite/encryptoapi/types/claim.go +++ b/src/github.com/matrix-org/dendrite/encryptoapi/types/claim.go @@ -14,41 +14,14 @@ package types -/* - { - "timeout": 10000, - "one_time_keys": { - "@alice:example.com": { - "JLAFKJWSCS": "curve25519" - } - } - } -*/ +// ClaimRequest structure type ClaimRequest struct { Timeout int64 `json:"timeout"` ClaimDetail map[string]map[string]string `json:"one_time_keys"` } -/* - { - "failures": {}, - "one_time_keys": { - "@alice:example.com": { - "JLAFKJWSCS": { - "signed_curve25519:AAAAHg": { - "key": "zKbLg+NrIjpnagy+pIY6uPL4ZwEG2v+8F9lmgsnlZzs", - "signatures": { - "@alice:example.com": { - "ed25519:JLAFKJWSCS": "FLWxXqGbwrb8SM3Y795eB6OA8bwBcoMZFXBqnTn58AYWZSqiD45tlBVcDa2L7RwdKXebW/VzDlnfVJ+9jok1Bw" - } - } - } - } - } - } - } -*/ +// ClaimResponse structure type ClaimResponse struct { - Failures map[string]interface{} `json:"failures"` + Failures map[string]interface{} `json:"failures"` ClaimBody map[string]map[string]map[string]interface{} `json:"one_time_keys"` } diff --git a/src/github.com/matrix-org/dendrite/encryptoapi/types/query.go b/src/github.com/matrix-org/dendrite/encryptoapi/types/query.go index 1c5dba3a2..c7dae9ea7 100644 --- a/src/github.com/matrix-org/dendrite/encryptoapi/types/query.go +++ b/src/github.com/matrix-org/dendrite/encryptoapi/types/query.go @@ -14,63 +14,30 @@ package types -/* - { - "timeout": 10000, - "device_keys": { - "@alice:example.com": ["DISYYYX","XYIISONM"] - } - } -*/ +// QueryRequest structure type QueryRequest struct { - Timeout int64 `json:"timeout"` + Timeout int64 `json:"timeout"` DeviceKeys map[string]interface{} `json:"device_keys"` - Token string `json:"token"` + Token string `json:"token"` } -/* - { - "failures": {}, - "device_keys": { - "@alice:example.com": { - "JLAFKJWSCS": { - "user_id": "@alice:example.com", - "device_id": "JLAFKJWSCS", - "algorithms": [ - "m.olm.curve25519-aes-sha256", - "m.megolm.v1.aes-sha" - ], - "keys": { - "curve25519:JLAFKJWSCS": "3C5BFWi2Y8MaVvjM8M22DBmh24PmgR0nPvJOIArzgyI", - "ed25519:JLAFKJWSCS": "lEuiRJBit0IG6nUf5pUzWTUEsRVVe/HJkoKuEww9ULI" - }, - "signatures": { - "@alice:example.com": { - "ed25519:JLAFKJWSCS": "dSO80A01XiigH3uBiDVx/EjzaoycHcjq9lfQX0uWsqxl2giMIiSPR8a4d291W1ihKJL/a+myXS367WT6NAIcBA" - } - }, - "unsigned": { - "device_display_name": "Alice's mobile phone" - } - } - } - } - } -*/ +// QueryResponse structure type QueryResponse struct { Failure map[string]interface{} `json:"failures"` DeviceKeys map[string]map[string]DeviceKeysQuery `json:"device_keys"` } +// DeviceKeysQuery structure type DeviceKeysQuery struct { - UserId string `json:"user_id"` - DeviceId string `json:"device_id"` + UserID string `json:"user_id"` + DeviceID string `json:"device_id"` Algorithm []string `json:"algorithms"` Keys map[string]string `json:"keys"` Signature map[string]map[string]string `json:"signatures"` Unsigned UnsignedDeviceInfo `json:"unsigned"` } +// UnsignedDeviceInfo structure type UnsignedDeviceInfo struct { Info string `json:"device_display_name"` } diff --git a/src/github.com/matrix-org/dendrite/encryptoapi/types/storage.go b/src/github.com/matrix-org/dendrite/encryptoapi/types/storage.go index 55815420a..c3d098398 100644 --- a/src/github.com/matrix-org/dendrite/encryptoapi/types/storage.go +++ b/src/github.com/matrix-org/dendrite/encryptoapi/types/storage.go @@ -14,17 +14,20 @@ package types +// KeyHolder structure type KeyHolder struct { - User_id, - Device_id, - Signature, key, - Key_algorithm, - Key_id, + UserID, + DeviceID, + Signature, + KeyAlgorithm, + KeyID, Key, - Key_type string + KeyType string } + +// AlHolder structure type AlHolder struct { - User_id, - Device_id, - Supported_algorithm string + UserID, + DeviceID, + SupportedAlgorithm string } diff --git a/src/github.com/matrix-org/dendrite/encryptoapi/types/upload.go b/src/github.com/matrix-org/dendrite/encryptoapi/types/upload.go index b2f542075..7e8a62c13 100644 --- a/src/github.com/matrix-org/dendrite/encryptoapi/types/upload.go +++ b/src/github.com/matrix-org/dendrite/encryptoapi/types/upload.go @@ -14,135 +14,46 @@ package types -/* - { - "device_keys": { - "user_id": "@alice:example.com", - "device_id": "JLAFKJWSCS", - "algorithms": [ - "m.olm.curve25519-aes-sha256", - "m.megolm.v1.aes-sha" - ], - "keys": { - "curve25519:JLAFKJWSCS": "3C5BFWi2Y8MaVvjM8M22DBmh24PmgR0nPvJOIArzgyI", - "ed25519:JLAFKJWSCS": "lEuiRJBit0IG6nUf5pUzWTUEsRVVe/HJkoKuEww9ULI" - }, - "signatures": { - "@alice:example.com": { - "ed25519:JLAFKJWSCS": "dSO80A01XiigH3uBiDVx/EjzaoycHcjq9lfQX0uWsqxl2giMIiSPR8a4d291W1ihKJL/a+myXS367WT6NAIcBA" - } - } - }, - "one_time_keys": { - "curve25519:AAAAAQ": "/qyvZvwjiTxGdGU0RCguDCLeR+nmsb3FfNG3/Ve4vU8", - "signed_curve25519:AAAAHg": { - "key": "zKbLg+NrIjpnagy+pIY6uPL4ZwEG2v+8F9lmgsnlZzs", - "signatures": { - "@alice:example.com": { - "ed25519:JLAFKJWSCS": "FLWxXqGbwrb8SM3Y795eB6OA8bwBcoMZFXBqnTn58AYWZSqiD45tlBVcDa2L7RwdKXebW/VzDlnfVJ+9jok1Bw" - } - } - }, - "signed_curve25519:AAAAHQ": { - "key": "j3fR3HemM16M7CWhoI4Sk5ZsdmdfQHsKL1xuSft6MSw", - "signatures": { - "@alice:example.com": { - "ed25519:JLAFKJWSCS": "IQeCEPb9HFk217cU9kw9EOiusC6kMIkoIRnbnfOh5Oc63S1ghgyjShBGpu34blQomoalCyXWyhaaT3MrLZYQAA" - } - } - } - } - } -*/ +// UploadEncrypt structure type UploadEncrypt struct { DeviceKeys DeviceKeys `json:"device_keys"` OneTimeKey map[string]interface{} `json:"one_time_keys"` } + +// UploadEncryptSpecific structure type UploadEncryptSpecific struct { DeviceKeys DeviceKeys `json:"device_keys"` OneTimeKey OneTimeKeySpecific `json:"one_time_keys"` } -/* - { - "one_time_key_counts": { - "curve25519": 10, - "signed_curve25519": 20 - } - } -*/ +// UploadResponse structure type UploadResponse struct { Count map[string]int `json:"one_time_key_counts"` } -/* - "device_keys": { - "user_id": "@alice:example.com", - "device_id": "JLAFKJWSCS", - "algorithms": [ - "m.olm.curve25519-aes-sha256", - "m.megolm.v1.aes-sha" - ], - "keys": { - "curve25519:JLAFKJWSCS": "3C5BFWi2Y8MaVvjM8M22DBmh24PmgR0nPvJOIArzgyI", - "ed25519:JLAFKJWSCS": "lEuiRJBit0IG6nUf5pUzWTUEsRVVe/HJkoKuEww9ULI" - }, - "signatures": { - "@alice:example.com": { - "ed25519:JLAFKJWSCS": "dSO80A01XiigH3uBiDVx/EjzaoycHcjq9lfQX0uWsqxl2giMIiSPR8a4d291W1ihKJL/a+myXS367WT6NAIcBA" - } - } - } -*/ +// DeviceKeys structure type DeviceKeys struct { - UserId string `json:"user_id"` - DeviceId string `json:"device_id"` + UserID string `json:"user_id"` + DeviceID string `json:"device_id"` Algorithm []string `json:"algorithms"` Keys map[string]string `json:"keys"` Signature map[string]map[string]string `json:"signatures"` } -/* - "signed_curve25519:AAAAHg": { - "key": "zKbLg+NrIjpnagy+pIY6uPL4ZwEG2v+8F9lmgsnlZzs", - "signatures": { - "@alice:example.com": { - "ed25519:JLAFKJWSCS": "FLWxXqGbwrb8SM3Y795eB6OA8bwBcoMZFXBqnTn58AYWZSqiD45tlBVcDa2L7RwdKXebW/VzDlnfVJ+9jok1Bw" - } - } - } -*/ +// KeyObject structure type KeyObject struct { Key string `json:"key"` Signature map[string]map[string]string `json:"signatures"` } -/* - "one_time_keys": { - "curve25519:AAAAAQ": "/qyvZvwjiTxGdGU0RCguDCLeR+nmsb3FfNG3/Ve4vU8", - "signed_curve25519:AAAAHg": { - "key": "zKbLg+NrIjpnagy+pIY6uPL4ZwEG2v+8F9lmgsnlZzs", - "signatures": { - "@alice:example.com": { - "ed25519:JLAFKJWSCS": "FLWxXqGbwrb8SM3Y795eB6OA8bwBcoMZFXBqnTn58AYWZSqiD45tlBVcDa2L7RwdKXebW/VzDlnfVJ+9jok1Bw" - } - } - }, - "signed_curve25519:AAAAHQ": { - "key": "j3fR3HemM16M7CWhoI4Sk5ZsdmdfQHsKL1xuSft6MSw", - "signatures": { - "@alice:example.com": { - "ed25519:JLAFKJWSCS": "IQeCEPb9HFk217cU9kw9EOiusC6kMIkoIRnbnfOh5Oc63S1ghgyjShBGpu34blQomoalCyXWyhaaT3MrLZYQAA" - } - } - } - } -*/ +// OneTimeKey structure type OneTimeKey struct { //KeyString map[string]string //KeyObject map[string]KeyObject KeySth map[string]interface{} } + +// OneTimeKeySpecific structure type OneTimeKeySpecific struct { KeyString map[string]string KeyObject map[string]KeyObject