{"record":{"id":"f33c744fa57eb4f1","repo":"docker/cli","slug":"cannot-load-key-from-provided-file-s-w","errorCode":null,"errorMessage":"cannot load key from provided file %s: %w","messagePattern":"cannot load key from provided file (.+?): %w","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/docker-trust/trust/key_load.go","lineNumber":99,"sourceCode":"\t\t}\n\t}\n\n\tfrom, err := os.OpenFile(keyPath, os.O_RDONLY, notary.PrivExecPerms)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tdefer from.Close()\n\n\treturn io.ReadAll(from)\n}\n\nfunc loadPrivKeyBytesToStore(privKeyBytes []byte, privKeyImporters []trustmanager.Importer, keyPath, keyName string, passRet notary.PassRetriever) error {\n\tvar err error\n\tif _, _, err = tufutils.ExtractPrivateKeyAttributes(privKeyBytes); err != nil {\n\t\treturn fmt.Errorf(\"provided file %s is not a supported private key - to add a signer's public key use docker trust signer add\", keyPath)\n\t}\n\tif privKeyBytes, err = decodePrivKeyIfNecessary(privKeyBytes, passRet); err != nil {\n\t\treturn fmt.Errorf(\"cannot load key from provided file %s: %w\", keyPath, err)\n\t}\n\t// Make a reader, rewind the file pointer\n\treturn trustmanager.ImportKeys(bytes.NewReader(privKeyBytes), privKeyImporters, keyName, \"\", passRet)\n}\n\nfunc decodePrivKeyIfNecessary(privPemBytes []byte, passRet notary.PassRetriever) ([]byte, error) {\n\tpemBlock, _ := pem.Decode(privPemBytes)\n\t_, containsDEKInfo := pemBlock.Headers[\"DEK-Info\"]\n\tif containsDEKInfo || pemBlock.Type == \"ENCRYPTED PRIVATE KEY\" {\n\t\t// if we do not have enough information to properly import, try to decrypt the key\n\t\tif _, ok := pemBlock.Headers[\"path\"]; !ok {\n\t\t\tprivKey, _, err := trustmanager.GetPasswdDecryptBytes(passRet, privPemBytes, \"\", \"encrypted\")\n\t\t\tif err != nil {\n\t\t\t\treturn []byte{}, errors.New(\"could not decrypt key\")\n\t\t\t}\n\t\t\tprivPemBytes = privKey.Private()\n\t\t}\n\t}","sourceCodeStart":81,"sourceCodeEnd":117,"githubUrl":"https://github.com/docker/cli/blob/4f84911bfe8811e9b028e4b1fee8e7510be79387/cmd/docker-trust/trust/key_load.go#L81-L117","documentation":"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>'.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Enter the correct passphrase that was used to encrypt the key file (distinct from the repo passphrase used by the trust store).","If the key should be unencrypted, re-export it without encryption (openssl ec -in enc.pem -out plain.pem) and load the unencrypted file.","Remove a conflicting DOCKER_CONTENT_TRUST_REPOSITORY_PASSPHRASE if it is being auto-supplied and is wrong, so you are prompted interactively.","Verify the PEM is not corrupt (openssl ec -in <file> -noout to test decryption with the known passphrase)."],"exampleFix":"# before: wrong passphrase for an encrypted key\ndocker trust key load enc-priv.key  # -> cannot load key (could not decrypt)\n# after (option A): supply correct passphrase interactively\n# after (option B): decrypt the key first, then load\nopenssl ec -in enc-priv.key -out plain-priv.key\ndocker trust key load plain-priv.key","handlingStrategy":"validation","validationCode":"// Probe decryption with a candidate passphrase before importing.\nfunc canDecryptKey(path, passphrase string) error {\n    b, err := os.ReadFile(path)\n    if err != nil {\n        return err\n    }\n    block, _ := pem.Decode(b)\n    if block == nil {\n        return errors.New(\"not a PEM file\")\n    }\n    _, hasDEK := block.Headers[\"DEK-Info\"]\n    if !hasDEK && block.Type != \"ENCRYPTED PRIVATE KEY\" {\n        return nil // unencrypted\n    }\n    if _, ok := block.Headers[\"path\"]; ok {\n        return nil // notary-managed, decryption handled by store\n    }\n    // Attempt decrypt with the candidate passphrase.\n    if _, _, err := trustmanager.GetPasswdDecryptBytes(fixedPassRetriever(passphrase), b, \"\", \"encrypted\"); err != nil {\n        return fmt.Errorf(\"wrong passphrase or unsupported encryption: %w\", err)\n    }\n    return nil\n}","typeGuard":null,"tryCatchPattern":"if privKeyBytes, err = decodePrivKeyIfNecessary(privKeyBytes, passRet); err != nil {\n    return fmt.Errorf(\"cannot load key from provided file %s: %w\", keyPath, err)\n}","preventionTips":["Know the passphrase that originally encrypted the key file (it may differ from the repo passphrase).","If unsure, decrypt the key with openssl first and load the unencrypted PEM.","Avoid passing an unrelated DOCKER_CONTENT_TRUST_REPOSITORY_PASSPHRASE that hijacks the interactive prompt.","Test decryption with 'openssl ec -in <file> -noout' before loading."],"tags":["docker","notary","content-trust","encryption","passphrase","private-key","decryption"],"backgroundTag":null,"analyzedSha":"4f84911bfe8811e9b028e4b1fee8e7510be79387","analyzedAt":"2026-08-07T12:15:29.814Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}