{"record":{"id":"a4f66a66d2dcd4f1","repo":"siyuan-note/siyuan","slug":"failed-to-decode-ca-key-pem","errorCode":null,"errorMessage":"failed to decode CA key PEM","messagePattern":"failed to decode CA key PEM","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/util/cert.go","lineNumber":274,"sourceCode":"\n\tblock, _ := pem.Decode(certPEM)\n\tif block == nil {\n\t\treturn nil, nil, fmt.Errorf(\"failed to decode CA certificate PEM\")\n\t}\n\n\tcaCert, err := x509.ParseCertificate(block.Bytes)\n\tif err != nil {\n\t\treturn nil, nil, err\n\t}\n\n\tkeyPEM, err := os.ReadFile(keyPath)\n\tif err != nil {\n\t\treturn nil, nil, err\n\t}\n\n\tblock, _ = pem.Decode(keyPEM)\n\tif block == nil {\n\t\treturn nil, nil, fmt.Errorf(\"failed to decode CA key PEM\")\n\t}\n\n\tcaKey, err := x509.ParseECPrivateKey(block.Bytes)\n\tif err != nil {\n\t\treturn nil, nil, err\n\t}\n\n\treturn caCert, caKey, nil\n}\n\nfunc writeCertAndKey(certPath, keyPath string, certDER []byte, privateKey *ecdsa.PrivateKey) error {\n\tcertFile, err := os.Create(certPath)\n\tif err != nil {\n\t\treturn err\n\t}\n\tdefer certFile.Close()\n\n\tif err = pem.Encode(certFile, &pem.Block{Type: \"CERTIFICATE\", Bytes: certDER}); err != nil {","sourceCodeStart":256,"sourceCodeEnd":292,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/8641553a1f07374001902d3ce773285db1292b2d/kernel/util/cert.go#L256-L292","documentation":"loadCA decodes the CA private key with pem.Decode and returns this error when the key bytes are not valid PEM. A decodable block is then parsed as an EC private key, so anything other than a PEM 'EC PRIVATE KEY' (or encrypted/foreign format) fails either here or in the subsequent ParseECPrivateKey.","triggerScenarios":"GetOrCreateTLSCert or refreshCertificate loading a CA key file that is empty, holds the certificate instead of the key, contains a PKCS#1 RSA key or an encrypted PEM where an unencrypted EC key is expected, or has lost its -----BEGIN ... PRIVATE KEY----- armor.","commonSituations":"Manually generated CA where the key was saved in another format (RSA instead of EC, PKCS#8); key file truncated or overwritten during rotation; wrong-path config mixing up cert and key files.","solutions":["Ensure the CA key file contains an unencrypted PEM EC private key (-----BEGIN EC PRIVATE KEY-----)","Regenerate the CA and server certificate pair so formats match what the kernel generates","Convert if needed: openssl ec -in key.pem -out ec-key.pem; verify with openssl ec -in ec-key.pem -check -noout"],"exampleFix":"// before: RSA PKCS#1 key saved as the CA key\ncaKeyPEM, _ := os.ReadFile(\"ca-rsa-key.pem\") // -----BEGIN RSA PRIVATE KEY-----\n// after: matching EC key as produced by the kernel\ncaKeyPEM, _ := os.ReadFile(\"ca.key\") // -----BEGIN EC PRIVATE KEY-----","handlingStrategy":"validation","validationCode":"const fs = require(\"fs\");\nconst pem = fs.readFileSync(caKeyPath, \"utf8\");\nif (!pem.includes(\"-----BEGIN EC PRIVATE KEY-----\")) {\n  throw new Error(`${caKeyPath} is not an unencrypted PEM EC private key`);\n}","typeGuard":null,"tryCatchPattern":"caCert, caKey, err := loadCA(caCertPath, caKeyPath)\nif err != nil {\n  log.Errorf(\"load CA key failed: %v\", err)\n  return nil, err\n}","preventionTips":["Generate CA keys as unencrypted EC keys matching the loader's expectation","Do not convert or re-export keys to RSA/PKCS#8 formats before handing them to the kernel","Verify with `openssl ec -in ca.key -check -noout` before use"],"tags":["tls","pem","private-key"],"backgroundTag":"invalid-argument-format","analyzedSha":"8641553a1f07374001902d3ce773285db1292b2d","analyzedAt":"2026-09-11T16:08:28.414Z","contentChangedAt":"2026-09-11T16:08:28.414Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}