Android:CertPathValidatorException:找不到证书路径的信任锚

时间:2014-03-11 00:05:18

标签: java android security ssl

我相信我已根据相关文章做了我应该做的一切,但我仍然得到这个错误。我创建了自己的CA并使用此CA签署了服务器证书。在Android方面,我使用自定义信任库创建了一个自定义TrustManager,其中包含此CA根证书。在服务器端使用System.setProperty(“javax.net.debug”,“ssl”)(即使在4.4中它也不能在Android端工作)我得到了更多的信息。我通过服务器问候和交换密钥。然后Android给我上面的错误(找不到认证路径的信任锚),在服务器端我得到 javax.net.ssl.SSLException:在收到对等方的close_notify之前关闭入站:可能的截断攻击?

我在我的电脑上镜像了应用程序(客户端)并且它可以工作。

Android是否支持使用SHA512withRSA 的2048密钥? 我对自签名证书没有问题(1024和SHA1withRSA);没有尝试使用2048和SHA512的自签名证书。

不知何故,我认为这是Android的一个缺点,没有记录或很难找到(有点像System.setProperty(“javax.net.debug”,“ssl”)无效)。

我实际上实现了自己的KeyManager和TrustManager以及密钥库和信任库,因为最终我需要相互TLS ...所有在PC上工作。希望它能够轻松迁移到Android。

以下是Keystores / Truststores的Android设置(获取文件并加载它们)

 LoadFile(getString(R.string.truststore_filename), R.raw.androidtruststore);
 LoadFile(getString(R.string.keystore_filename), R.raw.androidkeystore);
 String basePath = getFilesDir().getAbsolutePath() + "/";
 SecureRawHttpWanSender.setSecureProperties(basePath + getString(R.string.truststore_filename), 
                                                   getString(R.string.truststore_password),
                                                   basePath + getString(R.string.keystore_filename),
                                                   getString(R.string.keystore_password),
                                                   true);

这是在setSecureProperties()中完成的TrustManagers等的设置,它也在PC上使用。只加载文件是不同的(PC使用jks和Android使用bks)

    FileInputStream fIS = null;
    try
    {
        // On Android this is "BKS". Otherwise Sun Java is "JKS"
        trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
        Manager.log.log(Level.Info, Task.WanSecure, "Type of truststore: " + trustStore.getType());
        fIS = new FileInputStream(trustStoreFileName);
        trustStore.load(fIS, trustStorePassword.toCharArray());
        fIS.close();
        tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
        tmf.init(trustStore);
        if(keyStoreFileName != null)
        {
            keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
            Manager.log.log(Level.Info, Task.WanSecure, "Type of keystore: " + keyStore.getType());
            fIS = new FileInputStream(keyStoreFileName);
            keyStore.load(fIS, keyStorePassword.toCharArray());
            fIS.close();
            kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
            kmf.init(keyStore, keyStorePassword.toCharArray());
        }
        return true;
    }

感谢您的帮助(我发现任何我真正愚蠢的事情!)

1 个答案:

答案 0 :(得分:0)

我找到了上述问题的解决方案,但我不喜欢它。我可能实际上已经看到它在与该主题相关的一个问题中的其他地方提到过。我所做的是在android信任库中添加由CA签名的服务器证书。所以现在在我的信任库中,我有两个服务器证书,CA签署的服务器证书和CA根证书。

我不喜欢的是不一致。在我的Windows 7 PC上,我不需要CA签名的服务器证书,只需拥有CA根。我可以理解中间证书的必要性,如果服务器证书由CA签名,CA可能由信任库中的根CA验证,但中间CA的证书不在信任库中。然后链条被打破。

为什么我需要CA根签名的服务器证书以及Android上的根CA. 只需要我的PC上的根CA就显得非常混乱。我认为它是一个典型的不完整的Android实现。正如我发现XML模式验证的情况一样!