docker/cli · error
could not decrypt key
Error message
could not decrypt key
What it means
Returned by decodePrivKeyIfNecessary when trustmanager.GetPasswdDecryptBytes fails to decrypt an encrypted private key (PEM with DEK-Info header or 'ENCRYPTED PRIVATE KEY' type). The passphrase retrieved interactively or from env vars did not match the key's encryption, so decryption failed.
Solutions
- Re-run docker trust key load and enter the correct passphrase at the prompt.
- Set DOCKER_CONTENT_TRUST_REPOSITORY_PASSPHRASE (or ROOT_PASSPHRASE for root keys) to the correct value.
- If the passphrase is truly lost, regenerate a new key and re-add it to the repository's delegation roles.
Example fix
# before: docker trust key load key.priv # wrong passphrase # after: DOCKER_CONTENT_TRUST_REPOSITORY_PASSPHRASE=correctpass docker trust key load key.priv
Defensive patterns
Strategy: retry
Validate before calling
// Before loading, confirm the passphrase env var is set if the key is encrypted
func ensurePassphraseEnv(blockType string) error {
switch blockType {
case "ENCRYPTED PRIVATE KEY":
if os.Getenv("DOCKER_CONTENT_TRUST_REPOSITORY_PASSPHRASE") == "" {
return errors.New("set DOCKER_CONTENT_TRUST_REPOSITORY_PASSPHRASE for this encrypted key")
}
}
return nil
} Try / catch
// Allow a few passphrase attempts via the retriever loop; the PassRetriever
// already supports numAttempts — surface a clear message on final failure.
if errors.Is(err, /* decrypt error */) {
return fmt.Errorf("passphrase incorrect; re-run with the correct DOCKER_CONTENT_TRUST_REPOSITORY_PASSPHRASE: %w", err)
} Prevention
- Record the passphrase used when generating each key.
- Set DOCKER_CONTENT_TRUST_REPOSITORY_PASSPHRASE / ROOT_PASSPHRASE env vars in CI.
- If a passphrase is lost, rotate the key rather than guessing repeatedly.
When it happens
Trigger: Running 'docker trust key load <file>' on a passphrase-protected key and entering the wrong passphrase, or having DOCKER_CONTENT_TRUST_REPOSITORY_PASSPHRASE set to the wrong value. Line 113 fires after GetPasswdDecryptBytes returns an error.
Common situations: Forgot the passphrase used when the key was created; env var passphrase mismatch after a key rotation; copy-paste error in the passphrase; key encrypted with a different tool's default passphrase.
Related errors
- no valid signing keys for delegation roles
- path to a public key must be provided using the `--key` flag
- error: signing keys for remote repository
- error: could not find signing keys for remote repository
- cannot load key from provided file
AI-assisted analysis of docker/cli@4f84911bfe (2026-08-07).
Data as JSON: /api/errors/49e5ce3cf97780f3.
Report an issue: GitHub.
Appendix: source
Thrown at cmd/docker-trust/trust/key_load.go:113
if _, _, err = tufutils.ExtractPrivateKeyAttributes(privKeyBytes); err != nil {
return fmt.Errorf("provided file %s is not a supported private key - to add a signer's public key use docker trust signer add", keyPath)
}
if privKeyBytes, err = decodePrivKeyIfNecessary(privKeyBytes, passRet); err != nil {
return fmt.Errorf("cannot load key from provided file %s: %w", keyPath, err)
}
// Make a reader, rewind the file pointer
return trustmanager.ImportKeys(bytes.NewReader(privKeyBytes), privKeyImporters, keyName, "", passRet)
}
func decodePrivKeyIfNecessary(privPemBytes []byte, passRet notary.PassRetriever) ([]byte, error) {
pemBlock, _ := pem.Decode(privPemBytes)
_, containsDEKInfo := pemBlock.Headers["DEK-Info"]
if containsDEKInfo || pemBlock.Type == "ENCRYPTED PRIVATE KEY" {
// if we do not have enough information to properly import, try to decrypt the key
if _, ok := pemBlock.Headers["path"]; !ok {
privKey, _, err := trustmanager.GetPasswdDecryptBytes(passRet, privPemBytes, "", "encrypted")
if err != nil {
return []byte{}, errors.New("could not decrypt key")
}
privPemBytes = privKey.Private()
}
}
return privPemBytes, nil
}
View on GitHub (pinned to 4f84911bfe)