{"record":{"id":"ec25eef693280181","repo":"docker/cli","slug":"provided-file-s-is-not-a-supported-private-key","errorCode":null,"errorMessage":"provided file %s is not a supported private key - to add a signer's public key use docker trust signer add","messagePattern":"provided file (.+?) is not a supported private key - to add a signer's public key use docker trust signer add","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/docker-trust/trust/key_load.go","lineNumber":96,"sourceCode":"\t\t}\n\t\tif fileInfo.Mode()&nonOwnerReadWriteMask != 0 {\n\t\t\treturn nil, fmt.Errorf(\"private key file %s must not be readable or writable by others\", keyPath)\n\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}","sourceCodeStart":78,"sourceCodeEnd":114,"githubUrl":"https://github.com/docker/cli/blob/4f84911bfe8811e9b028e4b1fee8e7510be79387/cmd/docker-trust/trust/key_load.go#L78-L114","documentation":"In loadPrivKeyBytesToStore (key_load.go:94-97), tufutils.ExtractPrivateKeyAttributes could not parse the bytes as a supported private key PEM (it failed to extract role/attributes). The loader concludes the file is not a supported private key and suggests using 'docker trust signer add' for public keys. This is the first check in the import pipeline.","triggerScenarios":"Loading a file that is actually a PUBLIC key PEM ('PUBLIC KEY' block) rather than a private key; a certificate; an SSH public key; a random text/JSON file; a private key in an unsupported format (e.g. SSH private key, raw DER without PEM envelope, OpenSSH new format); a corrupt or truncated PEM.","commonSituations":"User confused public and private key files and passes the .pub; exported a key in a format notary does not consume (PKCS#8 vs the expected notary/TUF key PEM with role header); downloaded the wrong artifact from a key management system; concatenated/corrupted PEM.","solutions":["Confirm the file is a private key PEM: head -1 <file> should show '-----BEGIN EC PRIVATE KEY-----' or '-----BEGIN RSA PRIVATE KEY-----' / '-----BEGIN PRIVATE KEY-----'.","If you actually have a public key for a signer, use 'docker trust signer add <name> <key.pub> <image>' instead of 'docker trust key load'.","Convert the key to a supported PEM private key format (e.g. openssl ec -in ... -out key.pem) and retry.","Re-export the private key from the original source (notary key export) ensuring it is the private PEM with the role header."],"exampleFix":"# before: passing a public key by mistake\ndocker trust key load mykey.pub\n# after (option A): load the private key\ndocker trust key load mykey.pem\n# after (option B): adding a signer's public key\ndocker trust signer add team-a mykey.pub myrepo/img","handlingStrategy":"type-guard","validationCode":"// Sniff the PEM block type before loading to give a precise error.\nfunc isPrivateKeyPEM(path string) (bool, error) {\n    b, err := os.ReadFile(path)\n    if err != nil {\n        return false, err\n    }\n    block, _ := pem.Decode(b)\n    if block == nil {\n        return false, nil\n    }\n    switch block.Type {\n    case \"EC PRIVATE KEY\", \"RSA PRIVATE KEY\", \"PRIVATE KEY\", \"ENCRYPTED PRIVATE KEY\":\n        return true, nil\n    default:\n        return false, nil\n    }\n}","typeGuard":"// Guard that a file is a private key before invoking load.\nfunc assertPrivateKeyFile(path string) error {\n    ok, err := isPrivateKeyPEM(path)\n    if err != nil {\n        return err\n    }\n    if !ok {\n        return fmt.Errorf(\"provided file %s is not a supported private key - to add a signer's public key use docker trust signer add\", path)\n    }\n    return nil\n}","tryCatchPattern":"if _, _, err := tufutils.ExtractPrivateKeyAttributes(privKeyBytes); err != nil {\n    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)\n}","preventionTips":["Pass the private key PEM to 'docker trust key load' and the public (.pub) to 'docker trust signer add'.","Confirm head -1 <file> shows a PRIVATE KEY PEM header before loading.","Re-export keys in notary's supported PEM format if produced by another tool."],"tags":["docker","notary","content-trust","validation","key-format","pem","private-key"],"backgroundTag":null,"analyzedSha":"4f84911bfe8811e9b028e4b1fee8e7510be79387","analyzedAt":"2026-08-07T12:15:29.814Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}