From 4b35e4cc8a023c02da792da8e46fc539d0b33319 Mon Sep 17 00:00:00 2001 From: Kenneth Skovhede Date: Mon, 29 Jun 2026 15:21:11 +0200 Subject: [PATCH] Prevent creating a useless key This PR changes the creation order slightly, such that a new key is not created, if the database is encrypted. This is done to prevent creating a new random key, and then attempting to decrypt an existing encrypted database. This will naturally always fail, but first store a random key in the secret manager. Having a new (useless) key stored in the secret manager does not break anything but is confusing. This PR changes the logic so the useless key is not generated in the first place. --- Duplicati/Server/Program.cs | 48 +++++++++++++++++++------------------ 1 file changed, 25 insertions(+), 23 deletions(-) diff --git a/Duplicati/Server/Program.cs b/Duplicati/Server/Program.cs index c4a3b4313..ff78b0065 100644 --- a/Duplicati/Server/Program.cs +++ b/Duplicati/Server/Program.cs @@ -1160,6 +1160,29 @@ namespace Duplicati.Server disableDbEncryption = true; } + var hasEncryptedFields = false; + var warnedAboutEncryptedDb = false; + try + { + using (var cmd = con.CreateCommand(@$"SELECT ""Value"" FROM ""Option"" WHERE ""Name"" = @Name AND ""BackupID"" = @BackupId")) + hasEncryptedFields = Library.Utility.Utility.ParseBool(cmd + .SetParameterValue("@Name", Database.ServerSettings.CONST.ENCRYPTED_FIELDS) + .SetParameterValue("@BackupId", Connection.SERVER_SETTINGS_ID).ExecuteScalar()?.ToString(), false); + + if (hasEncryptedFields && !hasValidEncryptionKey) + { + warnedAboutEncryptedDb = true; + Log.WriteWarningMessage(LOGTAG, "EncryptionKeyMissing", null, Strings.Program.EncryptionKeyMissing(EncryptedFieldHelper.ENVIROMENT_VARIABLE_NAME)); + if (!silentConsole) + Console.WriteLine(Strings.Program.EncryptionKeyMissing(EncryptedFieldHelper.ENVIROMENT_VARIABLE_NAME)); + } + } + catch + { + // Ignore errors here, as we are just checking for a potential issue + // Only negative effect is that we do not show a potentially helpful warning + } + var defaultSecretProvider = SecretProviderHelper.GetDefaultSecretProviderAsync(commandlineOptions, CancellationToken.None).Await(); // If we are supposed to have an encryption key, but do not, try to get it from the (default) secret provider @@ -1178,7 +1201,8 @@ namespace Duplicati.Server } // If there is no encryption key, and the secret provider supports setting secrets, try to set the encryption key - if (!disableDbEncryption && string.IsNullOrWhiteSpace(encryptionKey) && defaultSecretProvider.IsSetSupported) + // Avoid generating a new key if the database is already encrypted as this will make a new key that will not work + if (!disableDbEncryption && string.IsNullOrWhiteSpace(encryptionKey) && defaultSecretProvider.IsSetSupported && !hasEncryptedFields) { var tmpkey = Convert.ToBase64String(System.Security.Cryptography.RandomNumberGenerator.GetBytes(32)); try @@ -1218,28 +1242,6 @@ namespace Duplicati.Server applicationSettings.SettingsEncryptionKeyProvidedExternally = hasValidEncryptionKey; - var hasEncryptedFields = false; - var warnedAboutEncryptedDb = false; - try - { - using (var cmd = con.CreateCommand(@$"SELECT ""Value"" FROM ""Option"" WHERE ""Name"" = @Name AND ""BackupID"" = @BackupId")) - hasEncryptedFields = Library.Utility.Utility.ParseBool(cmd - .SetParameterValue("@Name", Database.ServerSettings.CONST.ENCRYPTED_FIELDS) - .SetParameterValue("@BackupId", Connection.SERVER_SETTINGS_ID).ExecuteScalar()?.ToString(), false); - - if (hasEncryptedFields && !hasValidEncryptionKey) - { - warnedAboutEncryptedDb = true; - Log.WriteWarningMessage(LOGTAG, "EncryptionKeyMissing", null, Strings.Program.EncryptionKeyMissing(EncryptedFieldHelper.ENVIROMENT_VARIABLE_NAME)); - if (!silentConsole) - Console.WriteLine(Strings.Program.EncryptionKeyMissing(EncryptedFieldHelper.ENVIROMENT_VARIABLE_NAME)); - } - } - catch - { - // Ignore errors here, as we are just checking for a potential issue - // Only negative effect is that we do not show a potentially helpful warning - } if (!hasValidEncryptionKey && !disableDbEncryption) {