【问题标题】:GRPC Okhttp android client channel with self signed ssl certificate带有自签名 ssl 证书的 GRPC Okhttp android 客户端通道
【发布时间】:2020-11-23 08:08:51
【问题描述】:

我有一个使用自签名 ssl 证书的 grpc-js 服务器。

var credentials = grpc.ServerCredentials.createSsl(
    fs.readFileSync('./node/grpc/ssl/ca.crt'), 
    [{
        cert_chain: fs.readFileSync('./node/grpc/ssl/server.crt'),
        private_key: fs.readFileSync('./node/grpc/ssl/server.key')
    }], 
    true
);

然后我使用具有以下凭据设置的 grpc-js 客户端测试了此设置,并且可以正常工作。

var credentials = grpc.credentials.createSsl(
    fs.readFileSync('./node/grpc/ssl/ca.crt'),
    fs.readFileSync('./node/grpc/ssl/client.key'),
    fs.readFileSync('./node/grpc/ssl/client.crt')
);

我想使用 OkHttpChannelBuilder 在 Android 中复制它,但它有点复杂。这是我目前所拥有的。

private val mChannel : ManagedChannel
init {
    /**
     * Server certificate to make it trusted.
     */
    val serverCrtFile = applicationContext.resources.openRawResource(R.raw.server)
    val serverCertificate: X509Certificate =
        CertificateFactory.getInstance("X.509").generateCertificate(serverCrtFile) as X509Certificate

    val caKeyStore: KeyStore = KeyStore.getInstance(KeyStore.getDefaultType()).apply {
        load(null, null)
        setCertificateEntry("server", serverCertificate)
    }

    val trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()).apply {
        init(caKeyStore)
    }

    val sslContext = SSLContext.getInstance("TLS").apply {
        init(null, trustManagerFactory.trustManagers, null)
    }

    mChannel = OkHttpChannelBuilder
        .forAddress(BuildConfig.GRPC_HOST_ADDRESS, BuildConfig.GRPC_HOST_PORT)
        .sslSocketFactory(sslContext.socketFactory)
        .keepAliveTime(10, TimeUnit.SECONDS)
        .useTransportSecurity()
        .keepAliveWithoutCalls(true)
        .build()
}

在实施 ssl 之前一切正常(因此在通道构建器上使用 plaintext())。

我现在得到的错误是io.grpc.StatusRuntimeException: UNAVAILABLE: End of stream or IOException。 有人可以告诉我我是否做错了什么以及如何在 js 服务器和客户端之间建立成功的连接。

【问题讨论】:

  • 所以我可以将服务器的grpc.ServerCredentials.createSsl()函数的第三个参数设置为false。此参数指定客户端证书是否需要由服务器验证。我仍然需要一些有关如何在 Android 上设置客户端证书的帮助。
  • 你有完整的堆栈跟踪吗?另外,服务器是否需要双向 TLS?看起来确实如此,因为 grpc-js 客户端也接受了客户端证书/密钥。在这种情况下,您需要两个 KeyStore,一个用于客户端证书/密钥,一个用于 CA 证书。然后为客户端证书/密钥创建一个使用 KeyStore 初始化的 KeyManagerFactory。最后,使用从工厂获取的 KeyManager 初始化 SSLContext。 github.com/grpc/grpc-java/issues/6374#issuecomment-550166965 包含完整的代码 sn-p。

标签: kotlin ssl grpc grpc-java


【解决方案1】:

看起来服务器端的 SSL 握手失败了,因此获取服务器端详细日志以查看问题所在会很有帮助。

一种可能性是使用KeyStore.getInstance。可以试试"PKCS12"吗?

 KeyStore.getInstance("PKCS12")

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-10-25
    • 1970-01-01
    • 2021-11-17
    • 1970-01-01
    • 1970-01-01
    • 2014-06-07
    • 2010-11-13
    • 1970-01-01
    相关资源
    最近更新 更多