Android中TrustManager是否应信任信任库内的过期证书?
作为信任锚的过期X509证书是否会被Android SSL引擎信任?
val expiredCertificate: X509Certificate = ... val keyStore = KeyStore.getInstance(KeyStore.getDefaultType()) putCert(keyStore, expiredCertificate) val trustManagerFactory = TrustManagerFactory.getInstance(algorithm).apply { init(keyStore) } val trustManager = trustManagerFactory.trustManagers.firstOrNull() as? X509TrustManager val sslContext = SSLContext.getInstance("TLS").apply { init(null, arrayOf(trustManager), SecureRandom()) }
场景概述
- 获取一份已过期的X509证书
- 将该证书存入KeyStore
- 基于此KeyStore初始化SSLContext,使SSL引擎的信任库包含这份过期证书
- 与后端建立SSL连接时,服务器返回的证书链恰好包含这份存入信任库的过期证书
核心问题
验证证书链时,SSL引擎是否应当检查这份作为信任锚的过期证书的有效期?它是否应该信任该证书?
实际观察到的行为
该证书由android.security.net.config.RootTrustManager处理,委托给com.android.org.conscrypt.TrustManagerImpl,后者将证书存入trustAnchors变量时未执行任何检查,最终过期证书被信任。想确认这是Bug还是特性。
结论:这是Conscrypt的既定特性,而非Bug
原因说明
- 信任锚的特殊验证逻辑:当证书被直接作为信任锚放入信任库时,Conscrypt(Android默认SSL实现)会跳过对它的有效期、签名链完整性等常规检查。因为信任锚是证书链验证的终点,系统默认你是主动选择信任该证书的,因此不会再对它的属性做额外校验。
- 仅链中非锚证书会被严格检查:只有当证书是服务器叶子证书或链中的中间证书时,才会强制校验有效期、签名有效性等属性。如果信任锚过期,但服务器证书链以它为根,只要链的其他部分符合要求,整个链就会被判定为可信。
补充说明
- 这种设计是为了兼容性:部分场景下,旧根证书过期后仍需临时信任,或者特殊环境需要强制信任特定证书(哪怕过期),这种逻辑可以满足这类需求。
- 若需拒绝过期的信任锚,无法依赖系统默认TrustManager,必须自定义X509TrustManager,在
checkServerTrusted方法中手动对信任锚的有效期进行校验。
内容的提问来源于stack exchange,提问作者Eugene Chumak
相关产品推荐
相关产品推荐

