EDI AS2 HTTP跟踪?

时间:2017-02-22 11:35:59

标签: testing edi

我们正在研究AS2实现,并希望能够构建与SoapUI或Postman一起使用的有意义的测试用例。 为此,我们有两种方式:

  1. 只是尝试从现有客户端进行tcp-dump / trace调用
  2. 从普通的EDI文档开始手动构建一些简单的调用
  3. 或我们放弃的各种原因(1)因此我们必须使用(2)并且我们需要一些文档。 来自Oracle的这个文档是一个很好的起点:https://docs.oracle.com/cd/E19398-01/820-1228/agfat/index.html

    但我们无法真正找到从ORDERS edi文档(我们已​​经拥有)开始构建AS2请求的分步指南。

    理想情况下,我想要一个分步指南,其中包含:

    1. 生成私有证书:+ commandline
    2. 加密EDI文档:+ commandline + sampleoutput
    3. 创建签名:+ commandline + sampleoutput
    4. 构建S / MIME包:+ commandline + sampleoutput
    5. 通过HTTP / S发送:+ commandline + samplehttptrace

2 个答案:

答案 0 :(得分:4)

发送消息

要发送消息,我们需要一个包含要发送消息的文件,两边都有两对密钥(每个合作伙伴都有一对密钥用于签名,另一对密钥用于加密,每对密钥由公共和私有组成键)。对于本教程,我们将使用相同的密钥对进行每个合作伙伴的签名和加密。

生成密钥

使用OpenSSL创建两对密钥:

openssl req -x509 -newkey rsa:2048 -keyout P1_private.pem -out P1_public.pem -days 365

第二对相同:

openssl req -x509 -newkey rsa:2048 -keyout P2_private.pem -out P2_public.pem -days 365

扩展私钥文件

P1_private.pem和P2_private.pem仅包含私钥。 OpenSSL支持扩展PEM格式,其中私钥和公钥都可以在一个文件中。这简化了一些OpenSSL命令(可以给出一个文件而不是两个)。本教程假定已完成此操作:

cat P1_public.pem >> P1_private.pem

cat P2_public.pem >> P2_private.pem

否则,请查看OpenSSL命令手册,了解如何在需要的地方指定第二个文件。

签名文件

假设我们想通过来自P1 partner =>的AS2协议发送GETMSG.edi文件。通过签名和加密到P2。首先,我们为其添加适当的MIME标头:

Content-Type: application/edi-consent
Content-Disposition: attachment; filename="GETMSG.edi"

UNA:+./*'
UIB+UNOA:0++2289+++77777777:C:PASSWORDA+111111:M+19971001:074620'
UIH+SCRIPT:010:006:GETMSG+111'
UIT+111+2'
UIZ++1'

将新文件另存为GETMSG.msg

然后使用发送伙伴P1的私钥对文件进行签名:

openssl smime -sign -in GETMSG.msg -out GETMSG_SIGNED.msg -signer P1_private.pem

注意:OpenSSL会放置以' x-pkcs7- '开头的旧MIME类型,某些应用程序(pyAS2)只能处理没有eks> pkcs7的新MIME类型 - &#39 ;.只需删除' x - '从结果文件中到处都是。

<强>加密

现在我们有了多部分附件,第一部分是文件内容,第二部分是签名。现在我们使用接收伙伴P2的公钥加密它:

openssl smime -encrypt -in GETMSG_SIGNED.msg -out GETMSG_ENC.msg -des3 P2_public.pem

结果文件GETMSG_ENC.msg现在可以通过其他AS2标头发送给收件人。

注意:OpenSSL会放置以&#39; x-pkcs7- &#39;开头的旧MIME类型,某些应用程序(pyAS2)只能处理没有eks&gt; pkcs7的新MIME类型 - &#39 ;.只需删除&#39; x - &#39;从结果文件中到处都是。

通过cURL发送

要使用cURL发送,我们必须将POST请求的标题和正文分开。从文件GETMSG_ENC.msg中删除所有标题(它应该以&#39; MI ..&#39;开头)。 使用此命令将其从P1(AS2 ID:p1as2)发送到P2(AS2 ID:p2as2),假设P2 URL为&#34; http://localhost:8080/pyas2/as2receive&#34;:

set NOW=%DATE:~10,4%%DATE:~4,2%%DATE:~7,2%%TIME:~0,2%%TIME:~3,2%%TIME:~6,2%

curl -i -X POST-H "Content-Disposition: attachment; filename=\"smime.p7m\""-H "Content-Type: application/pkcs7-mime; smime-type=enveloped-data; name=\"smime.p7m\""-H "Content-Transfer-Encoding: base64"-H "AS2-TO: p1as2"-H "AS2-FROM: p2as2"-H "AS2-VERSION: 1.2"-H "MESSAGE-ID: <openssl%NOW%@LOCALHOST>"-H "Disposition-Notification-To: response@localhost"-H "DISPOSITION-NOTIFICATION-OPTIONS: signed-receipt-protocol=required, pkcs7-signature; signed-receipt-micalg=optional, sha1"--data-binary @GETMSG_ENC.msg http://localhost:8080/pyas2/as2receive

注意:此命令还会请求带有签名的MDN(因为存在Disposition-Notification-To和DISPOSITION-NOTIFICATION-OPTIONS的值)。

接收消息

接收方已经发生以下情况。这将包括解密消息,验证签名,提取有效负载以及准备确认或消息处理通知(MDN)。它还需要计算要在确认中发送的接收消息(MIC)的散列。

解密请求

使用OpenSSL命令解码请求内容保存为smime.p7m:

Using OpenSSL command decode request content saved as smime.p7m:

openssl smime -decrypt -in smime.p7m -recip P2_public.pem -inkey P2_private.pem -out request.txt

验证签名

openssl smime -verify -in request.txt -nosigs -noverify -signer P2_public.pem -out original.txt

计算Received-content-MIC

接收内容的摘要必须在原始文件WITH MIME标头上计算,在我们的例子中是GETMSG.msg的内容。

openssl dgst -sha1 -binary GETMSG.msg | openssl enc -e -base64

注意:在现实生活中,接收器必须从multipart / signed类型的解密内容中提取。第一部分是收到的内容。

邮件处理通知

未签名的邮件处理通知或确认看起来像是多部分报告:

Content-Type: multipart/report; report-type="disposition-notification"; boundary="===============1785295974=="

--===============1785295974==
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit

The AS2 message has been processed. Thank you for exchanging AS2 messages with Pyas2.

--===============1785295974==
Content-Type: message/disposition-notification; charset="us-ascii"
Content-Transfer-Encoding: 7bit

Reporting-UA: Bots Opensource EDI Translator
Original-Recipient: rfc822; p1as2
Final-Recipient: rfc822; p1as2
Original-Message-ID: <openssl20170706165018@LOCALHOST>
Disposition: automatic-action/MDN-sent-automatically; processed
Received-content-MIC: 1GZ1SDk5vvGz5YFGYP6lfhk4MXE=, sha1

--===============1785295974==--

签名消息处理通知

如果请求签名的MDN(取决于“处置 - 通知 - 选项&#39; HTTP标头”),则上面显示的多部分报告将包含在multipart / signed中。秒部分是上面第一部分的签名。如果我们假设mdn.txt不包含如上所示的签名MDN,那么签名:

openssl cms -sign -signer P2_private.pem -in mdn.txt -out mdn_signed.txt

现在我们只需要在mdn.txt或mdn_signed.txt的顶部添加一些特定于AS2的标头,具体取决于请求的MDN类型,然后通过HTTP传输(取自pyAS2的实际响应):

ediint-features: CEM
as2-from: p1as2
user-agent: PYAS2, A pythonic AS2 server
AS2-Version: 1.2
as2-to: p2as2
date: Thu, 06 Jul 2017 16:50:18 +0200
X-Frame-Options: SAMEORIGIN
Message-ID: <149935261885.25752.7388914440262498594@HOSTNAME>
Transfer-Encoding: chunked
Server: pyas2-webserver

基于来源: pyAS2文档,OpenSSL文档,NCPDP SCRIPT消息示例。

答案 1 :(得分:1)

我最近一直在尝试使用Andrew Haritonkin在他对这个问题的回答中描述的方法来测试新的AS2实现。

我发现了一些值得一提的怪癖。

    默认情况下,
  • openssl smime -encrypt发出-从逻辑上讲-S / MIME格式的内容。我的AS2解码器不接受此操作-仅供参考,这是Azure Logic Apps AS2解码操作。我发现通过在加密步骤中添加-outform DER选项来指定正确的格式,这会使openssl发出DER format
  • 中的加密消息。
  • 我从Azure Key Vault生成的.pfx证书开始。我找不到让openssl接受此签名的方法,因此我必须先将其转换为PEM。命令行openssl pkcs12 -in mycert.pfx -out mycert.pem -passin pass: -nodes似乎可以解决问题。 -passin pass:将输入证书的私钥密码指定为空字符串,默认由Azure生成时为空。不这样做会导致openssl提示输入密码,这在我使用它的上下文中(Docker容器)使整个过程失败。 -nodes的意思是“ no DES”而不是“ nodes”,并表示私钥不应通过输出证书中的密码来加密或保护。毋庸置疑,这听起来像是要传递相当高风险的数据,因为它没有任何保护措施以防私钥受到损害。