mirror of https://github.com/mautrix/go.git
Allow any UI auth for uploading cross signing keys
Fix endless loop with UI auth causing 401 when uploading keys. Use any type for key backup setup request auth data so that unmarshaled objects can be used that have signatures embedded. Generating keys will now also return them if we also want to setup key backup without storing the keys in-between.pull/175/head
parent
11c2907f2e
commit
b131dab9de
|
@ -2061,7 +2061,7 @@ func (cli *Client) GetKeyBackupLatestVersion(ctx context.Context) (resp *RespRoo
|
|||
// CreateKeyBackupVersion creates a new key backup.
|
||||
//
|
||||
// See: https://spec.matrix.org/v1.9/client-server-api/#post_matrixclientv3room_keysversion
|
||||
func (cli *Client) CreateKeyBackupVersion(ctx context.Context, req *ReqRoomKeysVersionCreate) (resp *RespRoomKeysVersionCreate, err error) {
|
||||
func (cli *Client) CreateKeyBackupVersion(ctx context.Context, req *ReqRoomKeysVersionCreate[backup.MegolmAuthData]) (resp *RespRoomKeysVersionCreate, err error) {
|
||||
urlPath := cli.BuildClientURL("v3", "room_keys", "version")
|
||||
_, err = cli.MakeRequest(ctx, http.MethodPost, urlPath, req, &resp)
|
||||
return
|
||||
|
@ -2080,7 +2080,7 @@ func (cli *Client) GetKeyBackupVersion(ctx context.Context, version id.KeyBackup
|
|||
// the auth_data can be modified.
|
||||
//
|
||||
// See: https://spec.matrix.org/v1.9/client-server-api/#put_matrixclientv3room_keysversionversion
|
||||
func (cli *Client) UpdateKeyBackupVersion(ctx context.Context, version id.KeyBackupVersion, req *ReqRoomKeysVersionUpdate) error {
|
||||
func (cli *Client) UpdateKeyBackupVersion(ctx context.Context, version id.KeyBackupVersion, req *ReqRoomKeysVersionUpdate[backup.MegolmAuthData]) error {
|
||||
urlPath := cli.BuildClientURL("v3", "room_keys", "version", version)
|
||||
_, err := cli.MakeRequest(ctx, http.MethodPut, urlPath, nil, nil)
|
||||
return err
|
||||
|
@ -2145,7 +2145,7 @@ func (cli *Client) UploadCrossSigningKeys(ctx context.Context, keys *UploadCross
|
|||
RequestJSON: keys,
|
||||
SensitiveContent: keys.Auth != nil,
|
||||
})
|
||||
if respErr, ok := err.(HTTPError); ok && respErr.IsStatus(http.StatusUnauthorized) {
|
||||
if respErr, ok := err.(HTTPError); ok && respErr.IsStatus(http.StatusUnauthorized) && uiaCallback != nil {
|
||||
// try again with UI auth
|
||||
var uiAuthResp RespUserInteractive
|
||||
if err := json.Unmarshal(content, &uiAuthResp); err != nil {
|
||||
|
@ -2154,7 +2154,7 @@ func (cli *Client) UploadCrossSigningKeys(ctx context.Context, keys *UploadCross
|
|||
auth := uiaCallback(&uiAuthResp)
|
||||
if auth != nil {
|
||||
keys.Auth = auth
|
||||
return cli.UploadCrossSigningKeys(ctx, keys, uiaCallback)
|
||||
return cli.UploadCrossSigningKeys(ctx, keys, nil)
|
||||
}
|
||||
}
|
||||
return err
|
||||
|
|
|
@ -14,6 +14,7 @@ import (
|
|||
"maunium.net/go/mautrix/crypto/ssss"
|
||||
"maunium.net/go/mautrix/crypto/utils"
|
||||
"maunium.net/go/mautrix/event"
|
||||
"maunium.net/go/mautrix/id"
|
||||
)
|
||||
|
||||
// FetchCrossSigningKeysFromSSSS fetches all the cross-signing keys from SSSS, decrypts them using the given key and stores them in the olm machine.
|
||||
|
@ -57,33 +58,8 @@ func (mach *OlmMachine) retrieveDecryptXSigningKey(ctx context.Context, keyName
|
|||
return decryptedKey, nil
|
||||
}
|
||||
|
||||
// GenerateAndUploadCrossSigningKeys generates a new key with all corresponding cross-signing keys.
|
||||
//
|
||||
// A passphrase can be provided to generate the SSSS key. If the passphrase is empty, a random key
|
||||
// is used. The base58-formatted recovery key is the first return parameter.
|
||||
//
|
||||
// The account password of the user is required for uploading keys to the server.
|
||||
func (mach *OlmMachine) GenerateAndUploadCrossSigningKeys(ctx context.Context, userPassword, passphrase string) (string, error) {
|
||||
key, err := mach.SSSS.GenerateAndUploadKey(ctx, passphrase)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to generate and upload SSSS key: %w", err)
|
||||
}
|
||||
|
||||
// generate the three cross-signing keys
|
||||
keysCache, err := mach.GenerateCrossSigningKeys()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
recoveryKey := key.RecoveryKey()
|
||||
|
||||
// Store the private keys in SSSS
|
||||
if err := mach.UploadCrossSigningKeysToSSSS(ctx, key, keysCache); err != nil {
|
||||
return recoveryKey, fmt.Errorf("failed to upload cross-signing keys to SSSS: %w", err)
|
||||
}
|
||||
|
||||
// Publish cross-signing keys
|
||||
err = mach.PublishCrossSigningKeys(ctx, keysCache, func(uiResp *mautrix.RespUserInteractive) interface{} {
|
||||
func (mach *OlmMachine) GenerateAndUploadCrossSigningKeysWithPassword(ctx context.Context, userPassword, passphrase string) (string, *CrossSigningKeysCache, error) {
|
||||
return mach.GenerateAndUploadCrossSigningKeys(ctx, func(uiResp *mautrix.RespUserInteractive) interface{} {
|
||||
return &mautrix.ReqUIAuthLogin{
|
||||
BaseAuthData: mautrix.BaseAuthData{
|
||||
Type: mautrix.AuthTypePassword,
|
||||
|
@ -92,17 +68,44 @@ func (mach *OlmMachine) GenerateAndUploadCrossSigningKeys(ctx context.Context, u
|
|||
User: mach.Client.UserID.String(),
|
||||
Password: userPassword,
|
||||
}
|
||||
})
|
||||
}, passphrase)
|
||||
}
|
||||
|
||||
// GenerateAndUploadCrossSigningKeys generates a new key with all corresponding cross-signing keys.
|
||||
//
|
||||
// A passphrase can be provided to generate the SSSS key. If the passphrase is empty, a random key
|
||||
// is used. The base58-formatted recovery key is the first return parameter.
|
||||
//
|
||||
// The account password of the user is required for uploading keys to the server.
|
||||
func (mach *OlmMachine) GenerateAndUploadCrossSigningKeys(ctx context.Context, uiaCallback mautrix.UIACallback, passphrase string) (string, *CrossSigningKeysCache, error) {
|
||||
key, err := mach.SSSS.GenerateAndUploadKey(ctx, passphrase)
|
||||
if err != nil {
|
||||
return recoveryKey, fmt.Errorf("failed to publish cross-signing keys: %w", err)
|
||||
return "", nil, fmt.Errorf("failed to generate and upload SSSS key: %w", err)
|
||||
}
|
||||
|
||||
// generate the three cross-signing keys
|
||||
keysCache, err := mach.GenerateCrossSigningKeys()
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
|
||||
// Store the private keys in SSSS
|
||||
if err := mach.UploadCrossSigningKeysToSSSS(ctx, key, keysCache); err != nil {
|
||||
return "", nil, fmt.Errorf("failed to upload cross-signing keys to SSSS: %w", err)
|
||||
}
|
||||
|
||||
// Publish cross-signing keys
|
||||
err = mach.PublishCrossSigningKeys(ctx, keysCache, uiaCallback)
|
||||
if err != nil {
|
||||
return "", nil, fmt.Errorf("failed to publish cross-signing keys: %w", err)
|
||||
}
|
||||
|
||||
err = mach.SSSS.SetDefaultKeyID(ctx, key.ID)
|
||||
if err != nil {
|
||||
return recoveryKey, fmt.Errorf("failed to mark %s as the default key: %w", key.ID, err)
|
||||
return "", nil, fmt.Errorf("failed to mark %s as the default key: %w", key.ID, err)
|
||||
}
|
||||
|
||||
return recoveryKey, nil
|
||||
return key.RecoveryKey(), keysCache, nil
|
||||
}
|
||||
|
||||
// UploadCrossSigningKeysToSSSS stores the given cross-signing keys on the server encrypted with the given key.
|
||||
|
@ -116,5 +119,17 @@ func (mach *OlmMachine) UploadCrossSigningKeysToSSSS(ctx context.Context, key *s
|
|||
if err := mach.SSSS.SetEncryptedAccountData(ctx, event.AccountDataCrossSigningUser, keys.UserSigningKey.Seed, key); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Also store these locally
|
||||
if err := mach.CryptoStore.PutCrossSigningKey(ctx, mach.Client.UserID, id.XSUsageMaster, keys.MasterKey.PublicKey); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := mach.CryptoStore.PutCrossSigningKey(ctx, mach.Client.UserID, id.XSUsageSelfSigning, keys.SelfSigningKey.PublicKey); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := mach.CryptoStore.PutCrossSigningKey(ctx, mach.Client.UserID, id.XSUsageUserSigning, keys.UserSigningKey.PublicKey); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
13
requests.go
13
requests.go
|
@ -97,8 +97,9 @@ type ReqUIAuthFallback struct {
|
|||
|
||||
type ReqUIAuthLogin struct {
|
||||
BaseAuthData
|
||||
User string `json:"user"`
|
||||
Password string `json:"password"`
|
||||
User string `json:"user,omitempty"`
|
||||
Password string `json:"password,omitempty"`
|
||||
Token string `json:"token,omitempty"`
|
||||
}
|
||||
|
||||
// ReqCreateRoom is the JSON request for https://spec.matrix.org/v1.2/client-server-api/#post_matrixclientv3createroom
|
||||
|
@ -428,14 +429,14 @@ type ReqBeeperSplitRoom struct {
|
|||
Parts []BeeperSplitRoomPart `json:"parts"`
|
||||
}
|
||||
|
||||
type ReqRoomKeysVersionCreate struct {
|
||||
type ReqRoomKeysVersionCreate[A any] struct {
|
||||
Algorithm id.KeyBackupAlgorithm `json:"algorithm"`
|
||||
AuthData json.RawMessage `json:"auth_data"`
|
||||
AuthData A `json:"auth_data"`
|
||||
}
|
||||
|
||||
type ReqRoomKeysVersionUpdate struct {
|
||||
type ReqRoomKeysVersionUpdate[A any] struct {
|
||||
Algorithm id.KeyBackupAlgorithm `json:"algorithm"`
|
||||
AuthData json.RawMessage `json:"auth_data"`
|
||||
AuthData A `json:"auth_data"`
|
||||
Version id.KeyBackupVersion `json:"version,omitempty"`
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue