正如标题所示,我正在尝试将在 IOS 设备(Swift)上生成的 base64 编码字符串(EC 公钥)转换为 Java PublicKey,后者将用于计算两方之间的共享密钥。代码中既没有运行时也没有编译时异常/错误,它编译并成功运行并生成了一个 PublicKey 但是当我将 PublicKey (Base64.encodeToString(PublicKey.encoded), Base64.NO_WRAP) 编码回 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
}
我传递给 iosB64EncodedStrPKToPK() 函数的公钥:BAlWWu46il/ly6Axd/qclmhEVhGth93QN5+h3JBJEKEmhKd1LfqkpCqX1cT1cQDs9nPq9Lq0/FtZitkjr7Rqd94=
我得到的输出: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)}")
我不是这方面的专家,也许有人会指引我正确的方向,并能看到我犯的错误。密码学不在我的专业领域。
我尝试过谷歌搜索、ChatGPT 和其他有见地的资源,如果您知道有关该问题的来源,我也很乐意接受。
我在 Android 环境中运行代码
我使用的BouncyCastle版本:
def bouncy_castle_version = '1.70'
implementation "org.bouncycastle:bcpkix-jdk15on:$bouncy_castle_version"
implementation "org.bouncycastle:bcprov-jdk15on:$bouncy_castle_version"