【问题标题】:Convert ByteArray to PrivateKey in Kotlin在 Kotlin 中将 ByteArray 转换为 PrivateKey
【发布时间】:2020-09-22 15:28:21
【问题描述】:

我有一个原始格式的私钥,一个字节数组:

val privKeyIControlUInt8 = byteArrayOfInts(
                0x00, 0x00, 0x00, 0x00, 0xB2, 0xC6, 0xFE, 0x9D,
                0x1F, 0x87, 0x85, 0x8C, 0x00, 0x00, 0x00, 0x0A,
                0x7D, 0x90, 0x8E, 0x1C, 0x11, 0x2D, 0x7B, 0xF9,
                0x30, 0x8D, 0xF3, 0x8C, 0xD5, 0xC0, 0x41, 0xF0
            )

我需要将此数组转换为私钥。我使用这个功能:

private fun generatePrivateKey(encodedPrivateKey: ByteArray): PrivateKey {
            Security.addProvider(BouncyCastleProvider())
            val keyFactory = KeyFactory.getInstance("????")
            return keyFactory.generatePrivate(PKCS8EncodedKeySpec(encodedPrivateKey))

        }

我不知道如何设置getInstance。我的私钥是 P256,也称为 secp256r1 和 prime256v1。 有什么想法吗?

提前非常感谢!

【问题讨论】:

    标签: android kotlin cryptography private-key secp256r1


    【解决方案1】:

    从原始数据派生私钥的一种方法如下(基于this 实现):

    fun getPrivateKeyFromRaw(key: BigInteger, curveName: String): ECPrivateKey {
        val ecParameterSpec = getParametersForCurve(curveName)
        val privateKeySpec = ECPrivateKeySpec(key, ecParameterSpec)
        val keyFactory = KeyFactory.getInstance("EC")
        return keyFactory.generatePrivate(privateKeySpec) as ECPrivateKey
    }
    
    fun getParametersForCurve(curveName: String): ECParameterSpec {
        val params = AlgorithmParameters.getInstance("EC")
        params.init(ECGenParameterSpec(curveName))
        return params.getParameterSpec(ECParameterSpec::class.java)
    }
    

    该实现使用纯 Java 类,即。 e.没有 BouncyCastle。这样,可以从原始数据中导出私钥,如下所示:

    import java.math.BigInteger
    import java.security.AlgorithmParameters
    import java.security.KeyFactory
    import java.security.interfaces.ECPrivateKey
    import java.security.spec.ECGenParameterSpec
    import java.security.spec.ECParameterSpec
    import java.security.spec.ECPrivateKeySpec
    ...
    val privKeyRaw = byteArrayOf(
        0x00.toByte(), 0x00.toByte(), 0x00.toByte(), 0x00.toByte(), 0xB2.toByte(), 0xC6.toByte(), 0xFE.toByte(), 0x9D.toByte(),
        0x1F.toByte(), 0x87.toByte(), 0x85.toByte(), 0x8C.toByte(), 0x00.toByte(), 0x00.toByte(), 0x00.toByte(), 0x0A.toByte(),
        0x7D.toByte(), 0x90.toByte(), 0x8E.toByte(), 0x1C.toByte(), 0x11.toByte(), 0x2D.toByte(), 0x7B.toByte(), 0xF9.toByte(),
        0x30.toByte(), 0x8D.toByte(), 0xF3.toByte(), 0x8C.toByte(), 0xD5.toByte(), 0xC0.toByte(), 0x41.toByte(), 0xF0.toByte()
    )
    val curveName = "secp256r1"
    val privKeyBI = BigInteger(1, privKeyRaw)
    val privateKey = getPrivateKeyFromRaw(privKeyBI, curveName)
    println(Base64.encodeToString(privateKey.encoded, Base64.DEFAULT)) // MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgAAAAALLG/p0fh4WMAAAACn2QjhwRLXv5MI3zjNXAQfChRANCAATL8eioa63NR6Rn6oF27Zx7/uiMZevH5uLJYhQWOCl10KUHgjIDE6fjQNGAzcHrfJM1Xwr8QKmZPsFIl8GMh82K
    

    可以在 ASN.1 解析器中查看,例如here.

    我已经在 Android P,API 28 上对此进行了测试。

    使用 BouncyCastle 可以实现更紧凑的实现,请参阅 here

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-09-03
      • 2016-05-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-11
      • 2020-02-19
      相关资源
      最近更新 更多