如何从 33 字节重建 33 字节压缩的 NIST P-256 public 密钥?
How to reconstruct 33-byte compressed NIST P-256 public key from 33 bytes?
假设33字节编码的Public密钥可以这样创建:
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: error:0c000079:ASN.1 encoding routines:OPENSSL_internal:HEADER_TOO_LONG
我也在尝试:
val generator = KeyPairGenerator.getInstance("ECDSA")
val ecPublicKey = generator
.generatePublic(X509EncodedKeySpec((publicEncoded))) as ECPublicKey
但是错误是:
java.security.spec.InvalidKeySpecException: encoded key spec not recognised
如何实现我的目标?
主要问题是您的 publicEncoded
不是编码的 public 密钥,而是编码的 ECPoint
(publicKey.q
)。
这意味着您需要先重建点,然后提供适当的曲线来重建密钥以获得正确的 ECPublicKeySpec
.
- 首先用
ECNamedCurveTable.getParameterSpec("secp256r1")
重新获取选择的曲线规格。然后,您可以使用 ecSpec.curve.decodePoint(publicEncoded)
重建 BC ECPoint
实例。
- 将 BouncyCastle
ECNamedCurveParameterSpec
变成 java.security.spec.ECParameterSpec
,将 BouncyCastle ECPoint
变成 java java.security.spec.ECPoint
。然后构造适当的 ECPublicKeySpec
,然后 ECDSA
密钥生成器可以使用它来重新创建完整的 PublicKey
.
参考文献:
这应该可以完成工作:
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
}
假设33字节编码的Public密钥可以这样创建:
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: error:0c000079:ASN.1 encoding routines:OPENSSL_internal:HEADER_TOO_LONG
我也在尝试:
val generator = KeyPairGenerator.getInstance("ECDSA")
val ecPublicKey = generator
.generatePublic(X509EncodedKeySpec((publicEncoded))) as ECPublicKey
但是错误是:
java.security.spec.InvalidKeySpecException: encoded key spec not recognised
如何实现我的目标?
主要问题是您的 publicEncoded
不是编码的 public 密钥,而是编码的 ECPoint
(publicKey.q
)。
这意味着您需要先重建点,然后提供适当的曲线来重建密钥以获得正确的 ECPublicKeySpec
.
- 首先用
ECNamedCurveTable.getParameterSpec("secp256r1")
重新获取选择的曲线规格。然后,您可以使用ecSpec.curve.decodePoint(publicEncoded)
重建 BCECPoint
实例。 - 将 BouncyCastle
ECNamedCurveParameterSpec
变成java.security.spec.ECParameterSpec
,将 BouncyCastleECPoint
变成 javajava.security.spec.ECPoint
。然后构造适当的ECPublicKeySpec
,然后ECDSA
密钥生成器可以使用它来重新创建完整的PublicKey
.
参考文献:
这应该可以完成工作:
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
}