duplicati/duplicati · error · InvalidOperationException

Refusing to encrypt with blacklisted key

Error message

Refusing to encrypt with blacklisted key

What it means

Thrown by EncryptedFieldHelper.Encrypt when the supplied KeyInstance has IsBlacklisted == true. KeyInstance.CreateKey computes IsBlacklisted via IsKeyBlacklisted(key) at creation time, so this guards against re-encrypting data with a key known to be compromised or weak. The exception is InvalidOperationException with Strings.EncryptedFieldHelper.KeyBlacklistedError.

Source

Thrown at Duplicati/Library/Encryption/EncryptedFieldHelper.cs:163

        // if the hashes don't match, the lenght criteria can be ignored,
        // and it will be returned as is.
        return value;

    }

    /// <summary>
    /// Encrypts a value to be stored in the database.
    /// </summary>
    /// <param name="value"></param>
    /// <param name="key">The key to use for encryption</param>
    /// <returns>The encrypted string</returns>
    public static string Encrypt(string value, KeyInstance? key)
    {
        if (key == null)
            throw new SettingsEncryptionKeyMissingException();

        if (key.IsBlacklisted)
            throw new InvalidOperationException(Strings.EncryptedFieldHelper.KeyBlacklistedError);

        using var hasher = HashFactory.CreateHasher(HashFactory.SHA256);
        var encrypted = AESStringEncryption.EncryptToHex(key.Key, value);

        var sb = new StringBuilder();
        sb.Append(HEADER_PREFIX);
        sb.Append(encrypted.ComputeHashToHex(hasher));
        sb.Append(key.Hash);
        sb.Append(encrypted);

        return sb.ToString();
    }

}

View on GitHub (pinned to 3f348be3e3)

Solutions

  1. Rotate to a new, non-blacklisted key and obtain a fresh KeyInstance via CreateKey.
  2. Re-encrypt existing data with the new key during a migration pass.
  3. Remove the old key reference from any live objects after rotation so Encrypt is never called with it.

Example fix

// before
var cipher = EncryptedFieldHelper.Encrypt(value, oldKey); // oldKey.IsBlacklisted == true

// after
var newKey = EncryptedFieldHelper.KeyInstance.CreateKey(GenerateStrongKey());
var cipher = EncryptedFieldHelper.Encrypt(value, newKey);
Defensive patterns

Strategy: validation

Validate before calling

if (key == null || key.IsBlacklisted)
    key = EncryptedFieldHelper.KeyInstance.CreateKey(GenerateStrongKey()); // rotate
var cipher = EncryptedFieldHelper.Encrypt(value, key);

Type guard

bool IsUsableKey(EncryptedFieldHelper.KeyInstance k) => !k.IsBlacklisted;

Try / catch

try { cipher = EncryptedFieldHelper.Encrypt(value, key); }
catch (InvalidOperationException ex) when (ex.Message.Contains("blacklisted"))
{
    logger.LogError("Refusing to use blacklisted key; rotate to a new key.");
    throw;
}

Prevention

When it happens

Trigger: Calling Encrypt(value, key) where key.IsBlacklisted is true (the key string matched the blacklist checked at CreateKey time).

Common situations: A previously-used key was added to the blacklist after a security incident; default/well-known weak keys are blacklisted by the application; attempting to write settings while still holding a reference to an old key instance.

Related errors


AI-assisted analysis of duplicati/duplicati@3f348be3e3 (2026-08-13). Data as JSON: /api/errors/8618778c6f4a130a. Report an issue: GitHub.