You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android深度睡眠模式下KeyStore的setKeyEntry调用失败(Bouncy Castle)原因排查

Android Service重连失败问题分析

背景

我的App有一个始终运行的消息读取Android Service,偶尔会和消息代理断开连接并触发重连逻辑。相关核心代码如下:

Log.d(TAG, "< ----- Loading KeyStore ----- >");
KeyStore androidKeyStore = KeyStore.getInstance(SystemVariables.ANDROID_KEYSTORE);
androidKeyStore.load(null);

Log.d(TAG, "< ----- Getting Private Key ----- >");
PrivateKey clientPrivateKey = (PrivateKey) androidKeyStore.getKey(SystemVariables.KEY_ALIAS, null);

Log.d(TAG, "< ----- Loading Certificates ----- >");

Certificate clientCertificate = CertificateReader.loadX509Certificate(ECertificateType.CLIENT);
Certificate distribCertificate = CertificateReader.loadX509Certificate(ECertificateType.DISTRIBUTOR);

Log.d(TAG, "< ----- Init KeyStore ----- >");
KeyStore keyStore = KeyStore.getInstance("pkcs12");
keyStore.load(null, null);

Log.d(TAG, "< ----- Init Certificate ----- >");
Certificate[] certChain = new Certificate[2];
certChain[1] = distribCertificate;
certChain[0] = clientCertificate;

if(clientPrivateKey == null){
    Log.d(TAG, "< ----- Private Key Is NULL ----- >");
}


Log.d(TAG, "< ----- Set KeyStore ----- >");
keyStore.setKeyEntry("client", clientPrivateKey, null, certChain);

...

触发状态

  • 应用刚启动时,代码运行完全正常;
  • 手机锁屏状态下,应用可能数小时后断开连接,但能成功重连;
  • 长时间深度睡眠后(通常1-2天未使用),重连失败并出现循环错误;
  • 从状态三解锁手机后,应用仍无法重连。

异常详情

异常触发于以下代码行:

keyStore.setKeyEntry("client", clientPrivateKey, null, certChain);

日志追踪

BouncyCastleProvider    com.example.cable                    D  < ----- Loading KeyStore ----- >
BouncyCastleProvider    com.example.cable                    D  < ----- Getting Private Key ----- >
BouncyCastleProvider    com.example.cable                    D  < ----- Loading Certificates ----- >
BouncyCastleProvider    com.example.cable                    D  < ----- Init KeyStore ----- >
BouncyCastleProvider    com.example.cable                    D  < ----- Init Certificate ----- >
BouncyCastleProvider    com.example.cable                    D  < ----- Set KeyStore ----- >
BouncyCastleProvider    com.example.cable                    D  < ----- B Connection to MQTT Client is failed: java.lang.NullPointerException ----- >

异常栈追踪

java.util.Hashtable.put(Hashtable.java:477), 
org.spongycastle.jcajce.provider.keystore.pkcs12.PKCS12KeyStoreSpi$IgnoresCaseHashtable.put(PKCS12KeyStoreSpi.java:1780), 
org.spongycastle.jcajce.provider.keystore.pkcs12.PKCS12KeyStoreSpi.engineSetKeyEntry(PKCS12KeyStoreSpi.java:577),
java.security.KeyStore.setKeyEntry(KeyStore.java:1200), 
com.example.cable.crypto.MqttSSL.trySSLConnect(MqttSSL.java:132)

环境说明

使用Bouncy Castle作为安全提供者,初始化代码如下:

static {
    Security.insertProviderAt(new org.spongycastle.jce.provider.BouncyCastleProvider(), 1);
}

疑问点

目前无法确定是否由深度睡眠导致问题,但怀疑该模式下处理器加密访问被禁用引发崩溃;另外Android会定期重建服务及相关实体,是否存在旧服务的读锁导致新状态无法读取数据?


内容的提问来源于stack exchange,提问作者I am Bodya

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 06:05:04