java - Android:CertPathValidatorException:找不到证书路径的信任 anchor

标签 java android security ssl

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

我已经在我的 PC 上镜像了应用程序(客户端)并且它可以运行。

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

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

我实际上实现了自己的 KeyManager 和 TrustManager 以及 keystore 和信任库,因为最终我将需要相互 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;
    }

感谢您的帮助(以及发现我所做的任何事情都非常愚蠢!)

最佳答案

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

我不喜欢的是不一致。在我的 Windows 7 PC 上,我不需要由 CA 签名的服务器证书,拥有 CA root 就足够了。如果服务器证书是由 CA 签名的,我可以理解对中间证书的需求,该 CA 可能由信任库中的根 CA 验证但中间 CA 的证书不在信任库中。然后链条就断了。

为什么我在Android上需要根CA加根CA签名的服务器证书但是 只需要我的 PC 上的根 CA 就很容易混淆。我将其视为 Android 的典型不完整实现。正如我所发现的那样,XML 模式验证就是如此!

关于java - Android:CertPathValidatorException:找不到证书路径的信任 anchor ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22313892/

相关文章:

android - 我的 Android 应用必须在市场上发布才能从 AdMob 赚取广告收入吗?

java - 在 Libgdx 中使用对象池

wpf - 在 Internet Explorer 中关闭 WPF XBAP 应用程序的安全消息

java - 实现从main到fragment的菜单项

java - 将节点添加到 JTree 时,startEditingAtPath() 抛出异常

java - 计时器和线程问题

Java需要实现默认方法

security - 是否使用 GUID 安全性虽然默默无闻?

asp.net - 通过经过身份验证的 Web 表单保护 ASP.net 中的 Ajax 请求

java - 使用 Java 输出 Google 自定义搜索解析后的 JSON 结果