Shane Shane - 7 months ago 34
PHP Question

Creating a PKCS #7 detached signature for Apple Wallet passes using PHP

This is an entirely new concept to me, so I'm shooting in the dark.


To create the signature file, make a PKCS #7 detached signature of the
manifest file, using the private key associated with your signing
certificate. Include the WWDR intermediate certificate as part of the
signature. You can download this certificate from Appleā€™s website.
Write the signature to the file signature at the top level of the pass
package. Include the date and time that the pass was signed using the
S/MIME signing-time attribute.


My understanding:




To create the signature file, make a PKCS #7 detached signature of the manifest file


I'll be using the
openssl_pkcs7_sign
function using the flag
PKCS7_DETACHED
.


using the private key associated with your signing certificate.


I'll be using the location of my ssl
cert.pem
file as the
signcert
parameter and the location of the
cert.key
file as the
privkey
parameter.


Include the WWDR intermediate certificate as part of the signature.


I'll include the path to the WWDR certificate in the
extracerts
parameter


Include the date and time that the pass was signed using the S/MIME signing-time attribute.


I'll include a an array with a key
signing-time
and value something like
2015-05-03 10:40:00
for the
headers
parameter.

My code:



private function createSignature($dir)
{
$cert = '/etc/ssl/cert.pem';
$key = '/etc/ssl/private/cert.key';
$wwdr = '/location/of/apple/wwdr/cert.cer';
$headers = [
'signing-time' => (new DateTime())->format('o-m-d H:i:s'),
];

return openssl_pkcs7_sign("$dir/manifest.json", "$dir/signature", $cert, $key, $headers, PKCS7_DETACHED, $wwdr);
}


Other questions:



I've noticed in the examples of the documentation for the
openssl_pkcs7_sign
function that some locations of the files are prefixed with
file://
. Why is this?

Answer
  1. Generate a Pass Type ID at https://developer.apple.com/account/ios/identifier/passTypeId
  2. Create a certificate for that Pass Type ID at https://developer.apple.com/account/ios/certificate/create/
  3. Download the certificate and put it in your keychain
  4. Find the certificate in your keychain and export it in as Certificates.p12 with no password
  5. Open terminal, run openssl pkcs12 -in Certificates.p12 -clcerts -nokeys -out pass_cert.pem -passin pass: to generate the certificate
  6. In terminal, run openssl pkcs12 -in Certificates.p12 -nocerts -out pass_key.pem -passin pass: -passout pass:YourPassword to generate the key
  7. Download the WWDR Certificate from https://www.apple.com/certificateauthority/ and put it in your keychain
  8. Export the WWDR Certificate from your keychain as wwdr.pem

The function to create the detached signature:

public function createSignature()
{
    $cert = "file://location/of/pass_cert.pem";
    $key = "file://location/of/pass_key.pem";
    $wwdr = "/location/of/wwdr.pem";

    openssl_pkcs7_sign("/location/of/manifest.json", "/location/of/signature",
        $cert, [$key, 'YourPassword'], [], PKCS7_BINARY | PKCS7_DETACHED, $wwdr);

    // convert pem to der
    $signature = file_get_contents("/location/of/signature");
    $begin = 'filename="smime.p7s"';
    $end = '------';
    $signature = substr($signature, strpos($signature, $begin) + strlen($begin));
    $signature = substr($signature, 0, strpos($signature, $end));
    $signature = trim($signature);
    $signature = base64_decode($signature);

    file_put_contents("/location/of/signature", $signature);
}

References: