Search code examples
androidencryptionkotlinbouncycastleprivate-key

ASN.1 encoding routines:OPENSSL_internal:HEADER_TOO_LONG


I have a problem with rconstructing the private key from byte array in Kotlin (using Android Studio)

I must load the private key that I have defined like below. From what I know, this EC Private key is 32 bytes long which correspond to secp256r1 curve

0x3C, 0x6D, etc... (this have 32 in total)

This is what i have:

val privateKeyArray = arrayOf(0x3C, 0x6D, etc...) //this have 32 size

Then I am trying to convert it to byteArray:

val privateKeyBytes = privateKeyArray.map { it.toByte() }.toByteArray())

And then I want to sign some data with it:

val keyFactory = KeyFactory.getInstance("EC")
val privateKey = keyFactory.generatePrivate(PKCS8EncodedKeySpec(privateKeyBytes))  //THIS line gives the Exception

val content = "random string".toByteArray()
val signer = Signature.getInstance("SHA256withECDSA")
signer.initSign(privateKey)
signer.update(content)
val signature = signer.sign()

However, when i am trying to generate the privateKey from the keyFactory I am getting the following Exception:

java.security.spec.InvalidKeySpecException: java.lang.RuntimeException: error:0c000079:ASN.1 encoding routines:OPENSSL_internal:HEADER_TOO_LONG at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2927)

How can I properly read the private key in this case?


Solution

  • I used BouncyCastle as the security provider, so you can try it as well. looks like the spec you are using is secp256r1. in this case, try following code to regen the PrivateKey object from the byte array that represents the key. remember, the byte array is just a BigInteger in Java.

    let me know if it works or not.

    public PrivateKey generatePrivateKey(byte[] keyBin) throws InvalidKeySpecException, NoSuchAlgorithmException {
        ECNamedCurveParameterSpec spec = ECNamedCurveTable.getParameterSpec("secp256r1");
        KeyFactory kf = KeyFactory.getInstance("ECDSA", new BouncyCastleProvider());
        ECNamedCurveSpec params = new ECNamedCurveSpec("secp256r1", spec.getCurve(), spec.getG(), spec.getN());
        ECPrivateKeySpec privKeySpec = new ECPrivateKeySpec(new BigInteger(keyBin), params);
        return kf.generatePrivate(privKeySpec);
    }