获取从 RPGLE 调用的 AS400 java 应用程序以信任 .PFX 证书
getting an AS400 java application called from RPGLE to trust a .PFX certificate
我整天都在为此工作,只是在猜测该怎么做。似乎知道此功能如何工作的人假设其他人都知道他们在说什么。他们会说诸如使用实用程序 ABC 生成 DEF 之类的话,但假设您知道 ABC 是什么、如何使用它以及完成后如何处理 DEF。让我先说我本质上是一名 AS400 RPG 编码员,但可以在 Java 中做一些事情。我猜已经够危险了。我仍然不太明白什么是信任库,甚至在技术上什至是密钥库。
基本上,我开发了一个简单的 AS400 java 应用程序,它基本上只是调用一些 HTTP 方法来向外部方发送交易。此应用程序直接从 RPGLE 程序调用。这一直运行良好,但现在他们决定使用 HTTPS。客户向我发送了一个 .PFX 文件,其中包含他们在 AS400 上使用名为数字证书管理器的实用程序创建密钥时的一些内容。我已经找到足够的信息来收集我必须在 IFS 的根应用程序目录中有一个 SSL 属性文件,并且工作正在查看该属性文件并且它似乎具有正确的参数。我遇到困难的是如何让证书信任应用程序。我不确定您是否需要 .PFX 文件存在于应用程序的 IFS 根目录中,或者您是否必须创建信任 store/key 存储,或者除了 SSL 属性文件之外您是否还需要任何东西?我发现所有问题的答案都是肯定的,这取决于你问的是谁。一些答案会引导您走上穷尽所有事情的道路,以到达某个点,结果什么也没有发生。这比什么都更像是发泄。我几乎得出结论,这东西是不可能的。 :)
下面是我用于仅使用 HTTP 连接到服务的代码。我一直在寻找一个简单的分步过程来解释在 AS400 上成功进行 HTTPS 握手需要什么。我没有足够的信息来判断我是否需要从客户那里获得更多信息,或者我是否有足够的信息让我自己完成。
HttpClient m_HttpClient = null;
PostMethod m_PostMthd = null;
SimpleHttpConnectionManager m_simpleHttpConMnger = new
SimpleHttpConnectionManager();
int timeoutInMilliseconds = 10000;
m_PostMthd = new PostMethod(urlEndpoint);
m_HttpClient = new HttpClient(m_simpleHttpConMnger);
HttpConnectionManagerParams lhttpConMnger =
m_simpleHttpConMnger.getParams();
lhttpConMnger.setConnectionTimeout(timeoutInMilliseconds);
lhttpConMnger.setSoTimeout(timeoutInMilliseconds);
m_PostMthd.setRequestHeader("SOAPAction",SOAPAction);
m_PostMthd.setRequestHeader("Content-Type","text/xml; charset=UTF-8");
m_PostMthd.setRequestEntity(new StringRequestEntity(inputMsg));
int l_status = m_HttpClient.executeMethod(m_PostMthd);
System.out.println("EXECUTION STATUS : " + l_status+"\n");
InputStream is = m_PostMthd.getResponseBodyAsStream();
BufferedReader rd = new BufferedReader(new InputStreamReader(is));
String line;
StringBuilder response = new StringBuilder();
while ((line = rd.readLine()) != null)
{
response.append(line);
response.append('\r');
}
rd.close();
return response.toString();
我认为这里有两个不同的问题:如何在 Java 中使用 PFX 文件,以及我应该如何处理它。第一个相当简单,第二个可能需要一些额外的信息,但我会尽我所能回答。
在 Java
中处理 PFX
PFX 是一种容器文件格式,可以包含一堆与 SSL/TLS 和密码学相关的不同类型的数据。 Java 有自己的容器格式,称为 JKS KeyStore。从广义上讲,这些是保存同类数据的等效方法,您只需要从一个导出到另一个。事先做这件事比在 运行 时尝试做要容易。引用 this answer:
keytool -importkeystore \
-srckeystore mypfxfile.pfx -srcstoretype pkcs12 \
-destkeystore clientcert.jks -deststoretype JKS
Keytool 包含在 JDK 中。一路上它会要求输入一些密码。您可以使用 keytool -list -keystore file.jks
命令来显示
JKS 文件。
我应该用这些东西做什么?
这个要看情况,这里你的问题有点含糊。在所有情况下,目的都是 身份验证 :客户端需要验证它正在与正确的服务器对话,并且可选地,服务器需要验证它正在与正确的客户端对话。这涉及三位信息和大量数学。
- 私钥和public密钥(连同一些数学,通常是RSA算法)用于创建一个锁和钥匙系统。您将私钥留给自己,并与需要它的任何人共享 public 密钥。这些在身份验证中的使用方式是使用私钥以数学方式提出可以使用 public 密钥验证的声明。数学是这样的,几乎不可能伪造这种说法。因此,如果经过数学检验,您可以确定与您交谈的人持有私钥。简而言之,这是数字签名。
- 一个证书嵌入了一个public密钥并向其中添加了一堆信息(密钥基本上只是一个巨大的素数,所以它在它自己的)。添加的信息包括密钥持有者的身份,以及保证证书有效性的颁发者的身份,所有这些都用数字签名密封。
根据应用程序的不同,您收到的 PFX 文件可能仅包含证书,也可能包含证书和相应的私钥(或两者)。
keytool -list
的输出将显示任意数量的 trustedCertEntry
记录,这些是没有可用私钥的证书,它可能包含一个 privateKeyEntry
,这是一个同时存在证书及其私钥的记录。记下任何私钥条目的 alias
。
客户端验证服务器
创建 HTTPS 连接时,服务器会向客户端出示证书,并证明服务器持有与证书中嵌入的 public 密钥相对应的私钥。客户端将不得不决定它是信任服务器的身份,还是中止连接。它通过数学检查服务器提供的证书与称为信任库的预共享受信任证书列表(cacerts
是一个常见的文件系统名称)来实现。
您的 OS'es 和网络浏览器都附带一个默认的信任库;此机制位于浏览器中的挂锁图标后面。
在您的情况下,您要连接的端点可能使用默认信任库中不存在的证书,因此您必须提供自己的[信任库]。
假设 Java 在 AS/400 上的工作方式与 Java 在 Windows 和 Linux 上的工作方式相同,您可以(引用 this answer)传递一个名为 javax.net.ssl.trustStore
的 Java 系统 属性,其中包含 JKS 密钥库的文件系统路径,其中包含可信签署人的证书。
另一种方法是将 JKS 文件命名为 jssecacerts
并将其放在您的 jre/lib/security
目录中,但请记住,它现在会影响 all java 处理 运行 使用该 JVM 安装而不仅仅是您正在执行此工作的那个。
服务器验证客户端
在网络上用的不多,但是HTTPS有做双向证书验证的选项。这意味着在客户端以上述方式对服务器进行身份验证后,服务器现在对客户端进行身份验证。这是完全相同的过程,但方向相反。
在专有SOAP服务中比较常见,所以这里可能就是这种情况。你的问题对我来说并不是很清楚。
这意味着您的应用程序必须向服务器提供证书,并且它必须拥有与证书中嵌入的 public 密钥相对应的私钥。遗憾的是,我自己在 Java 中从来没有这样做过,所以我不知道您必须传递的确切命令。您需要寻找一种方法来告诉您的连接这些事情:
- 要使用什么 JKS 密钥库文件(+它的密码)
- 使用那个 JKS 的哪个密钥别名(+它的密码)
我整天都在为此工作,只是在猜测该怎么做。似乎知道此功能如何工作的人假设其他人都知道他们在说什么。他们会说诸如使用实用程序 ABC 生成 DEF 之类的话,但假设您知道 ABC 是什么、如何使用它以及完成后如何处理 DEF。让我先说我本质上是一名 AS400 RPG 编码员,但可以在 Java 中做一些事情。我猜已经够危险了。我仍然不太明白什么是信任库,甚至在技术上什至是密钥库。
基本上,我开发了一个简单的 AS400 java 应用程序,它基本上只是调用一些 HTTP 方法来向外部方发送交易。此应用程序直接从 RPGLE 程序调用。这一直运行良好,但现在他们决定使用 HTTPS。客户向我发送了一个 .PFX 文件,其中包含他们在 AS400 上使用名为数字证书管理器的实用程序创建密钥时的一些内容。我已经找到足够的信息来收集我必须在 IFS 的根应用程序目录中有一个 SSL 属性文件,并且工作正在查看该属性文件并且它似乎具有正确的参数。我遇到困难的是如何让证书信任应用程序。我不确定您是否需要 .PFX 文件存在于应用程序的 IFS 根目录中,或者您是否必须创建信任 store/key 存储,或者除了 SSL 属性文件之外您是否还需要任何东西?我发现所有问题的答案都是肯定的,这取决于你问的是谁。一些答案会引导您走上穷尽所有事情的道路,以到达某个点,结果什么也没有发生。这比什么都更像是发泄。我几乎得出结论,这东西是不可能的。 :)
下面是我用于仅使用 HTTP 连接到服务的代码。我一直在寻找一个简单的分步过程来解释在 AS400 上成功进行 HTTPS 握手需要什么。我没有足够的信息来判断我是否需要从客户那里获得更多信息,或者我是否有足够的信息让我自己完成。
HttpClient m_HttpClient = null;
PostMethod m_PostMthd = null;
SimpleHttpConnectionManager m_simpleHttpConMnger = new
SimpleHttpConnectionManager();
int timeoutInMilliseconds = 10000;
m_PostMthd = new PostMethod(urlEndpoint);
m_HttpClient = new HttpClient(m_simpleHttpConMnger);
HttpConnectionManagerParams lhttpConMnger =
m_simpleHttpConMnger.getParams();
lhttpConMnger.setConnectionTimeout(timeoutInMilliseconds);
lhttpConMnger.setSoTimeout(timeoutInMilliseconds);
m_PostMthd.setRequestHeader("SOAPAction",SOAPAction);
m_PostMthd.setRequestHeader("Content-Type","text/xml; charset=UTF-8");
m_PostMthd.setRequestEntity(new StringRequestEntity(inputMsg));
int l_status = m_HttpClient.executeMethod(m_PostMthd);
System.out.println("EXECUTION STATUS : " + l_status+"\n");
InputStream is = m_PostMthd.getResponseBodyAsStream();
BufferedReader rd = new BufferedReader(new InputStreamReader(is));
String line;
StringBuilder response = new StringBuilder();
while ((line = rd.readLine()) != null)
{
response.append(line);
response.append('\r');
}
rd.close();
return response.toString();
我认为这里有两个不同的问题:如何在 Java 中使用 PFX 文件,以及我应该如何处理它。第一个相当简单,第二个可能需要一些额外的信息,但我会尽我所能回答。
在 Java
中处理 PFXPFX 是一种容器文件格式,可以包含一堆与 SSL/TLS 和密码学相关的不同类型的数据。 Java 有自己的容器格式,称为 JKS KeyStore。从广义上讲,这些是保存同类数据的等效方法,您只需要从一个导出到另一个。事先做这件事比在 运行 时尝试做要容易。引用 this answer:
keytool -importkeystore \
-srckeystore mypfxfile.pfx -srcstoretype pkcs12 \
-destkeystore clientcert.jks -deststoretype JKS
Keytool 包含在 JDK 中。一路上它会要求输入一些密码。您可以使用 keytool -list -keystore file.jks
命令来显示
JKS 文件。
我应该用这些东西做什么?
这个要看情况,这里你的问题有点含糊。在所有情况下,目的都是 身份验证 :客户端需要验证它正在与正确的服务器对话,并且可选地,服务器需要验证它正在与正确的客户端对话。这涉及三位信息和大量数学。
- 私钥和public密钥(连同一些数学,通常是RSA算法)用于创建一个锁和钥匙系统。您将私钥留给自己,并与需要它的任何人共享 public 密钥。这些在身份验证中的使用方式是使用私钥以数学方式提出可以使用 public 密钥验证的声明。数学是这样的,几乎不可能伪造这种说法。因此,如果经过数学检验,您可以确定与您交谈的人持有私钥。简而言之,这是数字签名。
- 一个证书嵌入了一个public密钥并向其中添加了一堆信息(密钥基本上只是一个巨大的素数,所以它在它自己的)。添加的信息包括密钥持有者的身份,以及保证证书有效性的颁发者的身份,所有这些都用数字签名密封。
根据应用程序的不同,您收到的 PFX 文件可能仅包含证书,也可能包含证书和相应的私钥(或两者)。
keytool -list
的输出将显示任意数量的 trustedCertEntry
记录,这些是没有可用私钥的证书,它可能包含一个 privateKeyEntry
,这是一个同时存在证书及其私钥的记录。记下任何私钥条目的 alias
。
客户端验证服务器
创建 HTTPS 连接时,服务器会向客户端出示证书,并证明服务器持有与证书中嵌入的 public 密钥相对应的私钥。客户端将不得不决定它是信任服务器的身份,还是中止连接。它通过数学检查服务器提供的证书与称为信任库的预共享受信任证书列表(cacerts
是一个常见的文件系统名称)来实现。
您的 OS'es 和网络浏览器都附带一个默认的信任库;此机制位于浏览器中的挂锁图标后面。
在您的情况下,您要连接的端点可能使用默认信任库中不存在的证书,因此您必须提供自己的[信任库]。
假设 Java 在 AS/400 上的工作方式与 Java 在 Windows 和 Linux 上的工作方式相同,您可以(引用 this answer)传递一个名为 javax.net.ssl.trustStore
的 Java 系统 属性,其中包含 JKS 密钥库的文件系统路径,其中包含可信签署人的证书。
另一种方法是将 JKS 文件命名为 jssecacerts
并将其放在您的 jre/lib/security
目录中,但请记住,它现在会影响 all java 处理 运行 使用该 JVM 安装而不仅仅是您正在执行此工作的那个。
服务器验证客户端
在网络上用的不多,但是HTTPS有做双向证书验证的选项。这意味着在客户端以上述方式对服务器进行身份验证后,服务器现在对客户端进行身份验证。这是完全相同的过程,但方向相反。
在专有SOAP服务中比较常见,所以这里可能就是这种情况。你的问题对我来说并不是很清楚。
这意味着您的应用程序必须向服务器提供证书,并且它必须拥有与证书中嵌入的 public 密钥相对应的私钥。遗憾的是,我自己在 Java 中从来没有这样做过,所以我不知道您必须传递的确切命令。您需要寻找一种方法来告诉您的连接这些事情:
- 要使用什么 JKS 密钥库文件(+它的密码)
- 使用那个 JKS 的哪个密钥别名(+它的密码)