How to reconstruct 33-byte compressed NIST P-256 public key from 33 bytes?

十年热恋 提交于 2019-12-12 01:16:38

问题


Supposed that the 33 bytes encoded Public Key can be created like this:

Security.addProvider(provider)
val generator = KeyPairGenerator.getInstance("ECDSA")
val ecSpec = ECNamedCurveTable.getParameterSpec("secp256r1")
generator.initialize(ecSpec)
val keyPair = generator.generateKeyPair()
val privateKey = keyPair.private as ECPrivateKey
val publicKey = keyPair.public as ECPublicKey
val publicEncoded = publicKey.q.getEncoded(true)

How can I reconstruct it again on the other side (when I am having only the 33 bytes sent from here)?

I was trying below code:

val publicKey =KeyFactory.getInstance("EC").generatePublic(X509EncodedKeySpec(publicEncoded))

But I guess this is totally wrong, as I am getting the:

java.security.spec.InvalidKeySpecException: java.lang.RuntimeException: error:0c000079:ASN.1 encoding routines:OPENSSL_internal:HEADER_TOO_LONG

I was trying also:

val generator = KeyPairGenerator.getInstance("ECDSA")
val ecPublicKey = generator
        .generatePublic(X509EncodedKeySpec((publicEncoded))) as ECPublicKey

But the error is:

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

How to achieve my goal?


回答1:


This should do the job:

import org.bouncycastle.jce.ECNamedCurveTable
import org.bouncycastle.jce.spec.ECPublicKeySpec

fun publicKeyFromCompressed(compressedPublicKey: ByteArray): PublicKey {
    val ecSpec = ECNamedCurveTable.getParameterSpec("secp256r1")
    val point = ecSpec.curve.decodePoint(compressedPublicKey)
    val publicKeySpec = ECPublicKeySpec(point, ecSpec)
    val keyFactory = KeyFactory.getInstance("ECDSA")
    val publicKey = keyFactory.generatePublic(publicKeySpec)
    return publicKey
}



回答2:


The primary problem is that your publicEncoded is not an encoded public key, but an encoded ECPoint (publicKey.q). This means you need to first reconstruct the point and then provide the appropriate curve to reconstruct the key to obtain the correct ECPublicKeySpec.

  1. First re-obtain the chosen curve spec with ECNamedCurveTable.getParameterSpec("secp256r1"). You can then use ecSpec.curve.decodePoint(publicEncoded) to reconstruct the BC ECPoint instance.
  2. Turn the BouncyCastle ECNamedCurveParameterSpec into the java.security.spec.ECParameterSpec and the BouncyCastle ECPoint into the java java.security.spec.ECPoint. Then construct the appropriate ECPublicKeySpec which can then be used by the ECDSA key generator to recreate the complete PublicKey.

References:

  • ECPoint.getEncoded() / ECCurve.decodePoint(byte[])
  • ECNamedCurveParameterSpec / ECPublicKeySpec
  • ECPublicKeySpec(ECPoint, ECParameterSpec)


来源:https://stackoverflow.com/questions/53706767/how-to-reconstruct-33-byte-compressed-nist-p-256-public-key-from-33-bytes

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!