升级BouncyCastle FIPS后Ktor CIO引擎出现EOFException等异常
问题:Ktor CIO引擎与BouncyCastle FIPS 2.1.x版本兼容性问题
问题背景
将BouncyCastle依赖从org.bouncycastle:bc-fips:2.0.0升级至2.1.0、org.bouncycastle:bctls-fips:2.0.19升级至2.1.20后,使用Ktor CIO客户端引擎短时间内发起多个HTTP GET请求时,随机触发两种错误:
java.io.EOFException:服务器提前关闭连接导致响应解析失败- Content-Length不匹配:实际接收字节数与响应头指定的预期值不符
切换至OkHttp或Apache引擎时,相同客户端代码可正常运行,排除业务逻辑问题,定位为CIO引擎与新版BouncyCastle FIPS的兼容性问题。该问题在Ktor 3.0.3及升级后的3.2.1版本中均存在。
相关日志与堆栈
失败请求日志
REQUEST: https://uclient-api.itunes.apple.com/WebObjects/MZStorePlatform.woa/wa/lookup?version=2&id=990728832&p=mdm-lockup&caller=MDM&platform=enterprisestore&cc=US METHOD: GET HEADERS: Accept: */* Accept-Charset: UTF-8 Content-Length: 0
成功响应日志(对比参考)
RESPONSE: 200 OK METHOD: HttpMethod(value=GET) FROM: https://uclient-api.itunes.apple.com/WebObjects/MZStorePlatform.woa/wa/lookup?version=2&id=990728832&p=mdm-lockup&caller=MDM&platform=enterprisestore&cc=US COMMON HEADERS -> Cache-Control: max-age=900, no-transform -> Connection: keep-alive -> Content-Length: 7127 -> Content-Type: application/json;charset=utf-8 -> Date: Sun, 20 Jul 2025 12:32:02 GMT -> Server: daiquiri/5 -> Strict-Transport-Security: max-age=31536000; includeSubDomains -> Vary: Accept-Encoding -> X-Apple-Application-Instance: 2005018 -> X-Apple-Application-Site: ST11 -> access-control-allow-origin: * -> apple-originating-system: MZStorePlatform -> apple-seq: 0.0 -> apple-timing-app: 11 ms -> apple-tk: false -> b3: 1e8397781c28e268cd5562ce4317c27b-e822c828b70d688f -> x-apple-jingle-correlation-key: D2BZO6A4FDRGRTKVMLHEGF6CPM -> x-apple-request-uuid: 1e839778-1c28-e268-cd55-62ce4317c27b -> x-b3-spanid: e822c828b70d688f -> x-b3-traceid: 1e8397781c28e268cd5562ce4317c27b -> x-daiquiri-instance: daiquiri:41896001:st53p00it-qujn12040301:7987:25RELEASE80:daiquiri-amp-store-l7shared-int-001-st; daiquiri:42282001:st53p00it-qujn15040102:7987:25RELEASE80:daiquiri-amp-store-l7shared-ext-001-st -> x-responding-instance: MZStorePlatform:2005018::: BODY Content-Type: application/json; charset=utf-8 BODY START <body here> BODY END
异常堆栈
java.io.EOFException: Failed to parse HTTP response: the server prematurely closed the connection at io.ktor.client.engine.cio.UtilsKt$readResponse$2.invokeSuspend(utils.kt:174) at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33) at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:100) at kotlinx.coroutines.internal.LimitedDispatcher$Worker.run(LimitedDispatcher.kt:124) at kotlinx.coroutines.scheduling.TaskImpl.run(Tasks.kt:89) at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:586) at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:820) at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:717) at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:704)
解决方案与排查方向
- 回退BouncyCastle版本:暂时降级到
bc-fips:2.0.0和bctls-fips:2.0.19,验证问题是否消失,确认新版本兼容性问题。 - 禁用CIO连接池:CIO引擎的连接复用可能与新版BouncyCastle的TLS处理逻辑冲突,尝试关闭连接池:
HttpClient(CIO) { engine { keepAlive = false maxConnectionsCount = 1 } } - 强制TLS版本适配:检查新版BouncyCastle默认TLS版本是否与服务器兼容,手动指定TLS版本:
HttpClient(CIO) { engine { https { sslContext = SSLContext.getInstance("TLSv1.2") sslContext.init(null, null, null) } } } - 提交兼容性问题报告:如果以上方法无效,收集包含TLS握手细节的完整调试日志,分别向Ktor和BouncyCastle项目提交问题,提供依赖版本、引擎配置和复现步骤。
内容的提问来源于stack exchange,提问作者Kamil Kurek
相关产品推荐
相关产品推荐

