Reading elliptic curve private key from file with BouncyCastle

Posted on

Reading elliptic curve private key from file with BouncyCastleError is an illegal operation performed by the user which results in the abnormal working of the program. By now, you’ve probably seen a few errors, either when compiling or running your code like Reading elliptic curve private key from file with BouncyCastle. It can be frustrating, but they can also give you a lot of information about exactly how you can fix the problems in your code about java and openssl. In this post covers the types of errors you’ll see when programming in Java, and how to fix them. Don’t pay any attention to the number of errors. Just read the first error message and work on fixing that error.

Problem :

The BouncyCastle cryptography APIs allow for creating and verifying digital signatures using the regular package objects, such as, and their container

Suppose I use OpenSSL to create a .pem (or, if easier, a .der file) containing the elliptic curve private key I want to use in my application. For example, it looks like this:


How do I use the BouncyCastle APIs to obtain a containing both this private key and a corresponding public key?

Please note I want to use the APIs available in BouncyCastle 1.50 (which is current at the time of writing) and no deprecated APIs. This unfortunately excludes the PEMReader class used in other SO answers. Furthermore, this question is specific to the format of elliptic curves; they contain additional parameters when compared RSA or DSA key files.

Solution :

In addition to the standard JCE approach shown by divanov as long as you give it the correct input (see my comment thereto), or just using JCE in the first place like your selfanswer, BouncyCastle 1.48 up DOES still contain the old PEMReader functionality just organized a bit differently and for this case you can use something like:

static void SO22963581BCPEMPrivateEC () throws Exception {
    Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
    Reader rdr = new StringReader ("-----BEGIN EC PRIVATE KEY-----n"
            +"GDxlA0AavdVDuoGXxNQPIed3FxPE3Q==n"+"-----END EC PRIVATE KEY-----n");
    Object parsed = new org.bouncycastle.openssl.PEMParser(rdr).readObject();
    KeyPair pair = new org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter().getKeyPair((org.bouncycastle.openssl.PEMKeyPair)parsed);
    System.out.println (pair.getPrivate().getAlgorithm());

In Java this will be pretty much the same code. After striping guarding strings away and decoding Base64 data give it to this utility method:

public static PrivateKey keyToValue(byte[] pkcs8key)
    throws GeneralSecurityException {

    PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(pkcs8key);
    KeyFactory factory = KeyFactory.getInstance("ECDSA");
    PrivateKey privateKey = factory.generatePrivate(spec);
    return privateKey;

Since I only need this for a quick and dirty demo, I solved it in the following way (in Scala). First, I generate a public private key pair in the REPL and print out its data:

Security.addProvider(new BouncyCastleProvider)

val SignatureScheme = "some signature scheme, eg ECDSA"
val RandomAlgorithm = "some random algorithm, eg SHA1PRNG"

val keygen = KeyPairGenerator.getInstance(SignatureScheme)
val rng = SecureRandom.getInstance(RandomAlgorithm)
keygen.initialize(KeySize, rng)

val kp = keygen.generateKeyPair()
println(kp.getPublic.getEncoded.toSeq) // toSeq so that Scala actually prints it

Then using the generated data,

val hardcodedPublic = Array[Byte]( /* data */ )
val hardcodedPrivate = Array[Byte]( /* data */ )

val factory = KeyFactory.getInstance(SignatureScheme)

val publicSpec = new X509EncodedKeySpec(hardcodedPublic)
val publicKey = factory.generatePublic(publicSpec)

val privateSpec = new PKCS8EncodedKeySpec(hardcodedPrivate)
val privateKey = factory.generatePrivate(privateSpec)

The key thing you need to know here is that by default public key data uses X509 encoding and private key data uses PKCS8 encoding. It should be possible to get OpenSSL to output these formats and parse them manually, but I did not check how.

I used information from this blog post about SpongyCastle (which is Android’s BouncyCastle alias) quite helpful. It is unfortunate that documentation is fragmented like this, and that BouncyCastle’s wiki was down at the time of this question.

Update: the BouncyCastle wiki is up, and you can find the documentation here.

Leave a Reply

Your email address will not be published. Required fields are marked *