Java TLS 套接字:找不到受信任的证书

2023-11-26

让我快速解释一下我想要做什么。我正在尝试用 java 构建我自己的 Apple 推送通知服务(用于测试目的)。该服务的工作得益于 TLS 套接字。

我有一个 java 客户端来创建 TLS 套接字以向 APN 发送推送通知。我更改了主机 url 以将套接字重定向到 localhost:2195。现在我正在尝试编写一个java套接字服务器来获取通知请求。

但是,我在握手过程中遇到异常,并且找不到如何修复它。

注意:我在两侧使用相同的证书,它是一个标准 .p12 文件,用于向 APN 发送推送通知。

这是客户端(简化):

KeyStore ks = KeyStore.getInstance("PKCS12");
ks.load(new FileInputStream(certificatePath), password.toCharArray());

KeyManagerFactory kmf = KeyManagerFactory.getInstance("sunx509");
kmf.init(ks, password.toCharArray());

TrustManagerFactory tmf = TrustManagerFactory.getInstance("sunx509"); 
tmf.init((KeyStore)null);

SSLContext sc = SSLContext.getInstance("TLS"); 
sc.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); 

SSLSocketFactory ssf = sc.getSocketFactory(); 
SSLSocket socket = (SSLSocket) ssf.createSocket(InetAddress.getLocalHost(), 2195);
socket.startHandshake();

这是服务器:

KeyStore ks = KeyStore.getInstance("PKCS12");
ks.load(new FileInputStream(certificatePath), password.toCharArray());

KeyManagerFactory kmf = KeyManagerFactory.getInstance("sunx509");
kmf.init(ks, password.toCharArray());

SSLContext context = SSLContext.getInstance("TLS");
context.init(kmf.getKeyManagers(), null, null);

SSLServerSocketFactory ssf = context.getServerSocketFactory();
serverSocket = (SSLServerSocket) ssf.createServerSocket(2195);

这是一个例外:

javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: No trusted certificate found

我猜客户端不信任服务器的证书。我尝试将客户端的 TrustManager 设置为接受服务器的 p12 并且它有效,但是我需要它在不编辑客户端的情况下工作(因为它与真正的 APN 一起工作)。

服务器需要什么样的证书才能被客户端信任?

提前致谢。


EDIT: 我错了! tmf.init(null) 确实使用默认密钥库,就像 sslctx.init(,null,) 一样! 默认值通常是 JRE/lib/security 中的 cacerts 文件,它信任许多已建立的 CA 所以现在我认为我们可以确信真正的服务器正在使用已建立的 CA 下的证书(所以 被你的客户信任),而你的 p12 中的证书显然不信任; 但这里有两种可能性:

  • 它是自签名的,或者由未知、模糊或未经验证的 CA 颁发

  • 它是由需要链证书(或多个)的“中间”CA 下的“真实”CA 颁发的 并且您的 p12 中没有链证书。请注意,这仍然适用于客户端身份验证 到真实服务器,因为真实服务器可以轻松“预加载”链证书 即使它们不在 Java 中,也位于其信任库中。

要区分这些,请查看keytool -keystore file -storetype pkcs12 -list -v并查看您拥有什么证书或证书序列。

那么解决的办法可能有以下几种:

  1. 如果您仅缺少已建立的 CA 的链证书,请获取并添加它们。 keytool 只允许您替换整个链,因此您必须获得所有需要的证书; openssl(如果您有或得到它)可以从 pkcs12 中提取密钥和证书, 替换或添加单个证书,然后将它们重新组合在一起。

  2. 为服务器创建不同的存储和密钥,并从已建立的 CA 获取证书(链)。 通常需要花费一些钱,并且需要您证明对服务器域名的控制权。 (您的客户可以而且应该仍然使用此 p12。两侧不必相同。)

  3. 找到信任锚(从 p12,或从其他地方,如 CA)并拥有它 在客户端显式加载的信任库中。您通过使用有效地尝试了这一点 p12 作为信任库并说您不希望这样。

  4. 将信任锚放入客户端的默认信任库中,以便客户端继续 使用默认值。如果您不介意修改您的 JRE(并且没有其他用户或应用程序 在你的系统上很麻烦)只需添加到 JRE/lib/security/cacerts.或者,假设您可以设置 系统属性,将锚点放入商店或将其留在 p12 中 并将 javax.net.ssl.trustStore{,Password,Type} 设置为指向该商店。 (如果您复制,您应该只获取证书;p12 是一个密钥和证书,而不仅仅是一个证书。 不要只是 -importkeystore; -importcert 证书文件,如有必要,使用 -exportcert 创建。) (您可以在代码中使用 System.setProperty,但这会更改您的代码。如果您从 命令行您可以使用“java -Dname=value...”。对于其他情况YMMV。)

存在一个可能的“类型”问题:如果证书是使用 ExtendedKeyUsage 扩展颁发的 并且该值仅指定 TLSclient 而不是 TLSserver(CA 可以选择这样做) 然后将其用于服务器probably不起作用——看来 JSSE 强制执行 EKU 限制。 但如果这是一个问题,你会得到一个非常不同的异常。 您也可以在上面的 keytool -list -v 中看到这一点。

由于您(正确地)希望为您的客户端使用此 p12,因此您的服务器逻辑同样需要 去相信它。 (将其用于传出身份验证不会自动使其受传入身份验证信任。) 但只有当 clientAuth 实际完成时,这不是默认的;你的服务器代码有吗 接受连接之前 SSLServerSocket 上的 .setNeedClientAuth(true) ? 可能的方法与上述相同,只是跳过#2 不适用。 如果客户端和服务器都使用相同的 JRE,那么 cacerts 的方式就会更容易一些。

最后,是的,TrustManager 'PKIX' 比 'SunX509' 更新且通常功能更丰富。 但对于基本测试“是我们信任库中的信任锚”,它们是等效的。

再次抱歉造成误导。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Java TLS 套接字:找不到受信任的证书 的相关文章

随机推荐

  • 如何避免在 Angular 2 中使用很长的相对路径进行导入?

    我怎样才能介绍类似的东西 my app name services 以避免像下面这样的导入行 import XyService from services validation xy service 打字稿 2 0 在 TypeScript
  • 由使用本地系统帐户的 Windows 服务启动的可执行文件无法访问网络共享

    我有一个由 Windows 服务启动的可执行文件 该程序将在客户计算机上运行 并且需要连接到远程共享才能执行特定任务 该共享由客户通过 UI 指定 因此我们事先不知道这一点 这意味着它不能 硬编码 也不能提前映射共享 以前我们要求客户登录到
  • 将 IPython 笔记本导出到 Reveal.js 时如何分隔幻灯片?

    当我使用 IPython 笔记本执行 Reveal js 演示文稿时 ipython nbconvert mynotebook ipynb to slides post serve 我将所有内容作为一张幻灯片来获取 如何将我的内容分成几张幻
  • 如何在 SQL Server 数据库中设计用户/角色架构?

    我想设计一个用户 角色系统 用户有一个名称和一个密码 然后用户可以有多个角色 例如Admin 为此 我创建了一个如下的架构 Users CREATE TABLE dbo Users id int NOT NULL name nvarchar
  • 如何easy_install Egg插件并在不重新启动应用程序的情况下加载它?

    我正在创建一个下载并安装自己的 Egg 插件的应用程序 但在 easy install 将 Egg 提取到位后加载 Egg 时遇到问题 现在是这样的 应用程序将egg下载到临时文件夹中 使用 setuptools command easy
  • EPERM,操作不允许错误,配置存储

    我知道这是一个常见错误node但我所有的故障排除技术似乎都失败了 Windows 7 32 位 电子邮件受保护 电子邮件受保护 当尝试运行诸如以下的包命令时会出现此问题bower and yo 自耕农 为了保持理智 在执行这些命令时 我处于
  • NumPy 或 Pandas:在具有 NaN 值的同时将数组类型保持为整数

    是否有一种首选方法来保留 a 的数据类型numpy数组固定为int or int64或其他 同时仍然有一个元素被列为numpy NaN 特别是 我正在将内部数据结构转换为 Pandas DataFrame 在我们的结构中 我们有仍然具有 N
  • 是否可以在 BigQuery 中使用 MD5 进行哈希处理?

    BigQuery 是否具有 MD5 功能 我知道它有 cityhash 但我特别需要 MD5 谢谢 例如 由于这会出现在 Google 搜索 BigQuery MD5 中 因此值得指出的是 BigQuery 本身支持以下哈希函数标准SQL
  • 相对较慢的python numpy 3D傅里叶变换

    对于我的工作 我需要对大图像执行离散傅立叶变换 DFT 在当前示例中 我需要 1921 x 512 x 512 图像的 3D FT 以及 512 x 512 图像的 2D FFT 现在 我正在使用 numpy 包和相关函数np fft ff
  • Java 中的按位与、按位或或问题

    我的项目中有几行代码 我看不到它们的价值 buffer i currentByte 0x7F currentByte 0x80 它从文件中读取文件缓冲区 存储为字节 然后传输到 buffer i 如图所示 但我无法理解总体目的是什么 有什么
  • 如何使用 CSS 设置警报框样式?

    更新 我读了很多关于这个主题的文章 尝试了一些脚本 需要帮助来找出你能做什么或不能做什么 社区回答了这一切 以下是一个很好的起点 这里的答案摘自下面的社区 谢谢 您无法覆盖默认的警报方式 它是由您的客户端生成的 edge chrome fi
  • 如何在 VB.NET 中获取 Caps Lock 的当前状态?

    如何使用 VB NET 查明 Caps Lock 是否已激活 这是我的后续先前的问题 Control IsKeyLocked Keys 方法 MSDN Imports System Imports System Windows Forms
  • XmlSerializer、“指定”后缀和 IReflect

    我发现如果一个可序列化的领域 财产有一个对应的类型字段Boolean名字为领域 财产带有 指定 后缀的名称 XmlSerializer 有条件地排除该名称领域 财产从序列化过程来看 好的 所以 我想避免这些字段的定义 并在运行时动态添加它们
  • curl 响应显示“不支持 HTTP 版本”,错误 505

    我使用curl发出请求 响应说不支持HTTP版本 错误505 使HTTP版本受支持的步骤是什么 谷歌搜索后 我应该使用curl http2 0 来使其工作 但我的curl 版本不支持该选项 因为它是在curl 7 33 中添加的 而我使用的
  • 我可以从脚本或命令行将文件复制到网上邻居吗? [关闭]

    Closed 这个问题是无关 目前不接受答案 在 Windows XP 中 是否可以通过命令行 批处理文件或者更好的 PowerShell 脚本将文件复制到网上邻居 让我走上这条研究道路的是尝试将文件从用户的计算机发布到 WSS 3 0 文
  • Notepad++ 正则表达式 -> newLine

    我使用 Notepad 我需要删除以 abc 开头的所有行 注意 我不需要将以 abc 开头的行替换为空行 但我需要完全删除这些行 我该如何继续 我想使用正则表达式 尝试更换 abc r n with nothing The 表示一行的开始
  • jQuery 动画回到原始位置

    我正在开发一个网站 其中有一些绝对定位的 div 我需要在单击时调整其大小 然后这些将填充 div 所在的容器 问题是如何让它们切换到去返回到原始位置 顶部 左侧 每个位置都不同 work item toggle toggle functi
  • 单例或类方法[重复]

    这个问题在这里已经有答案了 阅读完对某个问题的回复后question关于 Objective C 中的单例 似乎每个解决方案都在实例访问器中的线程方面做出了一些权衡 IE synchronized self if sharedInstanc
  • 不在对象上下文中时使用 $this - Laravel 4 PHP 5.4.12

    我试图使用变量 this 访问构造函数上的实例 在所有其他方法中 当我打电话时似乎效果很好 this gt event gt method 但在这个方法上它给我一个错误 不在对象上下文中时使用 this 我刚刚对这个问题进行了研究 我发现的
  • Java TLS 套接字:找不到受信任的证书

    让我快速解释一下我想要做什么 我正在尝试用 java 构建我自己的 Apple 推送通知服务 用于测试目的 该服务的工作得益于 TLS 套接字 我有一个 java 客户端来创建 TLS 套接字以向 APN 发送推送通知 我更改了主机 url