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
相关产品推荐
相关产品推荐

