hicli/profile: use mautrix-go's GetCachedDevices

This commit is contained in:
Tulir Asokan 2024-12-07 15:05:07 +02:00
parent a37a35795c
commit cc2f334502
5 changed files with 27 additions and 73 deletions

View file

@ -73,7 +73,7 @@ require (
gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect
gopkg.in/warnings.v0 v0.1.2 // indirect gopkg.in/warnings.v0 v0.1.2 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect
maunium.net/go/mautrix v0.22.1-0.20241205122504-933daead3b34 // indirect maunium.net/go/mautrix v0.22.1-0.20241207130433-421bd5c4c837 // indirect
mvdan.cc/xurls/v2 v2.5.0 // indirect mvdan.cc/xurls/v2 v2.5.0 // indirect
) )

View file

@ -250,7 +250,7 @@ gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
maunium.net/go/mautrix v0.22.1-0.20241205122504-933daead3b34 h1:oDfWbC8MwcMwrqtIhQ3uQBP23C/B9YqAUfKkDxToFm0= maunium.net/go/mautrix v0.22.1-0.20241207130433-421bd5c4c837 h1:v3cRnMfhKxpnKjhikZ5HY72MKIsgYzldL2s3cqbkNbY=
maunium.net/go/mautrix v0.22.1-0.20241205122504-933daead3b34/go.mod h1:oqwf9WYC/brqucM+heYk4gX11O59nP+ljvyxVhndFIM= maunium.net/go/mautrix v0.22.1-0.20241207130433-421bd5c4c837/go.mod h1:oqwf9WYC/brqucM+heYk4gX11O59nP+ljvyxVhndFIM=
mvdan.cc/xurls/v2 v2.5.0 h1:lyBNOm8Wo71UknhUs4QTFUNNMyxy2JEIaKKo0RWOh+8= mvdan.cc/xurls/v2 v2.5.0 h1:lyBNOm8Wo71UknhUs4QTFUNNMyxy2JEIaKKo0RWOh+8=
mvdan.cc/xurls/v2 v2.5.0/go.mod h1:yQgaGQ1rFtJUzkmKiHYSSfuQxqfYmd//X6PxvholpeE= mvdan.cc/xurls/v2 v2.5.0/go.mod h1:yQgaGQ1rFtJUzkmKiHYSSfuQxqfYmd//X6PxvholpeE=

2
go.mod
View file

@ -25,7 +25,7 @@ require (
golang.org/x/text v0.20.0 golang.org/x/text v0.20.0
gopkg.in/yaml.v3 v3.0.1 gopkg.in/yaml.v3 v3.0.1
maunium.net/go/mauflag v1.0.0 maunium.net/go/mauflag v1.0.0
maunium.net/go/mautrix v0.22.1-0.20241205122504-933daead3b34 maunium.net/go/mautrix v0.22.1-0.20241207130433-421bd5c4c837
mvdan.cc/xurls/v2 v2.5.0 mvdan.cc/xurls/v2 v2.5.0
) )

4
go.sum
View file

@ -91,7 +91,7 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
maunium.net/go/mauflag v1.0.0 h1:YiaRc0tEI3toYtJMRIfjP+jklH45uDHtT80nUamyD4M= maunium.net/go/mauflag v1.0.0 h1:YiaRc0tEI3toYtJMRIfjP+jklH45uDHtT80nUamyD4M=
maunium.net/go/mauflag v1.0.0/go.mod h1:nLivPOpTpHnpzEh8jEdSL9UqO9+/KBJFmNRlwKfkPeA= maunium.net/go/mauflag v1.0.0/go.mod h1:nLivPOpTpHnpzEh8jEdSL9UqO9+/KBJFmNRlwKfkPeA=
maunium.net/go/mautrix v0.22.1-0.20241205122504-933daead3b34 h1:oDfWbC8MwcMwrqtIhQ3uQBP23C/B9YqAUfKkDxToFm0= maunium.net/go/mautrix v0.22.1-0.20241207130433-421bd5c4c837 h1:v3cRnMfhKxpnKjhikZ5HY72MKIsgYzldL2s3cqbkNbY=
maunium.net/go/mautrix v0.22.1-0.20241205122504-933daead3b34/go.mod h1:oqwf9WYC/brqucM+heYk4gX11O59nP+ljvyxVhndFIM= maunium.net/go/mautrix v0.22.1-0.20241207130433-421bd5c4c837/go.mod h1:oqwf9WYC/brqucM+heYk4gX11O59nP+ljvyxVhndFIM=
mvdan.cc/xurls/v2 v2.5.0 h1:lyBNOm8Wo71UknhUs4QTFUNNMyxy2JEIaKKo0RWOh+8= mvdan.cc/xurls/v2 v2.5.0 h1:lyBNOm8Wo71UknhUs4QTFUNNMyxy2JEIaKKo0RWOh+8=
mvdan.cc/xurls/v2 v2.5.0/go.mod h1:yQgaGQ1rFtJUzkmKiHYSSfuQxqfYmd//X6PxvholpeE= mvdan.cc/xurls/v2 v2.5.0/go.mod h1:yQgaGQ1rFtJUzkmKiHYSSfuQxqfYmd//X6PxvholpeE=

View file

@ -8,12 +8,13 @@ package hicli
import ( import (
"context" "context"
"fmt" "errors"
"slices" "slices"
"strings"
"github.com/rs/zerolog" "github.com/rs/zerolog"
"maunium.net/go/mautrix" "maunium.net/go/mautrix"
"maunium.net/go/mautrix/crypto"
"maunium.net/go/mautrix/id" "maunium.net/go/mautrix/id"
) )
@ -59,81 +60,34 @@ type ProfileEncryptionInfo struct {
func (h *HiClient) GetProfileEncryptionInfo(ctx context.Context, userID id.UserID) (*ProfileEncryptionInfo, error) { func (h *HiClient) GetProfileEncryptionInfo(ctx context.Context, userID id.UserID) (*ProfileEncryptionInfo, error) {
var resp ProfileEncryptionInfo var resp ProfileEncryptionInfo
log := zerolog.Ctx(ctx) log := zerolog.Ctx(ctx)
userIDs, err := h.CryptoStore.FilterTrackedUsers(ctx, []id.UserID{userID}) cachedDevices, err := h.Crypto.GetCachedDevices(ctx, userID)
if err != nil { if errors.Is(err, crypto.ErrUserNotTracked) {
log.Err(err).Msg("Failed to check if user's devices are tracked")
return nil, fmt.Errorf("failed to check if user's devices are tracked: %w", err)
} else if len(userIDs) == 0 {
return &resp, nil return &resp, nil
} } else if err != nil {
ownKeys := h.Crypto.GetOwnCrossSigningPublicKeys(ctx) log.Err(err).Msg("Failed to get cached devices")
var ownUserSigningKey id.Ed25519 return nil, err
if ownKeys != nil {
ownUserSigningKey = ownKeys.UserSigningKey
} }
resp.DevicesTracked = true resp.DevicesTracked = true
csKeys, err := h.CryptoStore.GetCrossSigningKeys(ctx, userID) if cachedDevices.MasterKey != nil {
theirMasterKey := csKeys[id.XSUsageMaster] resp.MasterKey = cachedDevices.MasterKey.Key.Fingerprint()
theirSelfSignKey := csKeys[id.XSUsageSelfSigning] resp.FirstMasterKey = cachedDevices.MasterKey.First.Fingerprint()
if err != nil { if !cachedDevices.HasValidSelfSigningKey {
log.Err(err).Msg("Failed to get cross-signing keys")
return nil, fmt.Errorf("failed to get cross-signing keys: %w", err)
} else if csKeys != nil && theirMasterKey.Key != "" {
resp.MasterKey = theirMasterKey.Key.Fingerprint()
resp.FirstMasterKey = theirMasterKey.First.Fingerprint()
selfKeySigned, err := h.CryptoStore.IsKeySignedBy(ctx, userID, theirSelfSignKey.Key, userID, theirMasterKey.Key)
if err != nil {
log.Err(err).Msg("Failed to check if self-signing key is signed by master key")
return nil, fmt.Errorf("failed to check if self-signing key is signed by master key: %w", err)
} else if !selfKeySigned {
theirSelfSignKey = id.CrossSigningKey{}
resp.Errors = append(resp.Errors, "Self-signing key is not signed by master key") resp.Errors = append(resp.Errors, "Self-signing key is not signed by master key")
} }
} else { } else {
resp.Errors = append(resp.Errors, "Cross-signing keys not found") resp.Errors = append(resp.Errors, "Cross-signing keys not found")
} }
devices, err := h.CryptoStore.GetDevices(ctx, userID) resp.UserTrusted = cachedDevices.MasterKeySignedByUs
if err != nil { resp.Devices = make([]*ProfileDevice, len(cachedDevices.Devices))
log.Err(err).Msg("Failed to get devices for user") for i, dev := range cachedDevices.Devices {
return nil, fmt.Errorf("failed to get devices: %w", err)
}
if userID == h.Account.UserID {
resp.UserTrusted, err = h.CryptoStore.IsKeySignedBy(ctx, userID, theirMasterKey.Key, userID, h.Crypto.OwnIdentity().SigningKey)
} else if ownUserSigningKey != "" && theirMasterKey.Key != "" {
resp.UserTrusted, err = h.CryptoStore.IsKeySignedBy(ctx, userID, theirMasterKey.Key, h.Account.UserID, ownUserSigningKey)
}
if err != nil {
log.Err(err).Msg("Failed to check if user is trusted")
resp.Errors = append(resp.Errors, fmt.Sprintf("Failed to check if user is trusted: %v", err))
}
resp.Devices = make([]*ProfileDevice, len(devices))
i := 0
for _, device := range devices {
signatures, err := h.CryptoStore.GetSignaturesForKeyBy(ctx, device.UserID, device.SigningKey, device.UserID)
if err != nil {
log.Err(err).Stringer("device_id", device.DeviceID).Msg("Failed to get signatures for device")
resp.Errors = append(resp.Errors, fmt.Sprintf("Failed to get signatures for device %s: %v", device.DeviceID, err))
} else if _, signed := signatures[theirSelfSignKey.Key]; signed && device.Trust == id.TrustStateUnset && theirSelfSignKey.Key != "" {
if resp.UserTrusted {
device.Trust = id.TrustStateCrossSignedVerified
} else if theirMasterKey.Key == theirMasterKey.First {
device.Trust = id.TrustStateCrossSignedTOFU
} else {
device.Trust = id.TrustStateCrossSignedUntrusted
}
}
resp.Devices[i] = &ProfileDevice{ resp.Devices[i] = &ProfileDevice{
DeviceID: device.DeviceID, DeviceID: dev.DeviceID,
Name: device.Name, Name: dev.Name,
IdentityKey: device.IdentityKey, IdentityKey: dev.IdentityKey,
SigningKey: device.SigningKey, SigningKey: dev.SigningKey,
Fingerprint: device.Fingerprint(), Fingerprint: dev.Fingerprint(),
Trust: device.Trust, Trust: dev.Trust,
} }
i++
} }
slices.SortFunc(resp.Devices, func(a, b *ProfileDevice) int {
return strings.Compare(a.DeviceID.String(), b.DeviceID.String())
})
return &resp, nil return &resp, nil
} }