5

Having generated the private key like this:

    fun getKeyPair(): Pair<ByteArray, ByteArray> {
        Security.addProvider(provider)
        val generator = KeyPairGenerator.getInstance("ECDSA")
        val ecSpec = ECNamedCurveTable.getParameterSpec("secp256r1")
        generator.initialize(ecSpec)
        val keyPair = generator.generateKeyPair()
        val publicKey = keyPair.public as ECPublicKey
        val privateKey = keyPair.private
        return Pair(publicKey.q.getEncoded(true), privateKey.getEncoded())
    }

The public key can be reconstructed again like this:

    Security.addProvider(...spongy castle provider)
    val ecSpecs = ECNamedCurveTable.getParameterSpec("secp256r1")
    val q = ecSpecs.curve.decodePoint(publicKeyEncoded)
    val pubSpec = ECPublicKeySpec(q, ecSpecs)
    val keyFactory = KeyFactory.getInstance("ECDSA")
    val generatedPublic = keyFactory.generatePublic(pubSpec)

How it is possible to reconstruct private key from bytes also along with this?

UPDATE:

This code works well in actual app but it doesnt in JUnit testing:

val keyFactory = KeyFactory.getInstance("ECDSA")
val privSpec = PKCS8EncodedKeySpec(privateEncoded)
val generatedPrivate = keyFactory.generatePrivate(privSpec)

In JUnit test I am getting this error:

java.security.spec.InvalidKeySpecException: encoded key spec not recognised

My private key as encoded bytes has 150 bytes size.

K.Os
  • 5,123
  • 8
  • 40
  • 95
  • To find out the format of the encoded key, and thus a hint to KeySpec type needed to regenerate it, examine the `.format` property of the key, e.g. `val privFormat = privateKey.format` – President James K. Polk Dec 14 '18 at 01:31
  • Make sure that both your app and Junit use the provider you have installed. `Security.addProvider (provider)` installs the provider at the end, so if the system has another provider capable of handling EC keys, it will be used and you can get unexpected results. You can use `Security.insertProviderAt (sc, 1);` or specify it in the call to `KeyFactory.getInstance ("ECDSA", "SC")` – pedrofb Dec 19 '18 at 07:46
  • @pedrofb Unfortunately I've of course tried - it did not work – K.Os Dec 19 '18 at 08:55
  • I have a feeling I've already mentioned this to you before, but the Android Studio Junit testing environment is on the host, not on Android. Therefore the security provider used in the unit tests may need to be the official bouncycastle provider rather than spongycastle. – President James K. Polk Dec 19 '18 at 15:52
  • `publicKey.q.getEncoded(true)` doesn't seem to compile in my environment. There is no `q` property for `ECPublicKey`. Of course, I really don't know Kotlin beyond blind groping in the IDE. – President James K. Polk Dec 19 '18 at 15:58
  • @JamesKPolk you can see how it is done here: https://stackoverflow.com/questions/53629537/how-to-generate-33-byte-compressed-nist-p-256-public-key. I'm using SpongyCastle though (as it aims just for Android development - using Android Studio) – K.Os Dec 19 '18 at 16:06
  • ok, but you didn't pay attention to my previous comment. Your testing framework may be using local unit tests that run on the *host*. The *host* is not android, it's whatever Android Studio is running on, like Windows/Linux/Mac OS X – President James K. Polk Dec 19 '18 at 17:26

1 Answers1

4

Since the key is encoded using the standard Key.getEncoded(), the following standard solution should work:

val keyFactory = KeyFactory.getInstance("EC")
val privSpec = PKCS8EncodedKeySpec(privateEncoded)
val generatedPrivate = keyFactory.generatePrivate(privSpec)

The encoded key should contain all the required information to rebuild the private key without specifying additional parameters like you need to do for the reduced public key.

Kiskae
  • 24,655
  • 2
  • 77
  • 74
  • Unfortunately, when i used this and then want to test this generation in my JUnit test i am getting this error: "java.security.spec.InvalidKeySpecException: encoded key spec not recognised" I am using AndroidStudio - when I am running this code in the actual app this is working. Can you help me? – K.Os Dec 18 '18 at 21:48
  • The fact it works on some platforms but not others indicates the code itself is fine. Did you register the security provider for the last bit of code? – Kiskae Dec 19 '18 at 13:02
  • Don't know what you exactly mean by this, but I registered the security provider like in the question above (see the code) – K.Os Dec 19 '18 at 13:04