Compare commits

...

3 Commits

Author SHA1 Message Date
R Midhun Suresh
0a6fdc2eee Enable plain text encryption as early as possible 2025-05-22 17:11:27 +05:30
R Midhun Suresh
58403c94ce Move store creation into migration methods 2025-05-22 16:09:26 +05:30
R Midhun Suresh
d6893695d4 Use basic_text as fallback when encryption not available
Show the user a dialog and fallback to using basic_text temporarily when
a valid backend is available but encryption support is not.
2025-05-22 16:09:14 +05:30
2 changed files with 45 additions and 10 deletions

View File

@@ -56,6 +56,9 @@
"backend_changed": "Clear data and reload?",
"backend_changed_detail": "Unable to access secret from system keyring, it appears to have changed.",
"backend_changed_title": "Failed to load database",
"backend_no_encryption": "Your system has a supported keyring but encryption is not available.",
"backend_no_encryption_detail": "Electron has detected that encryption is not available on your keyring %(backend)s. Please ensure that you have the keyring installed. If you do have the keyring installed, please reboot and try again. Optionally, you can allow %(brand)s to use a weaker form of encryption.",
"backend_no_encryption_title": "No encryption support",
"unknown_backend_override": "Your system has an unsupported keyring meaning the database cannot be opened.",
"unknown_backend_override_details": "Please check the logs for more details.",
"unknown_backend_override_title": "Failed to load database",

View File

@@ -241,8 +241,9 @@ class Store extends ElectronStore<StoreData> {
// Linux safeStorage support is hellish, the support varies on the Desktop Environment used rather than the store itself.
// https://github.com/electron/electron/issues/39789 https://github.com/microsoft/vscode/issues/185212
const selectedSafeStorageBackend = safeStorage.getSelectedStorageBackend();
const isEncryptionAvailable = safeStorage.isEncryptionAvailable();
console.info(
`safeStorage backend '${selectedSafeStorageBackend}' selected, '${safeStorageBackend}' in config.`,
`safeStorage backend '${selectedSafeStorageBackend}' selected, '${safeStorageBackend}' in config, isEncryptionAvailable = ${isEncryptionAvailable}.`,
);
if (selectedSafeStorageBackend === "unknown") {
@@ -260,7 +261,44 @@ class Store extends ElectronStore<StoreData> {
return this.upgradeLinuxBackend2();
}
if (!safeStorageBackend) {
// The following enables plain text encryption if the backend used is basic_text.
// It has no significance for any other backend.
// We do this early so that in case we end up using the basic_text backend (either because that's the only one available
// or as a fallback when the configured backend lacks encryption support), encryption is already turned on.
safeStorage.setUsePlainTextEncryption(true);
// Whether we were using basic_text as a fallback before
const usingFallback = this.get("safeStorageBackendOverride") && safeStorageBackend === "basic_text";
if (this.mode === Mode.Encrypted && !isEncryptionAvailable && !usingFallback) {
// Sometimes we may have a working backend that for some reason does not support encryption at the moment.
// This may be because electron reported an incorrect backend or because of some known issues with the keyring itself.
// In any case, when this happens, we give the user an option to use a weaker form of encryption.
const { response } = await dialog.showMessageBox({
title: _t("store|error|backend_no_encryption_title"),
message: _t("store|error|backend_no_encryption"),
detail: _t("store|error|backend_no_encryption_detail", {
backend: safeStorageBackend,
brand: global.vectorConfig.brand || "Element",
}),
type: "error",
buttons: [_t("action|cancel"), _t("store|error|unsupported_keyring_cta")],
defaultId: 0,
cancelId: 0,
});
if (response === 0) {
throw new Error(
`Encryption support not available on backend ${safeStorageBackend} and user prohibits using weaker encryption.`,
);
}
this.recordSafeStorageBackend("basic_text");
this.set("safeStorageBackendOverride", true);
relaunchApp();
} else if (usingFallback) {
// On the next run, don't use the fallback.
// This is so that we can check if the problems with the keyring fixed itself.
this.set("safeStorageBackendOverride", false);
} else if (!safeStorageBackend) {
if (selectedSafeStorageBackend === "basic_text" && this.mode === Mode.Encrypted) {
const { response } = await dialog.showMessageBox({
title: _t("store|error|unsupported_keyring_title"),
@@ -311,12 +349,6 @@ class Store extends ElectronStore<StoreData> {
await clearDataAndRelaunch();
}
}
// We do not check allowPlaintextStorage here as it was already checked above if the storage is new
// and if the storage is existing then we should continue to honour the backend used to write the data
if (safeStorageBackend === "basic_text" && selectedSafeStorageBackend === safeStorageBackend) {
safeStorage.setUsePlainTextEncryption(true);
}
} else if (!safeStorageBackend) {
safeStorageBackend = this.mode === Mode.Encrypted ? "system" : "plaintext";
this.recordSafeStorageBackend(safeStorageBackend);
@@ -349,7 +381,7 @@ class Store extends ElectronStore<StoreData> {
relaunchApp();
}
private upgradeLinuxBackend2(): void {
if (!this.secrets) throw new Error("safeStorage not ready");
this.secrets = new PlaintextStorageWriter(this);
console.info("Performing safeStorage migration");
const data = this.get("safeStorage");
if (data) {
@@ -362,7 +394,7 @@ class Store extends ElectronStore<StoreData> {
relaunchApp();
}
private upgradeLinuxBackend3(): void {
if (!this.secrets) throw new Error("safeStorage not ready");
this.secrets = new PlaintextStorageWriter(this);
const selectedSafeStorageBackend = safeStorage.getSelectedStorageBackend();
console.info(`Finishing safeStorage migration to ${selectedSafeStorageBackend}`);
const data = this.get("safeStorage");