Code Monkey home page Code Monkey logo

phpas2's Introduction

PHPAS2 is a php-based implementation of the EDIINT AS2 standard

Latest Version on Packagist Build Status Total Downloads License

The PHPAS2 application enables you to transmit and receive AS2 messages with EDI-X12, EDIFACT, XML, or binary payloads between trading partners.

Requirements

  • php >= 7.1
  • ext-openssl
  • ext-zlib

Installation

composer require tiamo/phpas2

Usage

Basic example

cd example

composer install

chmod +x ./bin/console

# start a server to receive messages in 8000 port
php -S 127.0.0.1:8000 ./public/index.php

# send a test message
php bin/console send-message --from mycompanyAS2 --to phpas2

# send a file
php bin/console send-message --from mycompanyAS2 --to phpas2 --file /path/to/the/file 

Changelog

Please have a look in CHANGELOG

License

Licensed under the MIT license.

phpas2's People

Contributors

homer8173 avatar k0mar12 avatar mattdinthehouse avatar robsonala avatar tiamo avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

phpas2's Issues

isReport() in processMdn returning false on text/html

Afternoon!

To begin, I apologise if this isn't a bug! I've incorporated the awesome phpas2 library into a CodeIginiter setup. I've encountered an issue where, I think it may be a bug - although I'm not entirely sure it's a fault of the framework or my build up of a request/response.

I'm able to send payloads to a receiver server successfully, read & process them. It's when the synchronous MDN response is generated - the sender fails to accept that the response is an MDN.

// Raise error if message is not an MDN
if (!$payload->isReport()) {
    throw new \RuntimeException('MDN report not found in the response [' . $payload . ']');
}

This, returns false as per the log:

2021-06-23 13:15:46 - debug - Build the AS2 message to send to the partner - []
2021-06-23 13:15:46 - debug - Signing the message using partner key - []
2021-06-23 13:15:46 - debug - Calculate MIC - {"mic":"pmqfSeaJlqgMtiLo\/XlOtDUvlktpAe7nqMR7A\/F9qjE=, sha256"}
2021-06-23 13:15:46 - debug - Encrypting the message using partner public key - []
2021-06-23 13:15:46 - debug - AS2 message has been built successfully - []
2021-06-23 13:15:46 - info - Sender: Built Message, now sending. - []
2021-06-23 13:15:46 - debug - AS2 message successfully sent to partner - []
2021-06-23 13:15:46 - debug - Synchronous MDN received from partner - []
2021-06-23 13:15:46 - critical - MDN report not found in the response [
Date: Wed, 23 Jun 2021 13:15:22 GMT
Server: Apache/2.4.29 (Ubuntu)
Set-Cookie: ci_session=dq7rmnactn6dg4gs48q40pkggsuqhhb1; expires=Wed, 23-Jun-2021 17:55:22 GMT; Max-Age=16800; path=/; HttpOnly
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate
Pragma: no-cache
Vary: Accept-Encoding
Content-Length: 3312
Content-Type: text/html; charset=UTF-8

------569A442EF7514191F2563C50F0DB4B7B
Content-Type: multipart/report; report-type=disposition-notification; boundary="----=_361855cff16330619ada7062af3b983a10a9eaae"

------=_361855cff16330619ada7062af3b983a10a9eaae
Content-Type: text/plain
Content-Transfer-Encoding: 7bit

Your message was successfully received and processed.

------=_361855cff16330619ada7062af3b983a10a9eaae
Content-Type: message/disposition-notification
Content-Transfer-Encoding: 7bit

Reporting-UA: PHPAS2
Original-Recipient: rfc822; PRIMARYSERVER
Final-Recipient: rfc822; PRIMARYSERVER
Original-Message-ID: <[email protected]>
Disposition: automatic-action/MDN-sent-automatically; processed
Received-Content-MIC: pmqfSeaJlqgMtiLo/XlOtDUvlktpAe7nqMR7A/F9qjE=, sha256

------=_361855cff16330619ada7062af3b983a10a9eaae--

------569A442EF7514191F2563C50F0DB4B7B
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename="smime.p7s"
Content-Type: application/pkcs7-signature; name=smime.p7s; smime-type=signed-data

MIIGWQYJKoZIhvcNAQcCoIIGSjCCBkYCAQExDzANBglghkgBZQMEAgEFADALBgkq
hkiG9w0BBwGgggN+MIIDejCCAmICCQCX1XKw7jN4BjANBgkqhkiG9w0BAQsFADB...

The above MDN response is returning false on MimePart.php at line 157:

/**
 * @return bool
 */
public function isReport()
{
      $isReport = $this->getParsedHeader('content-type', 0, 0) === self::MULTIPART_REPORT;

      if ($isReport) {
          return true;
      }

      if ($this->isSigned()) {
            foreach ($this->getParts() as $part) {
                  if ($part->isReport()) {
                        return true;
                  }
            }
      }

      return false;
}

Where $this->getParsedHeader('content-type', 0, 0) is returning text/html. Which I can see is the outer envelope of the message payload.

I can see later in the processMdn() method, it loops through the parts and checks for the message/disposition-notification - which it does find when I make isReport() to default true.

However, I'm unsure if other AS2 Servers & Clients would also test the first outer Content-type thus would also fail.

How to edit the signature algorithm from sha256 to sha1

Hello,

how can i change the signature algorithm? The changes in the config/partners.php file were not successful. I also edit the mdn_options in this file. In the error log always show me the following error: app.CRITICAL: (MIC) Invalid hash algorithm. The partner send an test file with "sha1".

What am I doing wrong?

Thanks in advance

Receiving AS2 message from partner causes Entity `%s:%s` not found

It seem that the check when receiving an AS2 message from the partner always causes an error that the entity has not been found given in FileStorage.php on line 125

So instead of calling getMessage() from the StorageInterface (see Server.php on line 115) there should be a method foundMessage() to return either true or false and continue if the message has not been found.

pkcs7_sign|verify with 'binary' content-transfer-encoding

In CryptoHelper I've seen the comment:

/**
 * TODO: Implement pure methods without "openssl_pkcs7"
 * check openssl_pkcs7 doesn't work with binary data.
 */

From what I can tell, it has nothing to do with the data, but rather the inclusion of PKCS7_BINARY in the $flags arg for openssl_pcs7_sign. I've captured the output from opanssl_pkcs7_sign and tried to verify it. No joy. I can't even get it to verify using openssl on the command line. And my test used simple text, not binary data.

Without including PKCS7_BINARY I have no problem signing and verifying real binary data that has content-transfer-encoding set to 'base64' or 'quoted-printable'. I've even confirmed PKCS7_BINARY does what it's supposed to. Omitting signing/verifying, there's no issue with encrypting/decrypting binary data, even if content-transfer-encoding is set to 'binary' or '8bit'.

While I'm convinced this issue is no fault of the code in the library, the comment wouldn't be there if this issue had not already reared its ugly head. So... do you know of a viable workaround so that I can sign and verify actual binary data? I'm dealing with a business partner that is resistant to base64 content-transfer-encoding.

Severe file size limitation and (obsolete) folded headers

Thank you for your work on this library.

Are you open to a pull request to address a couple of issues I've found?

File Size Limitation

This library is being tested at work for receiving large file transfers from a business partner. Some of the files are nearly 50M. Everything works fine on small files. In my set of 24 test files, the largest successful transfer with the unmodified library was 174K. The next size up is 545K. It failed, as did all the other larger files.

I've identified the cause for the failure in 2 key methods: Utils::parseMessage (called by MimePart::fromString) and MimePart::setBody. In both cases, the culprit seems to be an inability of preg_match and preg_split to handle large subject arguments. They silently fail to return matches that succeed with the same patterns used with smaller strings.

I've rewritten both methods using strpos() to solve this limitation. It succeeds now with a 46M test file.

Obsolete Header Folding

AS2 messages from our business partner at work arrive with long header values folded to the next line with a leading horizontal tab. Even though they're POSTing via HTTP 1.1 and shouldn't be using obs-fold we still have to preserve them, because they are in the decrypted content and are included in MIC calculation.

I have an ugly kludge in place now in CryptoHelper, but I'm working on a more elegant solution in parseMessage.

Anyway, I appreciate the work you've done. It's been helpful. I'd like to contribute some of what I've found and solved if you're open to it.

--Glenn

send to mendelsontestAS2 problem

when i use the demo send message to  "mendelsontestAS2"
Q1:
the "MDN" return "The system is unable to find out the sign algorithm of the inbound AS2 message."

Q2:
and if i config "compress true" then the MDN return "exception reading compressed stream."

any one can help me?

Transport of UNA & UNB not working

Those lines affect the transport by those various errors :
Partner failed to process file. processed/error: Failed to decrypt S/Mime message. Error: "error:0D07803A:asn1 encoding routines:asn1_item_embed_d2i:nested asn1 error".
Partner failed to process file. processed/error: Failed to decrypt S/Mime message. Error: "error:0D0680A8:asn1 encoding routines:asn1_check_tlen:wrong tag".
Partner failed to process file. processed/error: Failed to decrypt S/Mime message. Error: "error:0D07803A:asn1 encoding routines:asn1_item_embed_d2i:nested asn1 error".

The end of the message is working fine only if i remove those lines :
UNA:+.? '
UNB+UNOC:3+SENDERID:14+RECEIVERID:14+200915:1019+37856120'

I'm having a configuration with :
'content_type' => 'text/plain',
'compression' => false,
'signature_algorithm' => false,
'encryption_algorithm' => '3des',
'content_transfer_encoding' => 'base64',
'mdn_mode' => PartnerInterface::MDN_MODE_SYNC,
'mdn_options' => 'signed-receipt-protocol=optional, pkcs7-signature; signed-receipt-micalg=optional, sha256',

Conflicting with guzzlehttp/guzzle ^7

Would be great, if the dependency on guzzle could be uped to or include guzzlehttp/guzzle ^7.0 as there might be locked packages requiring new versions of that lib.

CryptoHelper writing to >dev>null causes problems on Windows server

@tiamo Hey there and my apologies for bothering you again.
Telling from your examples, it seems your library is based upon Sebastien Malot's AS2Secure. I'm trying to rewrite our AS2 service which uses AS2Secure.
The CryptoHelper components delegates the result of pkcs7 verification to >dev>null which works on Unix but not on a Windows machine. On Windows it needs to be >nul. AS2Secure had the same problem; I did change this in that library directly because otherwise, we couldn't get a message through.
Though PHP gives only a warning level error, it might be the reason, why the message cannot be further processed, it stops dead stating "Signature Verification Failed". The response MDN seems to be empty; client says there is no MDN report.
Maybe there's a chance of having a configure option for this, if not auto-detecting environment.

headers of body are sent instead of headers of message

I needed to change Management.php line 221 with the lines from former version to make it work:
'headers' => MimePart::fromString($message->getHeaders())->getHeaders(),
'body' => $message->getPayload(),

in latest version it is passing the headers of the payload.
I am wondering why you changed this?

app.CRITICAL: Signature Verification Failed

Hello,

I get

[2022-01-28 15:24:14] app.CRITICAL: Signature Verification Failed [] []

My installation works with previous partner.

I received the certificate file in binary .cer format and then converted it using openssl to .crt so i can use it with my code ( because my previous partner had that file format and it works).

Any idea how can i fix this ?

Thank you.

Problem with the encoding special german characters

Hi ,
I have problem when I send send message with special german characters like ä ü ö etc.
When I send the message containing these characters, the message is not encoded correctly. Where exactly I use the option mentioning utf-8 format. I tried many ways but still the other party is getting the message not correctly.
Kindest regards
Nab

Still "dev"/unstable?

Currently one requirement is:

"phpseclib/phpseclib": "dev-master"

This causes composer to raise a stink:

tiamo/phpas2 1.3.1 requires phpseclib/phpseclib dev-master -> satisfiable by phpseclib/phpseclib[dev-master] but these conflict with your requirements or minimum-stability.

Any chance that the stable version of "phpseclib/phpseclib" could used instead?

If not could you add to the install docs that the following should be added:

"minimum-stability": "dev",
"prefer-stable": true,

Thanks

CryptoHelper::verify method seems wrong

The CryptoHelper::verify() method (here) uses openssl_pkcs7_verify.
But the parameters do not match the documentation at all:

  • The first parameter is a MimePart or a content string when it should be a filename
  • The third parameter is an output file when it should be null
  • The fourth parameter is an array of strings (which actually only contains a single certificate as a string, which comes from PartnerInterface::getCertificate()) when according to this, it should contain an array of filenames.

Am I missing something here?

The Message Integrity Code (MIC) does not match the sent AS2 message

Overview

When sending a message with an attachment, the following error occurs:

The Message Integrity Code (MIC) does not match the sent AS2 message (required: **required_mic**, sha256, returned: **returned_mic**, sha256) {"message_id":"**message_id**"}

Meanwhile, sending a message without an attachment does not produce an error.

Steps to reproduce

This issue can be reproduced with the example, included in the library. To do that, run the following commands:

git clone https://github.com/tiamo/phpas2.git phpas2_issue_reproduction
cd phpas2_issue_reproduction/example
composer install
chmod +x ./bin/console
# run the server in the background with no output
php -S 127.0.0.1:8000 ./public/index.php >& /dev/null &
echo "This is the message" > example_message.txt
php bin/console send-message --from mycompanyAS2 --to phpas2 --file example_message.txt

The last command produces the following output:

[2022-11-19 17:34:33] app.DEBUG: Build the AS2 message to send to the partner
[2022-11-19 17:34:33] app.DEBUG: Signing the message using partner key
[2022-11-19 17:34:33] app.DEBUG: Calculate MIC {"mic":"**mic**, sha256"}
[2022-11-19 17:34:33] app.DEBUG: Compressing outbound message after signing...
[2022-11-19 17:34:33] app.DEBUG: Encrypting the message using partner public key
[2022-11-19 17:34:33] app.DEBUG: AS2 message has been built successfully
[2022-11-19 17:34:33] app.DEBUG: AS2 message successfully sent to partner
[2022-11-19 17:34:33] app.DEBUG: Synchronous MDN received from partner
[2022-11-19 17:34:33] app.DEBUG: Found MDN report for message ["**message_id**"]
[2022-11-19 17:34:33] app.DEBUG: Message has been successfully processed, verifying the MIC if present.
[2022-11-19 17:34:33] app.ERROR: The Message Integrity Code (MIC) does not match the sent AS2 message (required: **required_mic**, sha256, returned: **returned_mic**, sha256) {"message_id":"**message_id**"}

However, if one were to run bin/console send-message --from mycompanyAS2 --to phpas2 (sending a message without an attachment) instead of the last command, the message would be sent successfully:

[2022-11-19 17:42:47] app.DEBUG: Build the AS2 message to send to the partner
[2022-11-19 17:42:47] app.DEBUG: Signing the message using partner key
[2022-11-19 17:42:47] app.DEBUG: Calculate MIC {"mic":"**mic**, sha256"} []
[2022-11-19 17:42:47] app.DEBUG: Compressing outbound message after signing...
[2022-11-19 17:42:47] app.DEBUG: Encrypting the message using partner public key
[2022-11-19 17:42:47] app.DEBUG: AS2 message has been built successfully
[2022-11-19 17:42:47] app.DEBUG: AS2 message successfully sent to partner
[2022-11-19 17:42:47] app.DEBUG: Synchronous MDN received from partner
[2022-11-19 17:42:47] app.DEBUG: Found MDN report for message ["**message_id**"]
[2022-11-19 17:42:47] app.DEBUG: Message has been successfully processed, verifying the MIC if present.
[2022-11-19 17:42:47] app.DEBUG: File Transferred successfully to the partner

System information

OS: Ubuntu 20.04.5 LTS
PHP: PHP 8.1.12 (cli) (built: Oct 28 2022 17:39:37) (NTS)

MDN coming with LF instead of CR/LF

Hey,
we are receiving complaints, that returned MDNs are buggy, because most probably there are only LFs instead of CR/LFs as with previous versions. This seems to put original sender into trouble evaluating our response. There seems to be no option configuring this, right?

Best regards,
Claus.

Disposition-Notification-Options used in 2 different ways

I am deep into the code:
On the sending side, the Disposition-Notification-Options are included in the message headers, but on the receiving side, they are only parsed from the payload headers. Therefore, the "micAlgo" variable is never given a value, but the micContent variable is not empty, causing an exception in CryptoHelper::calculateMIC.
BTW, I have never posted in GitHub before, so my apologies if this is not the right forum for my comment.

partner constructor

Hello! I'm trying to use your library. It looks fine, but when a run the example init.php or the tests, I get an error when the partner it's being creating. It can't save the .json file for the partner and when the code is trying to get the partnet, It throws an exception reading the .json file because it doesn't exist.

The documentation says that I have to implement 3 classes before to use the examples, but I'm not sure about how do I have to do it.

Output ServerTests.php:

file_put_contents(\tests\resources\partner\sn24ebmp2rgmiwu.json): failed to open stream: No such file or directory
 \tests\Mock\FileStorage.php:98
 \tests\ServerTest.php:66

Output init.php

PHP Warning:  file_put_contents(\partner\mycompanyas2.json): failed to open stream: No such file or directory in \examples\models\FileStorage.php on line 98
PHP Stack trace:
PHP   1. {main}() \examples\init.php:0
PHP   2. models\FileStorage->savePartner() examples\init.php:34
PHP   3. file_put_contents() \examples\models\FileStorage.php:98

Thank you

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.