{"record":{"id":"f302bfd6d987c4d5","repo":"XTLS/Xray-core","slug":"failed-to-decode-key","errorCode":null,"errorMessage":"failed to decode key","messagePattern":"failed to decode key","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"common/protocol/tls/cert/cert.go","lineNumber":34,"sourceCode":"\t\"github.com/xtls/xray-core/common\"\n\t\"github.com/xtls/xray-core/common/errors\"\n)\n\ntype Certificate struct {\n\t// certificate in ASN.1 DER format\n\tCertificate []byte\n\t// Private key in ASN.1 DER format\n\tPrivateKey []byte\n}\n\nfunc ParseCertificate(certPEM []byte, keyPEM []byte) (*Certificate, error) {\n\tcertBlock, _ := pem.Decode(certPEM)\n\tif certBlock == nil {\n\t\treturn nil, errors.New(\"failed to decode certificate\")\n\t}\n\tkeyBlock, _ := pem.Decode(keyPEM)\n\tif keyBlock == nil {\n\t\treturn nil, errors.New(\"failed to decode key\")\n\t}\n\treturn &Certificate{\n\t\tCertificate: certBlock.Bytes,\n\t\tPrivateKey:  keyBlock.Bytes,\n\t}, nil\n}\n\nfunc (c *Certificate) ToPEM() ([]byte, []byte) {\n\treturn pem.EncodeToMemory(&pem.Block{Type: \"CERTIFICATE\", Bytes: c.Certificate}),\n\t\tpem.EncodeToMemory(&pem.Block{Type: \"RSA PRIVATE KEY\", Bytes: c.PrivateKey})\n}\n\ntype Option func(*x509.Certificate)\n\nfunc Authority(isCA bool) Option {\n\treturn func(cert *x509.Certificate) {\n\t\tcert.IsCA = isCA\n\t}","sourceCodeStart":16,"sourceCodeEnd":52,"githubUrl":"https://github.com/XTLS/Xray-core/blob/7d214f8b094f75322fa3990f8aadad1c912f24f5/common/protocol/tls/cert/cert.go#L16-L52","documentation":"Returned by ParseCertificate when pem.Decode finds no PEM block in the private-key input. The key material must be a PEM block (e.g. RSA/EC PRIVATE KEY or PKCS#8); anything else fails here. Note the parser assumes RSA-style single-block keys (ToPEM re-encodes as 'RSA PRIVATE KEY').","triggerScenarios":"Calling ParseCertificate with a DER-encoded key, an empty keyPEM, or a modern PKCS#8 'PRIVATE KEY' file can still decode as a PEM block - but encrypted ('ENCRYPTED PRIVATE KEY') or non-PEM input returns nil from pem.Decode and triggers this error.","commonSituations":"Using an encrypted private key without decrypting it first, key files in DER format, or an empty key file due to a bad deploy.","solutions":["Ensure the key is an unencrypted PEM private key: `openssl rsa -in key.pem -check -noout`","Decrypt encrypted keys first: `openssl rsa -in encrypted.pem -out plain.pem`","Convert DER keys: `openssl rsa -inform der -in key.der -out key.pem`"],"exampleFix":"# decrypt an encrypted key before use\nopenssl rsa -in encrypted_key.pem -out key.pem","handlingStrategy":"validation","validationCode":"block, _ := pem.Decode(keyPEM)\nif block == nil || block.Type == \"ENCRYPTED PRIVATE KEY\" {\n    return errors.New(\"key must be an unencrypted PEM private key\")\n}","typeGuard":"func isPEMPrivateKey(b []byte) bool { block, _ := pem.Decode(b); return block != nil && strings.HasSuffix(block.Type, \"PRIVATE KEY\") }","tryCatchPattern":null,"preventionTips":["Decrypt keys before config load (openssl rsa)","Reject encrypted PKCS#8 upfront in config validation"],"tags":["tls","private-key","pem","parsing"],"backgroundTag":null,"analyzedSha":"7d214f8b094f75322fa3990f8aadad1c912f24f5","analyzedAt":"2026-08-15T14:26:24.325Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}