Code Monkey home page Code Monkey logo

applepay-php's Introduction

applepay-php

applepay-php is a PHP extension that verifies and decrypts Apple Pay payment tokens according to Apple's spec[1]. It relies on OpenSSL for all crypto operations. Currently, it serves as the backbone for Etsy's PHP-based Apple Pay token handling endpoint.

Build

$ # Clone repo
$ git clone https://github.com/etsy/applepay-php.git
$ cd applepay-php
$
$ # Install OpenSSL development files (>= 1.0.2 required)
$ sudo yum install openssl-devel
$ # -or- sudo apt-get install libssl-dev
$ # etc...
$
$ # Build extension
$ phpize && ./configure && make
$
$ # Optionally install
$ sudo make install
$ echo 'extension=applepay.so' | sudo tee /etc/php.d/applepay.ini
$ # -or- echo 'extension=applepay.so' | sudo tee -a /etc/php.ini
$ # etc...

Pre-reqs

Before running the demo, you'll need a 'Payment Processing Certificate' and a private key from Apple (referred to as merch.cer and priv.p12 below). You can generate these at Apple's Dev Center. You'll also need an example payment token generated on an end-user device and the timestamp at which it was generated. An RSA-encrypted token should look like this:

{
    "data": "<base64>",
    "header": {
        "applicationData": "<hex_optional>"
        "wrappedKey": "<base64>",
        "publicKeyHash": "<base64>",
        "transactionId": "<hex>"
    },
    "signature": "<base64>",
    "version": "RSA_v1"
}

An ECC-encrypted token should look like this:

{
    "data": "<base64>",
    "header": {
        "applicationData": "<hex_optional>"
        "ephemeralPublicKey": "<base64>",
        "publicKeyHash": "<base64>",
        "transactionId": "<hex>"
    },
    "signature": "<base64>",
    "version": "EC_v1"
}

For more info check out the Apple Pay Programming Guide[2].

Demo

$ # Copy in your payment processing cert and test token
$ cd examples
$ cp /secret/place/merch.cer .
$ cp /secret/place/token.json .
$
$ # Extract private key from cert
$ openssl pkcs12 -export -nocerts -inkey merch.key -out priv.p12 -password 'pass:'
$
$ # Get intermediate and root certs from Apple
$ wget -O int.cer 'https://www.apple.com/certificateauthority/AppleAAICAG3.cer'
$ wget -O root.cer 'https://www.apple.com/certificateauthority/AppleRootCA-G3.cer'
$
$ # Verify chain of trust
$ openssl x509 -inform DER -in merch.cer -pubkey > pub.pem
$ openssl x509 -inform DER -in root.cer > root.pem
$ openssl x509 -inform DER -in int.cer > int_merch.pem
$ openssl x509 -inform DER -in merch.cer >> int_merch.pem
$ openssl verify -verbose -CAfile root.pem int_merch.pem # should output OK
$
$ # Run demo
$ cd ..
$ php -denable_dl=on -dextension=`pwd`/modules/applepay.so examples/decrypt.php -p <privkey_pass> -c examples/token.json -t <time_of_transaction>

If everything goes well you should see decrypted payment data.

Future work

  • Split up library into libapplepay and a PHP wrapper
  • HHVM port

[1] https://developer.apple.com/library/prerelease/ios/documentation/PassKit/Reference/PaymentTokenJSON/PaymentTokenJSON.html

[2] https://developer.apple.com/library/ios/ApplePay_Guide/

applepay-php's People

Contributors

adsr avatar ovidiupruteanu avatar rjiegit 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  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  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  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

applepay-php's Issues

Private key error

Hello!
I am getting a private key error Nr. 18.
Would you be able to recommend the best way to export/format the key in order not to have this error?
Please advise
Thank you!

compilation failure

I am getting a compilation error.

 /home/mark/applepay-php/applepay.c  -fPIC -DPIC -o .libs/applepay.o
/home/mark/applepay-php/applepay.c: In function ‘_applepay_parse_cryptogram’:
/home/mark/applepay-php/applepay.c:412:34: error: ‘z_applicationData_stack’ undeclared (first use in this function)
             z_applicationData = &z_applicationData_stack;

If I comment out the code below compilation goes through fine.

        if (zend_hash_find_compat(ht_header, "applicationData", sizeof("applicationData")-1, &z_applicationData) == SUCCESS) {
            convert_to_string(z_applicationData);
        } else {
            z_applicationData = &z_applicationData_stack;
            ZVAL_EMPTY_STRING(z_applicationData);
        }

Chain of trust failing

I am using the apple_pay.cer that I downloaded from the Apple Developer Portal. This is the error I get when I execute openssl verify -verbose -CAfile root.pem int_merch.pem

Error Message:
int_merch.pem: /CN=Apple Application Integration CA - G3/OU=Apple Certification Authority/O=Apple Inc./C=US error 7 at 0 depth lookup:certificate signature failure 98898:error:0D0C50A1:asn1 encoding routines:ASN1_item_verify:unknown message digest algorithm:/BuildRoot/Library/Caches/com.apple.xbs/Sources/OpenSSL098/OpenSSL098-64.50.6/src/crypto/asn1/a_verify.c:164:

Clean up `examples/applepay.php`

  1. Rename script to something descriptive like decrypt_token.php
  2. Replace hard-coded paths in examples/applepay.php with switches
  3. Add option to pass cryptogram as JSON instead of hex string
  4. Output result in JSON

If the script is flexible enough it could serve as an integration test harness (#1)

Problem payment param token applicationData

Previously, everything worked well. But after we came to the payment params "applicationData", then there is an error APPLEPAY_ERROR_SIGNATURE_NOT_VERIFIED

version = "EC_v1"
data = ....
signature = ....
header =
ephemeralPublicKey = "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEDHl2BZXSTG2ar8D5czlR2EopTAPz06WtRrjdpnK0Vu00V3EkJj1PD+sUoNBR4eAyeGOCF/eJbATMdEtMERCuBg=="
applicationData = "16422424b4947f2fb374571fe69262c51cf19a33bcb27f059231ad620c71ef4b"
publicKeyHash = "7WWhqu7whJLy84c5cg/f2fl/Ad8dVbJhdRhOySqA/Co="
transactionId = "9c907ef747044ec52645bb33c4ebb95ae38a6aa22391e65c28ea7ffd37d5d751"

Getting APPLEPAY_ERROR_INT_CERT_MISSING_OID after re-generating new certificates

Hello,

I have re-generated both the Merchant Identity nd Payment Processing certificates my current ones are going to expire soon.

I am following the instructions on the README, but keep getting the APPLEPAY_ERROR_INT_CERT_MISSING_OID error. I believe this arises from validating the intermediate certificate from Apple is the right one?

When viewing the payment processing certificate in Keychain Access, I can see that it was issued by Apple Worldwide Developer Relations CA - G2 - not the G3 one referenced in the README (https://www.apple.com/certificateauthority/AppleAAICAG3.cer) though I don't know if this is relevant.

Any help would be greatly appreciated!

Public Key Hash Check failing

Aside from bypassing the actual hash check, no matter what I do, I cannot get the _applepay_verify_pubkey_hash to pass. If I bypass this function (i.e. comment out "return APPLEPAY_ERROR_FAILED_TO_VERIFY_PUBKEY_HASH") then everything decrypts and works great. Any advice on what went wrong?

Decrypt for RSA option.

The extension at the moment only considers decryption for ECC, which was for the longest time the only encryption option available.

Now when following Apple's instructions on creating Apple Pay Merchant ID certificates, RSA is used as the encryption option.

Though oddly enough, EC_v1 is returned as the value of token.paymentData.version when a payment is authorised for a merchant with this setup.

This means when attempting to decrypt, the error APPLEPAY_ERROR_COULD_NOT_INIT_SECRET_CTX is raised.

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.