问题
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.
- First re-obtain the chosen curve spec with
ECNamedCurveTable.getParameterSpec("secp256r1")
. You can then useecSpec.curve.decodePoint(publicEncoded)
to reconstruct the BCECPoint
instance. - Turn the BouncyCastle
ECNamedCurveParameterSpec
into thejava.security.spec.ECParameterSpec
and the BouncyCastleECPoint
into the javajava.security.spec.ECPoint
. Then construct the appropriateECPublicKeySpec
which can then be used by theECDSA
key generator to recreate the completePublicKey
.
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