You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

iOS生成的EC公钥Base64转Java PublicKey后结果不一致问题排查

问题:iOS生成的EC公钥Base64转Java PublicKey后重新编码不一致

尝试将iOS(Swift)生成的基于secp256r1曲线的EC公钥Base64编码字符串转换为Android平台的Java PublicKey,用于双方计算共享密钥。代码无编译或运行时异常,可成功生成PublicKey,但将其重新Base64编码后与传入的原公钥不一致。

相关代码

import android.util.Base64
import org.bouncycastle.asn1.sec.SECNamedCurves
import org.bouncycastle.math.ec.ECCurve
import java.math.BigInteger
import java.nio.charset.StandardCharsets
import java.security.*
import java.security.spec.*
import javax.crypto.*
import javax.crypto.spec.IvParameterSpec
import javax.crypto.spec.SecretKeySpec


fun iosB64EncodedStrPKToPK(iOSB64EncodedPK: String): PublicKey {
    val decodedPK = Base64.decode(iOSB64EncodedPK, Base64.NO_WRAP)
    val x9ECParamSpec = SECNamedCurves.getByName("secp256r1")
    val curve = x9ECParamSpec.curve
    val point = curve.decodePoint(decodedPK)
    val xBcEC = point.affineXCoord.toBigInteger()
    val yBcEC = point.affineYCoord.toBigInteger()
    val gBcEC = x9ECParamSpec.g
    val xGBcEC = gBcEC.affineXCoord.toBigInteger()
    val yGBcEC = gBcEC.affineYCoord.toBigInteger()
    val hBcEC = x9ECParamSpec.h.toInt()
    val nBcEC = x9ECParamSpec.n
    val jPEC = ECPoint(xBcEC, yBcEC)
    val gJpEC = ECPoint(xGBcEC, yGBcEC)
    val jEllipticCurve = convertECCurveToEllipticCurve(curve, gJpEC, nBcEC, hBcEC)
    val eCParameterSpec = ECParameterSpec(jEllipticCurve, gJpEC, nBcEC, hBcEC)
    val ecPubLicKeySpec = ECPublicKeySpec(jPEC, eCParameterSpec)
    val keyFactorySpec = KeyFactory.getInstance("EC")
    return keyFactorySpec.generatePublic(ecPubLicKeySpec)
}

private fun convertECCurveToEllipticCurve(
    curve: ECCurve,
    ecPoint: ECPoint,
    n: BigInteger,
    h: Int
): EllipticCurve {
    val ecField = ECFieldFp(curve.field.characteristic)
    val firstCoefficient = curve.a.toBigInteger()
    val secondCoefficient = curve.b.toBigInteger()
    val ecParams = ECParameterSpec(
        EllipticCurve(ecField, firstCoefficient, secondCoefficient),
            ecPoint,
            n,
            h
        )
    return ecParams.curve
}

测试数据

  • 传入的原公钥Base64字符串:
    BAlWWu46il/ly6Axd/qclmhEVhGth93QN5+h3JBJEKEmhKd1LfqkpCqX1cT1cQDs9nPq9Lq0/FtZitkjr7Rqd94=
  • 转换后重新Base64编码得到的字符串:
    MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAECVZa7jqKX+XLoDF3+pyWaERWEa2H3dA3n6HckEkQoSaEp3Ut+qSkKpfVxPVxAOz2c+r0urT8W1mK2SOvtGp33g==

测试代码

val pkIOS = "BAlWWu46il/ly6Axd/qclmhEVhGth93QN5+h3JBJEKEmhKd1LfqkpCqX1cT1cQDs9nPq9Lq0/FtZitkjr7Rqd94="

Log.i("SOME_TAG","PUBLIC_KEY_IOS:${Base64.encodeToString(iosB64EncodedStrPKToPK(pkIOS).encoded,Base64.NO_WRAP)}") 

运行环境与依赖

运行环境为Android,使用的BouncyCastle版本为1.70:

def bouncy_castle_version = '1.70'
implementation "org.bouncycastle:bcpkix-jdk15on:$bouncy_castle_version"
implementation "org.bouncycastle:bcprov-jdk15on:$bouncy_castle_version"

需求:希望得到问题排查方向指引,同时欢迎推荐相关学习资料。


内容的提问来源于stack exchange,提问作者codeasus

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 23:32:19