Deriving ECDSA Public Key from Private Key

前端 未结 3 1663
既然无缘
既然无缘 2021-01-03 01:41

I was attempting to generate a public ECDSA key from a private key, and I haven\'t managed to find much help on the internet as to how to do this. Pretty much everything is

3条回答
  •  时光说笑
    2021-01-03 02:09

    I came here with the same problem in Kotlin, so, in case it helps anyone, here's how I derived the PublicKey from an ECDSA PrivateKey in Kotlin. This code is based on Lev Knoblock's Java answer and then trial-and-errored until it worked.

    In my case I knew that my key used the secp256k1 curve, so I could hard-code that part. I didn't bother to learn how to generalize it to other curves.

    import java.security.KeyFactory
    import java.security.KeyPair
    import java.security.PrivateKey
    import java.security.PublicKey
    import org.bouncycastle.asn1.pkcs.PrivateKeyInfo
    import org.bouncycastle.jce.ECNamedCurveTable
    import org.bouncycastle.jce.interfaces.ECPrivateKey
    import org.bouncycastle.jce.spec.ECNamedCurveParameterSpec
    import org.bouncycastle.jce.spec.ECPublicKeySpec
    import org.bouncycastle.math.ec.ECPoint
    import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter
    import org.bouncycastle.openssl.PEMParser
    
    fun getECPrivateKeyFromPEM(privatePem: String): ECPrivateKey {
        val pemParser = PEMParser(privatePem.reader())
        val privateKeyInfo = pemParser.readObject() as PrivateKeyInfo
        return JcaPEMKeyConverter().getPrivateKey(privateKeyInfo) as ECPrivateKey
    }
    
    fun getKeyPairFromECPrivateKey(privateKey: ECPrivateKey): KeyPair {
        val keyFactory: KeyFactory = KeyFactory.getInstance("ECDSA", "BC")
        val spec: ECNamedCurveParameterSpec = ECNamedCurveTable.getParameterSpec("secp256k1")
        val Q: ECPoint = spec.getG().multiply(privateKey.getD())
        val publicKey: PublicKey = keyFactory.generatePublic(ECPublicKeySpec(Q, spec))
        return KeyPair(publicKey, privateKey)
    }
    

    And here's my test harness:

    import java.io.StringWriter
    import org.bouncycastle.openssl.jcajce.JcaPEMWriter
    
    fun main() {
        val privatePem = """
           |-----BEGIN PRIVATE KEY-----
           |MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQg55EMdhNJX+YN/bjN
           |Eof91oKqEqD0QidEsRMhHBwSRjShRANCAARnSFpE0LDugORBWlSJz0Zf9e0mR9s6
           |tlxSeo1Nbd2vv9LDedm+l/CfZpbyYvPm49DAKDhkUHFIVDd2SsiPrRa7
           |-----END PRIVATE KEY-----
        """.trimMargin()
        val privateKey: ECPrivateKey = getECPrivateKeyFromPEM(privatePem)
        val pair: KeyPair = getKeyPairFromECPrivateKey(privateKey)
        val pems: String = StringWriter().use {
            val pemWriter = JcaPEMWriter(it)
            pemWriter.writeObject(pair.getPublic())
            pemWriter.writeObject(pair.getPrivate())
            pemWriter.flush()
            it.toString()
        }
        println(pems)
    }
    

    This prints out:

    -----BEGIN PUBLIC KEY-----
    MFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEcE4HMAHLDvPr6xHKsjhPXJzTdxLlRRR8
    BfYnI2TGb0QLTFyyXm13CeYiLnxbkGhSvz9ZRo0zGQygKPVpgiThSw==
    -----END PUBLIC KEY-----
    -----BEGIN EC PRIVATE KEY-----
    MHcCAQEEIOeRDHYTSV/mDf24zRKH/daCqhKg9EInRLETIRwcEkY0oAoGCCqGSM49
    AwEHoUQDQgAEZ0haRNCw7oDkQVpUic9GX/XtJkfbOrZcUnqNTW3dr7/Sw3nZvpfw
    n2aW8mLz5uPQwCg4ZFBxSFQ3dkrIj60Wuw==
    -----END EC PRIVATE KEY-----
    

提交回复
热议问题