{"record":{"id":"0e11976217932a29","repo":"apache/pulsar","slug":"unable-to-find-ec-parameter-for-the-given-curve-oi","errorCode":null,"errorMessage":"Unable to find EC Parameter for the given curve oid: ${ecOID.getId()}","messagePattern":"Unable to find EC Parameter for the given curve oid: (.+?)","errorType":"exception","errorClass":"PEMException","httpStatus":null,"severity":"error","filePath":"pulsar-client-messagecrypto-bc/src/main/java/org/apache/pulsar/client/impl/crypto/MessageCryptoBc.java","lineNumber":275,"sourceCode":"    }\n\n    public static PublicKey loadPublicKey(byte[] keyBytes) throws Exception {\n        Reader keyReader = new StringReader(new String(keyBytes));\n        PublicKey publicKey;\n        try (PEMParser pemReader = new PEMParser(keyReader)) {\n            Object pemObj = pemReader.readObject();\n            JcaPEMKeyConverter pemConverter = new JcaPEMKeyConverter().setProvider(bcProvider());\n            SubjectPublicKeyInfo keyInfo;\n            X9ECParameters ecParam = null;\n\n            if (pemObj instanceof ASN1ObjectIdentifier) {\n                // make sure this is EC Parameter we're handling. In which case\n                // we'll store it and read the next object which should be our\n                // EC Public Key\n                ASN1ObjectIdentifier ecOID = (ASN1ObjectIdentifier) pemObj;\n                ecParam = ECNamedCurveTable.getByOID(ecOID);\n                if (ecParam == null) {\n                    throw new PEMException(\"Unable to find EC Parameter for the given curve oid: \" + ecOID.getId());\n                }\n                pemObj = pemReader.readObject();\n            } else if (pemObj instanceof X9ECParameters) {\n                ecParam = (X9ECParameters) pemObj;\n                pemObj = pemReader.readObject();\n            }\n\n            if (pemObj instanceof X509CertificateHolder) {\n                keyInfo = ((X509CertificateHolder) pemObj).getSubjectPublicKeyInfo();\n            } else {\n                keyInfo = (SubjectPublicKeyInfo) pemObj;\n            }\n            publicKey = pemConverter.getPublicKey(keyInfo);\n\n            if (ecParam != null && ECDSA.equals(publicKey.getAlgorithm())) {\n                ECParameterSpec ecSpec = new ECParameterSpec(ecParam.getCurve(), ecParam.getG(), ecParam.getN(),\n                        ecParam.getH(), ecParam.getSeed());\n                KeyFactory keyFactory = KeyFactory.getInstance(ECDSA, bcProvider());","sourceCodeStart":257,"sourceCodeEnd":293,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/pulsar-client-messagecrypto-bc/src/main/java/org/apache/pulsar/client/impl/crypto/MessageCryptoBc.java#L257-L293","documentation":"During PEM public-key parsing in MessageCryptoBc.loadPublicKey, an ASN1ObjectIdentifier representing an EC curve OID was read from the PEM file, but BouncyCastle's ECNamedCurveTable.getByOID could not resolve it to a known curve's X9ECParameters. The library only supports named curves registered with BouncyCastle, so it throws PEMException rather than continuing with an unknown curve. This means the key file references an EC curve the bundled BC provider does not know by that OID.","triggerScenarios":"Calling addPublicKeyCipher(keyName, keyReader) where keyReader.getPublicKey returns key bytes whose PEM EC public key header contains an ECParameters OID that ECNamedCurveTable does not resolve (unrecognized curve OID, e.g. a curve absent from the BC version in use, or a malformed/typo'd OID).","commonSituations":"Producers with ECDSA encryption keys generated with an unusual or exotic curve (e.g. secp256k1 or a custom curve not in BC's named table for the bundled BC version); key files edited or regenerated after a BouncyCastle version change; copying an OID string incorrectly into a hand-written key file.","solutions":["Regenerate the key pair with a standard named curve supported by BouncyCastle, e.g. prime256v1 (P-256) or secp384r1: openssl ecparam -name prime256v1 -genkey -noout -out private.pem","Verify the curve OID in the PEM file: openssl asn1parse -in key.pem and confirm it maps to a named curve BC knows","Upgrade/realign the BouncyCastle dependency so ECNamedCurveTable contains the curve referenced by the key","Confirm the key file actually contains an EC public key and was not truncated or corrupted during distribution"],"exampleFix":"// before: key generated with unsupported curve\nopenssl ecparam -name secp256k1 -genkey -noout -out mykey.pem\n// after: use a BC-supported named curve\nopenssl ecparam -name prime256v1 -genkey -noout -out mykey.pem","handlingStrategy":"validation","validationCode":"// Check the PEM's curve is a BC named curve before calling addPublicKeyCipher\nASN1ObjectIdentifier oid = /* parse from PEM */;\nif (org.bouncycastle.asn1.ec.ECNamedCurveTable.getByOID(oid) == null) {\n    throw new IllegalArgumentException(\"Unsupported EC curve OID: \" + oid.getId() +\n        \"; regenerate key with prime256v1 or secp384r1\");\n}","typeGuard":null,"tryCatchPattern":"try {\n    crypto.addPublicKeyCipher(keyName, keyReader);\n} catch (PulsarClientException.CryptoException | org.bouncycastle.openssl.PEMException e) {\n    log.error(\"EC key rejected (unsupported curve?): {}\", e.getMessage());\n}","preventionTips":["Generate EC keys only with standard named curves: prime256v1, secp384r1, secp521r1","Run openssl asn1parse -in key.pem once when onboarding a key to confirm the curve OID","Pin and test against the exact BouncyCastle version bundled with your Pulsar client","Validate all encryption keys at application startup, not at first publish"],"tags":["crypto","ecdsa","pem","key-parsing","bouncycastle"],"backgroundTag":"unsupported-ec-curve-oid","analyzedSha":"820761864ed8e2a7d2e52dd9763ad2ae117c1395","analyzedAt":"2026-09-06T00:14:20.138Z","contentChangedAt":"2026-09-06T00:14:20.138Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}