如何从先前生成的 ECDSA 两个编码密钥对构造私钥?
Posted
技术标签:
【中文标题】如何从先前生成的 ECDSA 两个编码密钥对构造私钥?【英文标题】:How to construct private key from generated previously ECDSA both encoded key pair? 【发布时间】:2018-12-13 15:12:39 【问题描述】:生成了这样的私钥:
fun getKeyPair(): Pair<ByteArray, ByteArray>
Security.addProvider(provider)
val generator = KeyPairGenerator.getInstance("ECDSA")
val ecSpec = ECNamedCurveTable.getParameterSpec("secp256r1")
generator.initialize(ecSpec)
val keyPair = generator.generateKeyPair()
val publicKey = keyPair.public as ECPublicKey
val privateKey = keyPair.private
return Pair(publicKey.q.getEncoded(true), privateKey.getEncoded())
可以像这样再次重构公钥:
Security.addProvider(...spongy castle provider)
val ecSpecs = ECNamedCurveTable.getParameterSpec("secp256r1")
val q = ecSpecs.curve.decodePoint(publicKeyEncoded)
val pubSpec = ECPublicKeySpec(q, ecSpecs)
val keyFactory = KeyFactory.getInstance("ECDSA")
val generatedPublic = keyFactory.generatePublic(pubSpec)
如何同时从字节重建私钥?
更新:
此代码在实际应用中运行良好,但在 JUnit 测试中却不行:
val keyFactory = KeyFactory.getInstance("ECDSA")
val privSpec = PKCS8EncodedKeySpec(privateEncoded)
val generatedPrivate = keyFactory.generatePrivate(privSpec)
在 JUnit 测试中我收到此错误:
java.security.spec.InvalidKeySpecException: encoded key spec not recognised
我作为编码字节的私钥有 150 字节大小。
【问题讨论】:
要找出编码密钥的格式,从而提示重新生成它所需的 KeySpec 类型,请检查密钥的.format
属性,例如val privFormat = privateKey.format
确保您的应用和 Junit 都使用您已安装的提供程序。 Security.addProvider (provider)
会在最后安装提供程序,因此如果系统有另一个能够处理 EC 密钥的提供程序,它将被使用,并且您会得到意想不到的结果。您可以使用Security.insertProviderAt (sc, 1);
或在调用KeyFactory.getInstance ("ECDSA", "SC")
时指定它
@pedrofb 不幸的是,我当然尝试过 - 它没有用
我有一种感觉,我之前已经向您提过这个,但是android Studio Junit测试环境是在主机上,而不是在Android上。因此,单元测试中使用的安全提供者可能需要是官方的 bouncycastle 提供者而不是 spongycastle。
publicKey.q.getEncoded(true)
在我的环境中似乎无法编译。 ECPublicKey
没有 q
属性。当然,除了在 IDE 中瞎摸索之外,我真的不了解 Kotlin。
【参考方案1】:
由于密钥是使用标准Key.getEncoded()
编码的,因此以下标准解决方案应该有效:
val keyFactory = KeyFactory.getInstance("EC")
val privSpec = PKCS8EncodedKeySpec(privateEncoded)
val generatedPrivate = keyFactory.generatePrivate(privSpec)
编码后的密钥应包含重建私钥所需的所有信息,而无需像为简化的公钥那样指定额外的参数。
【讨论】:
不幸的是,当我使用它然后想在我的 JUnit 测试中测试这一代时,我收到了这个错误:“java.security.spec.InvalidKeySpecException:编码的密钥规范无法识别”我正在使用 AndroidStudio - 当我在实际应用程序中运行此代码时,它正在工作。你能帮帮我吗? 它在某些平台上运行但在其他平台上运行的事实表明代码本身很好。您是否为最后一段代码注册了安全提供程序? 不知道你到底是什么意思,但我在上面的问题中注册了安全提供程序(见代码)以上是关于如何从先前生成的 ECDSA 两个编码密钥对构造私钥?的主要内容,如果未能解决你的问题,请参考以下文章