【问题标题】:How to reconstruct 33-byte compressed NIST P-256 public key from 33 bytes?如何从 33 字节重构 33 字节压缩 NIST P-256 公钥?
【发布时间】:2018-12-10 13:32:34
【问题描述】:

假设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: error: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:无法识别编码的密钥规范

如何实现我的目标?

【问题讨论】:

    标签: android kotlin cryptography bouncycastle ecdsa


    【解决方案1】:

    主要问题是您的publicEncoded 不是编码的公钥,而是编码的ECPoint (publicKey.q)。 这意味着您需要先重构点,然后提供适当的曲线来重构密钥以获得正确的ECPublicKeySpec。

    1. 首先使用ECNamedCurveTable.getParameterSpec("secp256r1") 重新获取所选曲线规格。然后,您可以使用 ecSpec.curve.decodePoint(publicEncoded) 重构 BC ECPoint 实例。
    2. 将 BouncyCastle ECNamedCurveParameterSpec 转换为 java.security.spec.ECParameterSpec 并将 BouncyCastle ECPoint 转换为 java java.security.spec.ECPoint。然后构造适当的ECPublicKeySpec,然后ECDSA 密钥生成器可以使用它来重新创建完整的PublicKey。

    参考资料:

    【讨论】:

    【解决方案2】:

    这应该可以完成工作:

    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
    }
    

    【讨论】:

    • 您需要正确转换point 和ecSpec,因为ECNamedCurveTable 返回的类型不兼容。
    • @Kiskae 只要您使用类的 Bouncy Castle 版本而不是 jce 版本,就无需转换。
    猜你喜欢
    • 2019-05-06
    • 1970-01-01
    • 1970-01-01
    • 2023-03-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-08
    • 1970-01-01
    相关资源
    最近更新 更多