无法在三星上初始化密钥库 android
Can't initialise keystore on Samsung android
编辑:我现在在非三星 KitKat 4.4.3 设备 (Gigabyte/Zebra TC55) 上看到了这个错误。
我正在尝试在我的自定义 X509TrustManager
class 中初始化一个 null KeyStore
。
在构造函数中,我执行以下操作:
public EasyX509TrustManager(KeyStore keystore) throws NoSuchAlgorithmException, KeyStoreException, IOException, CertificateException {
super();
//keystore.load(null);
TrustManagerFactory factory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
factory.init((KeyStore) null); <--- ERROR HERE
TrustManager[] trustmanagers = factory.getTrustManagers();
if (trustmanagers.length == 0) {
throw new NoSuchAlgorithmException("no trust manager found");
}
this.standardTrustManager = (X509TrustManager) trustmanagers[0];
}
并获取以下堆栈跟踪:
java.security.KeyStoreException: initialization failed
at org.spongycastle.jsse.provider.ProvTrustManagerFactorySpi.engineInit(ProvTrustManagerFactorySpi.java:127)
at javax.net.ssl.TrustManagerFactory.init(TrustManagerFactory.java:191)
at my.android.app.http.EasyX509TrustManager.<init>(EasyX509TrustManager.java:51)
at my.android.app.http.EasySSLSocketFactory.createEasySSLContext(EasySSLSocketFactory.java:53)
at my.android.app.http.EasySSLSocketFactory.getSSLContext(EasySSLSocketFactory.java:83)
at my.android.app.http.EasySSLSocketFactory.createSocket(EasySSLSocketFactory.java:133)
at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:165)
at org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:164)
at org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:119)
at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:360)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:670)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:509)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:487)
at my.android.app.util.LoginUtils.loginOnline(LoginUtils.java:184)
at my.android.app.util.LoginUtils.login(LoginUtils.java:95)
at my.android.app.LoginActivity$UserLoginTask.doInBackground(LoginActivity.java:336)
at my.android.app.LoginActivity$UserLoginTask.doInBackground(LoginActivity.java:320)
at android.os.AsyncTask.call(AsyncTask.java:287)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
at java.util.concurrent.FutureTask.run(FutureTask.java:137)
at android.os.AsyncTask$SerialExecutor.run(AsyncTask.java:230)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569)
at java.lang.Thread.run(Thread.java:856)
Caused by: java.security.InvalidAlgorithmParameterException: trustAnchors.isEmpty()
at java.security.cert.PKIXParameters.checkTrustAnchors(PKIXParameters.java:588)
at java.security.cert.PKIXParameters.<init>(PKIXParameters.java:84)
at java.security.cert.PKIXBuilderParameters.<init>(PKIXBuilderParameters.java:58)
at org.spongycastle.jsse.provider.ProvX509TrustManager.<init>(ProvX509TrustManager.java:34)
at org.spongycastle.jsse.provider.ProvTrustManagerFactorySpi.engineInit(ProvTrustManagerFactorySpi.java:122)
... 23 more
如果我尝试按如下方式初始化工厂,我也会得到相同的堆栈跟踪:
factory.init(KeyStore.getInstance(KeyStore.getDefaultType()));
从堆栈跟踪可以看出,我正在使用 SpongyCastle
,BouncyCastle
的 Android 版本来处理我的 security/keystores 等,但是,这个问题仅出现在带有 Android JellyBean -> KitKat 的三星设备上。我有多个三星,它影响了他们所有人。我还有其他设备 运行 JellyBean,它们能够很好地连接到服务器,所以这似乎是三星独有的问题。
谁能告诉我如何解决这个密钥库初始化问题?
我没有使用自己的密钥库,所以如果可能的话,我想使用空密钥库或内置 android 密钥库。
这是来自 logcat 的更多日志,这些日志来自非三星 4.4.3 设备,可能会有帮助:
03-28 15:10:06.357 8084-8423/my.android.app W/dalvikvm: Unable to resolve superclass of Lorg/spongycastle/jsse/provider/ProvX509ExtendedTrustManager; (377)
03-28 15:10:06.367 8084-8423/my.android.app W/dalvikvm: Link of class 'Lorg/spongycastle/jsse/provider/ProvX509ExtendedTrustManager;' failed
03-28 15:10:06.367 8084-8423/my.android.app E/dalvikvm: Could not find class 'org.spongycastle.jsse.provider.ProvX509ExtendedTrustManager', referenced from method org.spongycastle.jsse.provider.ProvTrustManagerFactorySpi.engineInit
03-28 15:10:06.367 8084-8423/my.android.app W/dalvikvm: VFY: unable to resolve new-instance 3263 (Lorg/spongycastle/jsse/provider/ProvX509ExtendedTrustManager;) in Lorg/spongycastle/jsse/provider/ProvTrustManagerFactorySpi;
03-28 15:10:06.367 8084-8423/my.android.app D/dalvikvm: VFY: replacing opcode 0x22 at 0x006e
03-28 15:10:06.377 8084-8423/my.android.app W/dalvikvm: Unable to resolve superclass of Lorg/spongycastle/jsse/provider/ProvX509ExtendedTrustManager; (377)
Link of class 'Lorg/spongycastle/jsse/provider/ProvX509ExtendedTrustManager;' failed
03-28 15:10:06.377 8084-8423/my.android.app E/dalvikvm: Could not find class 'org.spongycastle.jsse.provider.ProvX509ExtendedTrustManager', referenced from method org.spongycastle.jsse.provider.ProvTrustManagerFactorySpi.engineInit
03-28 15:10:06.377 8084-8423/my.android.app W/dalvikvm: VFY: unable to resolve new-instance 3263 (Lorg/spongycastle/jsse/provider/ProvX509ExtendedTrustManager;) in Lorg/spongycastle/jsse/provider/ProvTrustManagerFactorySpi;
03-28 15:10:06.377 8084-8423/my.android.app D/dalvikvm: VFY: replacing opcode 0x22 at 0x001e
03-28 15:10:06.387 8084-8423/my.android.app W/dalvikvm: Unable to resolve superclass of Lorg/spongycastle/jsse/provider/ProvX509ExtendedTrustManager; (377)
Link of class 'Lorg/spongycastle/jsse/provider/ProvX509ExtendedTrustManager;' failed
03-28 15:10:06.387 8084-8423/my.android.app D/dalvikvm: DexOpt: unable to opt direct call 0x3ea1 at 0x77 in Lorg/spongycastle/jsse/provider/ProvTrustManagerFactorySpi;.engineInit
03-28 15:10:06.397 8084-8423/my.android.app W/dalvikvm: Unable to resolve superclass of Lorg/spongycastle/jsse/provider/ProvX509ExtendedTrustManager; (377)
Link of class 'Lorg/spongycastle/jsse/provider/ProvX509ExtendedTrustManager;' failed
03-28 15:10:06.397 8084-8423/my.android.app D/dalvikvm: DexOpt: unable to opt direct call 0x3ea1 at 0x27 in Lorg/spongycastle/jsse/provider/ProvTrustManagerFactorySpi;.engineInit
谢谢。
我明白了,post 答案也会,但我需要放弃赏金,所以第一个回答的人会得到它。
从代码中可以看出,对于 Lollipop 下的设备,您不能将空密钥库传递给系统密钥库,您必须通过引用 AndroidCAStore
获取实例。看这里:
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
context = SSLContext.getInstance("TLSv1.2", new BouncyCastleJsseProvider());
KeyStore keyStore = KeyStore.getInstance("AndroidCAStore");//KeyStore.getDefaultType());
keyStore.load(null, null);
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
keyManagerFactory.init(keyStore, null);
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(keyStore);
context.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), new SecureRandom());
} else {
context = SSLContext.getInstance("TLSv1.2");
context.init(null, null, null);
}
我不确定为什么必须这样做。可能是因为我正在使用 SpongyCastle
,或者三星在其 SocketFactory 的实现中更改了某些内容。
编辑:我现在在非三星 KitKat 4.4.3 设备 (Gigabyte/Zebra TC55) 上看到了这个错误。
我正在尝试在我的自定义 X509TrustManager
class 中初始化一个 null KeyStore
。
在构造函数中,我执行以下操作:
public EasyX509TrustManager(KeyStore keystore) throws NoSuchAlgorithmException, KeyStoreException, IOException, CertificateException {
super();
//keystore.load(null);
TrustManagerFactory factory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
factory.init((KeyStore) null); <--- ERROR HERE
TrustManager[] trustmanagers = factory.getTrustManagers();
if (trustmanagers.length == 0) {
throw new NoSuchAlgorithmException("no trust manager found");
}
this.standardTrustManager = (X509TrustManager) trustmanagers[0];
}
并获取以下堆栈跟踪:
java.security.KeyStoreException: initialization failed
at org.spongycastle.jsse.provider.ProvTrustManagerFactorySpi.engineInit(ProvTrustManagerFactorySpi.java:127)
at javax.net.ssl.TrustManagerFactory.init(TrustManagerFactory.java:191)
at my.android.app.http.EasyX509TrustManager.<init>(EasyX509TrustManager.java:51)
at my.android.app.http.EasySSLSocketFactory.createEasySSLContext(EasySSLSocketFactory.java:53)
at my.android.app.http.EasySSLSocketFactory.getSSLContext(EasySSLSocketFactory.java:83)
at my.android.app.http.EasySSLSocketFactory.createSocket(EasySSLSocketFactory.java:133)
at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:165)
at org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:164)
at org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:119)
at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:360)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:670)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:509)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:487)
at my.android.app.util.LoginUtils.loginOnline(LoginUtils.java:184)
at my.android.app.util.LoginUtils.login(LoginUtils.java:95)
at my.android.app.LoginActivity$UserLoginTask.doInBackground(LoginActivity.java:336)
at my.android.app.LoginActivity$UserLoginTask.doInBackground(LoginActivity.java:320)
at android.os.AsyncTask.call(AsyncTask.java:287)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
at java.util.concurrent.FutureTask.run(FutureTask.java:137)
at android.os.AsyncTask$SerialExecutor.run(AsyncTask.java:230)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569)
at java.lang.Thread.run(Thread.java:856)
Caused by: java.security.InvalidAlgorithmParameterException: trustAnchors.isEmpty()
at java.security.cert.PKIXParameters.checkTrustAnchors(PKIXParameters.java:588)
at java.security.cert.PKIXParameters.<init>(PKIXParameters.java:84)
at java.security.cert.PKIXBuilderParameters.<init>(PKIXBuilderParameters.java:58)
at org.spongycastle.jsse.provider.ProvX509TrustManager.<init>(ProvX509TrustManager.java:34)
at org.spongycastle.jsse.provider.ProvTrustManagerFactorySpi.engineInit(ProvTrustManagerFactorySpi.java:122)
... 23 more
如果我尝试按如下方式初始化工厂,我也会得到相同的堆栈跟踪:
factory.init(KeyStore.getInstance(KeyStore.getDefaultType()));
从堆栈跟踪可以看出,我正在使用 SpongyCastle
,BouncyCastle
的 Android 版本来处理我的 security/keystores 等,但是,这个问题仅出现在带有 Android JellyBean -> KitKat 的三星设备上。我有多个三星,它影响了他们所有人。我还有其他设备 运行 JellyBean,它们能够很好地连接到服务器,所以这似乎是三星独有的问题。
谁能告诉我如何解决这个密钥库初始化问题? 我没有使用自己的密钥库,所以如果可能的话,我想使用空密钥库或内置 android 密钥库。
这是来自 logcat 的更多日志,这些日志来自非三星 4.4.3 设备,可能会有帮助:
03-28 15:10:06.357 8084-8423/my.android.app W/dalvikvm: Unable to resolve superclass of Lorg/spongycastle/jsse/provider/ProvX509ExtendedTrustManager; (377)
03-28 15:10:06.367 8084-8423/my.android.app W/dalvikvm: Link of class 'Lorg/spongycastle/jsse/provider/ProvX509ExtendedTrustManager;' failed
03-28 15:10:06.367 8084-8423/my.android.app E/dalvikvm: Could not find class 'org.spongycastle.jsse.provider.ProvX509ExtendedTrustManager', referenced from method org.spongycastle.jsse.provider.ProvTrustManagerFactorySpi.engineInit
03-28 15:10:06.367 8084-8423/my.android.app W/dalvikvm: VFY: unable to resolve new-instance 3263 (Lorg/spongycastle/jsse/provider/ProvX509ExtendedTrustManager;) in Lorg/spongycastle/jsse/provider/ProvTrustManagerFactorySpi;
03-28 15:10:06.367 8084-8423/my.android.app D/dalvikvm: VFY: replacing opcode 0x22 at 0x006e
03-28 15:10:06.377 8084-8423/my.android.app W/dalvikvm: Unable to resolve superclass of Lorg/spongycastle/jsse/provider/ProvX509ExtendedTrustManager; (377)
Link of class 'Lorg/spongycastle/jsse/provider/ProvX509ExtendedTrustManager;' failed
03-28 15:10:06.377 8084-8423/my.android.app E/dalvikvm: Could not find class 'org.spongycastle.jsse.provider.ProvX509ExtendedTrustManager', referenced from method org.spongycastle.jsse.provider.ProvTrustManagerFactorySpi.engineInit
03-28 15:10:06.377 8084-8423/my.android.app W/dalvikvm: VFY: unable to resolve new-instance 3263 (Lorg/spongycastle/jsse/provider/ProvX509ExtendedTrustManager;) in Lorg/spongycastle/jsse/provider/ProvTrustManagerFactorySpi;
03-28 15:10:06.377 8084-8423/my.android.app D/dalvikvm: VFY: replacing opcode 0x22 at 0x001e
03-28 15:10:06.387 8084-8423/my.android.app W/dalvikvm: Unable to resolve superclass of Lorg/spongycastle/jsse/provider/ProvX509ExtendedTrustManager; (377)
Link of class 'Lorg/spongycastle/jsse/provider/ProvX509ExtendedTrustManager;' failed
03-28 15:10:06.387 8084-8423/my.android.app D/dalvikvm: DexOpt: unable to opt direct call 0x3ea1 at 0x77 in Lorg/spongycastle/jsse/provider/ProvTrustManagerFactorySpi;.engineInit
03-28 15:10:06.397 8084-8423/my.android.app W/dalvikvm: Unable to resolve superclass of Lorg/spongycastle/jsse/provider/ProvX509ExtendedTrustManager; (377)
Link of class 'Lorg/spongycastle/jsse/provider/ProvX509ExtendedTrustManager;' failed
03-28 15:10:06.397 8084-8423/my.android.app D/dalvikvm: DexOpt: unable to opt direct call 0x3ea1 at 0x27 in Lorg/spongycastle/jsse/provider/ProvTrustManagerFactorySpi;.engineInit
谢谢。
我明白了,post 答案也会,但我需要放弃赏金,所以第一个回答的人会得到它。
从代码中可以看出,对于 Lollipop 下的设备,您不能将空密钥库传递给系统密钥库,您必须通过引用 AndroidCAStore
获取实例。看这里:
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
context = SSLContext.getInstance("TLSv1.2", new BouncyCastleJsseProvider());
KeyStore keyStore = KeyStore.getInstance("AndroidCAStore");//KeyStore.getDefaultType());
keyStore.load(null, null);
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
keyManagerFactory.init(keyStore, null);
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(keyStore);
context.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), new SecureRandom());
} else {
context = SSLContext.getInstance("TLSv1.2");
context.init(null, null, null);
}
我不确定为什么必须这样做。可能是因为我正在使用 SpongyCastle
,或者三星在其 SocketFactory 的实现中更改了某些内容。