问题
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 BCECPointinstance. - Turn the BouncyCastle
ECNamedCurveParameterSpecinto thejava.security.spec.ECParameterSpecand the BouncyCastleECPointinto the javajava.security.spec.ECPoint. Then construct the appropriateECPublicKeySpecwhich can then be used by theECDSAkey 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