【发布时间】:2021-06-30 07:22:40
【问题描述】:
我正在开发一个应用程序,我必须在其中使用证书(在 .crt 文件中)和私钥(在 .pem 文件中)与后端服务器通信。
问题是——当我使用curl时,连接成功
curl (...) --cert pubcert.crt --key privkey.pem
但是当我尝试从 Android 应用程序连接时,我得到了
HTTP FAILED: javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
我的 OkHttpClient:
val privKeyInputStream = context.resources.openRawResource(R.raw.privkey)
val pubKeyInputStream = context.resources.openRawResource(R.raw.pubcert)
val cf: CertificateFactory = CertificateFactory.getInstance("X.509")
val certificate: X509Certificate = cf.generateCertificate(pubKeyInputStream) as X509Certificate
val keyPair = KeyPair(certificate.publicKey, loadPrivateKey(privKeyInputStream))
val rootCertificate = HeldCertificate(keyPair, certificate)
val certificates: HandshakeCertificates = HandshakeCertificates.Builder()
.addTrustedCertificate(rootCertificate.certificate)
.build()
return OkHttpClient
.Builder()
.sslSocketFactory(certificates.sslSocketFactory(), certificates.trustManager)
.build()
fun loadPrivateKey(inputStream: InputStream): PrivateKey? {
var key: PrivateKey? = null
try {
val br = BufferedReader(InputStreamReader(inputStream))
val builder = StringBuilder()
var inKey = false
var line = br.readLine()
while (line != null) {
if (!inKey) {
if (line.startsWith("-----BEGIN ") &&
line.endsWith(" PRIVATE KEY-----")
) {
inKey = true
}
line = br.readLine()
continue
} else {
if (line.startsWith("-----END ") &&
line.endsWith(" PRIVATE KEY-----")
) {
inKey = false
break
}
builder.append(line)
}
line = br.readLine()
}
println(builder.toString())
//
val encoded: ByteArray = Base64.decode(builder.toString(), Base64.DEFAULT)
val keySpec = PKCS8EncodedKeySpec(encoded)
val kf = KeyFactory.getInstance("RSA")
key = kf.generatePrivate(keySpec)
} finally {
inputStream.close()
}
return key
}
【问题讨论】: