EDI AS2 HTTP trace? - testing

We're looking into an AS2 implementation and would like to be able to build meaningful test-cases to be used with SoapUI or Postman.
In order to do this we have two ways:
just try to tcp-dump/trace calls from an existing client
manually build some simple calls starting from the plain EDI documents
or various reasons we've discarded (1) so we must go with (2) and we need some documentation.
This doc from Oracle is a good starting point: https://docs.oracle.com/cd/E19398-01/820-1228/agfat/index.html
but we cannot really find a step-by-step guide for building the AS2 request starting from the ORDERS edi document (which we already have).
Ideally I'd like a step-by-step guide which says something like:
generate a private cert: +commandline
encrypt the EDI document: +commandline +sampleoutput
create signature: +commandline +sampleoutput
build the S/MIME package: +commandline +sampleoutput
send over HTTP/S: +commandline +samplehttptrace

Sending Message
To send a message we need a file with message to send, two pairs of keys for both sides (each partner has one pair of keys for signing and another pair of keys for encrypting, each pair of keys consists of public and private keys). For this tutorial we will use the same pair of keys for signing and encryption per partner.
Generate Keys
Using OpenSSL create two pairs of keys:
openssl req -x509 -newkey rsa:2048 -keyout P1_private.pem -out P1_public.pem -days 365
The same for second pair:
openssl req -x509 -newkey rsa:2048 -keyout P2_private.pem -out P2_public.pem -days 365
Extend Private Key Files
P1_private.pem and P2_private.pem contain only private keys. OpenSSL supports extended PEM format where both, private and public keys, can be in one file. This simplifies some OpenSSL commands (one file can be given instead of two). This tutorial assumes that this has been done:
cat P1_public.pem >> P1_private.pem
cat P2_public.pem >> P2_private.pem
Otherwise, check OpenSSL commands manual to see how to specify second file where needed.
Sign File
Let's assume we want to send GETMSG.edi file via AS2 protocol from P1 partner => to P2, with signing and encryption. First we add appropriate MIME headers to it:
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'
Save new file as GETMSG.msg
Then sign the file with private key of sending partner P1:
openssl smime -sign -in GETMSG.msg -out GETMSG_SIGNED.msg -signer P1_private.pem
Note: OpenSSL puts old MIME types that start with 'x-pkcs7-', some applications (pyAS2) can handle only new MIME types without eks 'pkcs7-'. Just remove 'x-' everywhere from resulting file.
Encrypt
Now we have multipart attachment with first part being the file content and the second part is the signature. Now we encrypt it with public key of receiving partner P2:
openssl smime -encrypt -in GETMSG_SIGNED.msg -out GETMSG_ENC.msg -des3 P2_public.pem
Resulting file GETMSG_ENC.msg can be send now to recipient as request with additional AS2 headers.
Note: OpenSSL puts old MIME types that start with 'x-pkcs7-', some applications (pyAS2) can handle only new MIME types without eks 'pkcs7-'. Just remove 'x-' everywhere from resulting file.
Send via cURL
To send with cURL we have to separate headers and body of POST request. Remove from file GETMSG_ENC.msg all headers (it shoud start with 'MI..').
Use this command to send it from P1 (AS2 ID: p1as2) to P2 (AS2 ID: p2as2), assuming that P2 URL is "http://localhost:8080/pyas2/as2receive":
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
Note: this command would also request MDN with signature (because of presence of Disposition-Notification-To and value of DISPOSITION-NOTIFICATION-OPTIONS).
Receiving Message
The following will already happen on receiving side. That would include decrypting message, verifying signature, extracting payload and preparing acknowledgment or message disposition notification (MDN). It would also require to calculate hash of received message (MIC) to be send in acknowledgment.
Decrypt Request
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
Verify Signature
openssl smime -verify -in request.txt -nosigs -noverify -signer P2_public.pem -out original.txt
Calculate Received-content-MIC
Digest of received content has to be calculated over original file WITH MIME headers, in our case that is content of GETMSG.msg.
openssl dgst -sha1 -binary GETMSG.msg | openssl enc -e -base64
Note: in real life receiver has to extract that from decrypted content of type multipart/signed. First part is the received content.
Message Disposition Notification
Not signed message disposition notification or acknowledgement would look like multipart report:
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==--
Signed Message Disposition Notification
If signed MDN is requested (depends on 'Disposition-Notification-Options' HTTP header) then multipart report shown above is wrapped in multipart/signed. And seconds part is signature of the first part shown above. If we assume that mdn.txt contains not signed MDN as shown above, then to sign it:
openssl cms -sign -signer P2_private.pem -in mdn.txt -out mdn_signed.txt
Now we need only to add some AS2 specific headers to the top of mdn.txt or mdn_signed.txt, depending on what kind of MDN was requested, before transmitting it over HTTP (taken from actual response of 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
Based on sources: pyAS2 documentation, OpenSSL documentation, NCPDP SCRIPT message example.

I have recently been attempting to test a new AS2 implementation using the approach described by Andrew Haritonkin in his answer to this question.
I found a few quirks that are worth mentioning in their own right.
openssl smime -encrypt by default emits - logically enough - S/MIME formatted content. This is not accepted by my AS2 decoder - for reference, this is the Azure Logic Apps AS2 decode action. I found that the correct format is specified by adding the -outform DER option to the encrypt step, which causes openssl to emit the encrypted message in DER format
I was starting with a .pfx certificate generated by Azure Key Vault. I couldn't find a way to get openssl to accept this for signing, so I had to convert it to PEM first. The command line openssl pkcs12 -in mycert.pfx -out mycert.pem -passin pass: -nodes seemed to do the trick. -passin pass: specifies the private key password for the input certificate as being the empty string, which it is by default when generated by Azure. Not doing this causes openssl to prompt for the password, which failed the whole process in the context I was using it (a Docker container). -nodes means "no DES" not "nodes" and indicates that the private key should not be encrypted or protected by a passphrase in the output certificate. Needless to say this sounds like quite a high-risk piece of data to be handing around because it has no protection whatsoever against compromise of the private key.

Related

Signing a Document with ECDSA

I am able to sign and verify an ECDSA signature with the commands:
openssl dgst -sha256 -sign privateKey.pem data.txt > sign_data,txt
openssl dgst -sha256 -verify publicKey.pem -signature sign_data.txt data.txt
The output for the verification command is:
Verified OK
However, when I am sending my signed request to the server, I am getting an error saying that my signature was invalid. In my application, I am calling the above sign commands and then I am reading the signature (using python) as:
signature = open('sign_data.txt','rb').read()
Given these circumstances, can I be sure that there is no problem with the signature value and that another processing error occurred. In other words, could it be possible that the receiver can still reject a signature even if the above openssl passed the tests?

Difference between pem, crt, key files

I'm having problems understanding the difference between files produced by openssl and how to detect them.
For example I'm trying to generate Self-signed cert with private key and generate JKS file from p12
format. I'm googling like a madman but I still don't know how to generate it correctly to be able to use following commands.
openssl pkcs12 -export -in user.pem -inkey user.key -certfile user.pem -out testkeystore.p12
keytool -importkeystore -srckeystore testkeystore.p12 -srcstoretype pkcs12 -destkeystore wso2carbon.jks -deststoretype JKS
Source: https://www.ibm.com/support/pages/how-generate-jks-keystore-existing-private-key
I found a couple of different commands to generate Self-signed cert and private key but I don't know how to map resulting files to the commands above and whats worse I don't understand what those commands do.
I mean I see what files they generate and understand that certificate and private key used to sign it ( or maybe the other way around :| ) but what is the difference between those commands and is cert.pem === certificate.crt - Those file extensions are driving me crazy.
openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -keyout privateKey.key -out certificate.crt
openssl req -newkey rsa:2048 -new -nodes -x509 -days 3650 -keyout key.pem -out cert.pem
This is yet another situation where I'm having similar issues with the openssl command. At this point I'm even ready to read some RFC ( I hope it won't come to this :) )
Thanks in advance for help
Those file names represent different parts of the key generation and verification process. Please note that the names are just convention, you could just as easily call the files pepperoni.pizza and the content will be the same, so do be conscious of how you use the filenames.
A brief primer on PKI - Keys come in two halves, a public key and a private key. The public key can be distributed publicly and widely, and you can use it to verify, but not replicate, information generated using the private key. The private key must be kept secret.
.key files are generally the private key, used by the server to encrypt and package data for verification by clients.
.pem files are generally the public key, used by the client to verify and decrypt data sent by servers. PEM files could also be encoded private keys, so check the content if you're not sure.
.p12 files have both halves of the key embedded, so that administrators can easily manage halves of keys.
.cert or .crt files are the signed certificates -- basically the "magic" that allows certain sites to be marked as trustworthy by a third party.
.csr is a certificate signing request, a challenge used by a trusted third party to verify the ownership of a keypair without having direct access to the private key (this is what allows end users, who have no direct knowledge of your website, confident that the certificate is valid). In the self-signed scenario you will use the certificate signing request with your own private key to verify your private key (thus self-signed). Depending on your specific application, this might not be needed. (needed for web servers or RPC servers, but not much else).
A JKS keystore is a native file format for Java to store and manage some or all of the components above, and keep a database of related capabilities that are allowed or rejected for each key.
The commands you list look fine to me, and I don't see a question beyond asking what the different files are for. If you need more information, please enrich your question.
.key is the private key. This is accessible the key owner and no one else.
.csr is the certificate request. This is a request for a certificate authority to sign the key. (The key itself is not included.)
.crt is the certificate produced by the certificate authority that verifies the authenticity of the key. (The key itself is not included.) This is given to other parties, e.g. HTTPS client.
.pem is a text-based container using base-64 encoding. It could be any of the above files.
-----BEGIN EXAMPLE-----
...
-----END EXAMPLE-----
.p12 is a PKCS12 file, which is a container format usually used to combine the private key and certificate.
There isn't only one extension. For example you may see certificates with either the .crt or a .pem extension.
Just to add more info: .der, another (binary) encoding (either public or private key, or csr)

Difference beween .arm and .csr file (SSL)

I am generating two CSRs ( Certificate signing request )
1 . using java keytool i get a .csr format file.
using IBM key management tool i get .arm file.
Though both the files contains the same kind of data ( ie . base64 encoded public key details)
My question "can i rename .csr file to .arm" will it be the same ...
Thanks.
The most common syntax for a CSR is PKCS#10, which can be represented in binary or text formats. A CSR contains a number of pieces of information including: a public key, the subject distinguished name, a signature, and optional attributes. If you can view the files in a text editor and they look similar to this:
-----BEGIN CERTIFICATE REQUEST-----
MIIBnTCCAQYCAQAwXTELMAkGA1UEBhMCU0cxETAPBgNVBAoTCE0yQ3J5cHRvMRIw
EAYDVQQDEwlsb2NhbGhvc3QxJzAlBgkqhkiG9w0BCQEWGGFkbWluQHNlcnZlci5l
eGFtcGxlLmRvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAr1nYY1Qrll1r
uB/FqlCRrr5nvupdIN+3wF7q915tvEQoc74bnu6b8IbbGRMhzdzmvQ4SzFfVEAuM
MuTHeybPq5th7YDrTNizKKxOBnqE2KYuX9X22A1Kh49soJJFg6kPb9MUgiZBiMlv
tb7K3CHfgw5WagWnLl8Lb+ccvKZZl+8CAwEAAaAAMA0GCSqGSIb3DQEBBAUAA4GB
AHpoRp5YS55CZpy+wdigQEwjL/wSluvo+WjtpvP0YoBMJu4VMKeZi405R7o8oEwi
PdlrrliKNknFmHKIaCKTLRcU59ScA6ADEIWUzqmUzP5Cs6jrSRo3NKfg1bd09D1K
9rsQkRc9Urv9mRBIsredGnYECNeRaK5R1yzpOowninXC
-----END CERTIFICATE REQUEST-----
then they are text (aka PEM) encoded CSRs. These text encoded CSRs can be decoded and viewed using the following openssl command:
openssl req -in your-csr-filename -noout -text
Renaming the file will not affect openssl's ability to decode them. However, some applications that process CSRs may expect a particular filename extension.
You can inspect your certificate signing request (csr) using OpenSSL with a command such as:
openssl x509 -req -in yourfile.csr -text -noout
I'm assuming that IBM's thingy is a wrapper around openssl so I would expect your .arm to be an x509 certificate going by a different name. Be interested to hear what you get back ...
The answer is yes. The .arm file is the same format as .csr. As you stated, they both contain the same type of data and therefore can simply be renamed. Furthermore, the common types of CSR requests are PKCS#10 and PKCS#12.
#snow60y: You won't see anything with 'openssl x509 -req -in yourfile.csr -text -noout' because there is no private key contained within the CSR and it is not signed, so it is not an x509 yet. A CSR should NEVER contain a private key and therefore, analyzing with that command should fail. You can use that command with a SIGNED cert, but not the request. For the request, use:
openssl req -in your-csr-filename -noout -text

How to use result of CryptSignMessage with OpenSSL to verify digital sign

I'm trying to verify detached PKCS#7 signature. A file generated using WIN32 CryptoAPI function CryptSignMessage(). File is signed on client side, but it must be validate on server side FreeBSD. So I cannot use CryptoAPI.
Please help me to determinate how to use OpenSSL for this kind of task. Now I have two files FILENAME.xml and FILENAME.xml.sig which contains a signature information. According to specification this file include "a hash of the specified content, signs the hash, and then encodes both the original message content and the signed hash." As I figured out it also contains certificates. With openssl i can retrieve public key and certificate from this file but I have no idea how to retrieve signature information?
So I'm trying to retrieve information from this file such as public key and signature to use it with openssl command
openssl dgst -verify PUBLIC_KEY_FILE -signature SIGNATURE_FILE -md_gost94 FILENAME.xml
Verification Failure
Also there is service which can read all information from this file. http://notary.cryptopro.ru/Detached.aspx
Information about EDS:
Algortim hashing:
Name:
GOST R 34.11-94
ID:
1.2.643.2.2.9
Algortim public key:
Name:
GOST R 34.10-2001
ID:
1.2.643.2.2.19
Value:
2DEA 8713 5AS2 69AA 34E0 B333 EF61 3773 5CF1
3BC4 BAD0 1745 0DDD 9577 FFAE BA4A A9EB A8CF
64B9 C338 1513 8BDB C478 BA3A 5409 6419 03A6
DD3A 04D2 D132 3319 8031
Serial Number: 1F11 EF05 0001 0000 1032
Maybe I dont understand something. Please help.
Is it posible at all?
If you used CryptSignMessage() function, you have the certificate for this public key. So, you can use openssl cms service (in some distros openssl is built without it, in this case you can recompile them with enable-cms option).
The sample command is:
openssl cms -verify -nointern -noverify -certfile CERTIFICATE_FILE -inform DER -in SIGNATURE_FILE -content CONTENT_FILE -out /dev/null
where CERTIFICATE_FILE is a certificate in Base64 form.
P.S. I'm not sure about GOST algorithms support. Try sha1RSA first.

OpenSSL treats smime message with Content-type 'Application/EDI' as text and changes line breaks

I receive smime message with content-type 'Application/EDI'. It is non-standard mime type and content should be interpreted as binary. But OpenSSL during verifying signature treats it as text and changes line breaks from '\n' to '\r\n' (as needed by spec for content-type 'text'). So digest becomes wrong and verification fails.
Is there any way to make openssl not chaging anything in original message? Argument '-binary' doesn't work on any version (I tried 0.9.7, 0.9.8, 1.0.0).
Ok, answering my own question.
I've split input data into two separate files with content and signature removing unnecessary metadata. After that I changed mime type of signature to application/pkcs7-mime and verification became successful with this command:
openssl.exe smime -verify -inform SMIME -CAfile caCert.pem -certfile cert.pem -in signature.txt -content content.txt
Variant with changing -inform to PEM also works, but signature must be without Content-xxx headers