假设可以像这样创建33字节编码的公钥:
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)
如何在另一侧重新构建它(当我仅从此处发送33个字节时)?
我正在尝试下面的代码:
val publicKey =KeyFactory.getInstance("EC").generatePublic(X509EncodedKeySpec(publicEncoded))
但是我想这是完全错误的,因为我得到了:
java.security.spec.InvalidKeySpecException:java.lang.RuntimeException:错误:0c000079:ASN.1编码例程:OPENSSL_internal:HEADER_TOO_LONG
我也在尝试:
val generator = KeyPairGenerator.getInstance("ECDSA")
val ecPublicKey = generator
.generatePublic(X509EncodedKeySpec((publicEncoded))) as ECPublicKey
但是错误是:
java.security.spec.InvalidKeySpecException:无法识别编码的密钥规范
如何实现我的目标?
答案 0 :(得分:2)
主要问题是您的 publicEncoded
不是已编码的公共密钥,而是已编码的 ECPoint
( publicKey.q
)。
这意味着您需要首先重建该点,然后提供适当的曲线以重建关键点以获得正确的 ECPublicKeySpec
。
ECNamedCurveTable.getParameterSpec(“ secp256r1”)
重新获得所选曲线规格。然后,您可以使用 ecSpec.curve.decodePoint(publicEncoded)
重建BC ECPoint
实例。 ECNamedCurveParameterSpec
转换为 java.security.spec.ECParameterSpec
,将BouncyCastle ECPoint
转换为java java.security .spec.ECPoint
。然后构造适当的 ECPublicKeySpec
,然后供 ECDSA
密钥生成器使用,以重新创建完整的 PublicKey
。参考文献:
答案 1 :(得分:1)
这应该可以完成工作:
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
}