docker/cli · error

cannot load key from provided file

Error message

cannot load key from provided file %s: %w

What it means

In loadPrivKeyBytesToStore (key_load.go:98-100), the file passed the private-key attribute extraction (so it looks like a private key) but decodePrivKeyIfNecessary failed. decodePrivKeyIfNecessary (key_load.go:105-118) detects encrypted PEM (DEK-Info header or 'ENCRYPTED PRIVATE KEY' type) and, when there is no 'path' header, calls trustmanager.GetPasswdDecryptBytes to decrypt; if that returns an error it returns the hard-coded 'could not decrypt key', which is then wrapped as 'cannot load key from provided file <path>'.

Solutions

  1. Enter the correct passphrase that was used to encrypt the key file (distinct from the repo passphrase used by the trust store).
  2. If the key should be unencrypted, re-export it without encryption (openssl ec -in enc.pem -out plain.pem) and load the unencrypted file.
  3. Remove a conflicting DOCKER_CONTENT_TRUST_REPOSITORY_PASSPHRASE if it is being auto-supplied and is wrong, so you are prompted interactively.
  4. Verify the PEM is not corrupt (openssl ec -in <file> -noout to test decryption with the known passphrase).

Example fix

# before: wrong passphrase for an encrypted key
docker trust key load enc-priv.key  # -> cannot load key (could not decrypt)
# after (option A): supply correct passphrase interactively
# after (option B): decrypt the key first, then load
openssl ec -in enc-priv.key -out plain-priv.key
docker trust key load plain-priv.key
Defensive patterns

Strategy: validation

Validate before calling

// Probe decryption with a candidate passphrase before importing.
func canDecryptKey(path, passphrase string) error {
    b, err := os.ReadFile(path)
    if err != nil {
        return err
    }
    block, _ := pem.Decode(b)
    if block == nil {
        return errors.New("not a PEM file")
    }
    _, hasDEK := block.Headers["DEK-Info"]
    if !hasDEK && block.Type != "ENCRYPTED PRIVATE KEY" {
        return nil // unencrypted
    }
    if _, ok := block.Headers["path"]; ok {
        return nil // notary-managed, decryption handled by store
    }
    // Attempt decrypt with the candidate passphrase.
    if _, _, err := trustmanager.GetPasswdDecryptBytes(fixedPassRetriever(passphrase), b, "", "encrypted"); err != nil {
        return fmt.Errorf("wrong passphrase or unsupported encryption: %w", err)
    }
    return nil
}

Try / catch

if privKeyBytes, err = decodePrivKeyIfNecessary(privKeyBytes, passRet); err != nil {
    return fmt.Errorf("cannot load key from provided file %s: %w", keyPath, err)
}

Prevention

When it happens

Trigger: Loading an encrypted private key PEM where the supplied passphrase is wrong, the passphrase retriever errored, or the encryption parameters (DEK-Info/cipher) are unsupported/corrupt. The interactive passphrase prompt was given the wrong value, or DOCKER_CONTENT_TRUST_REPOSITORY_PASSPHRASE does not match the key's encryption passphrase.

Common situations: Wrong passphrase entered at the prompt; env var passphrase mismatch; key was encrypted with a different passphrase than the one configured; copy/paste error in the passphrase; key encrypted with an algorithm the notary crypto layer cannot decrypt.

Related errors


AI-assisted analysis of docker/cli@4f84911bfe (2026-08-07). Data as JSON: /api/errors/f33c744fa57eb4f1. Report an issue: GitHub.

Appendix: source

Thrown at cmd/docker-trust/trust/key_load.go:99

		}
	}

	from, err := os.OpenFile(keyPath, os.O_RDONLY, notary.PrivExecPerms)
	if err != nil {
		return nil, err
	}
	defer from.Close()

	return io.ReadAll(from)
}

func loadPrivKeyBytesToStore(privKeyBytes []byte, privKeyImporters []trustmanager.Importer, keyPath, keyName string, passRet notary.PassRetriever) error {
	var err error
	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()
		}
	}

View on GitHub (pinned to 4f84911bfe)