APN-Node: Error when loading PEM file

2019-08-18 02:11发布

问题:

I am trying to get apn-node to push to my devices. The server is hosted on Heroku, so I do not want to commit the file. Also, I do not want to fetch it from a remote server but instead put it in an environment variable.

I already tried the following (source):
I created and downloaded the certificate from Apple and now have it in my Keychain. I exported it as a *.p12 file and converted it with openssl pkcs12 -in dev.p12 -out dev.pem -nodes into a *.pem file.

To set the environment variable, I did export APN_CERT="$(cat dev.pem)". When I print it out in my application it shows the certificate perfectly fine. However, when I actually send a notification (and node-apn opens the connection) it throws an [Error: wrong tag].
This error is emitted by the crypto module:

apn Raising error: +4ms [Error: wrong tag] undefined undefined
 apn Error occurred with trace: +1ms Error: wrong tag
  at Object.exports.createCredentials (crypto.js:176:17)
  at Object.exports.connect (tls.js:1344:27)
  at apnSocketLegacy

The module also throws a APN transmission error: moduleInitialisationFailed (Code: 513).

I was unable to find any useful information other than that this could be related to the crypto module itself of node itself. That's why I suspect I did something wrong when creating the certificate but thankful for any guiding advice.

回答1:

I found this guide for apns-sharp which actually described how to generate a valid .p12 file.

Still, writing it into an environment variable did not work. My code for reading it is: new Buffer(certString, 'binary') but I thought it still was not supplied in a correct format.

The solution for me was to actually read the buffer directly from a file via fs.readFileSync.


To get the env variable to work you could encode the file via cat cert.p12 | base64 and load it as such with new Buffer(certString, 'base64'). This finally worked for me.



回答2:

The preference here would be to use an encrypted p12 stored alongside the applciation and specify a passphrase which you set via an environment variable.

I was unable to replicate your problem using the following script

var apn = require("apn");

var token = "<token>; // iPad

var service = new apn.connection({
    cert: process.env.APN_CERT, key: process.env.APN_KEY
});

service.on("connected", function() {
    console.log("Connected");
});

service.on("error", function(err) {
    console.log("Standard error", err);
});

function pushNotification() {
    var note = new apn.notification().setAlertText("Hello");

    service.pushNotification(note, token);
    service.shutdown();
}

pushNotification();

Run with:

$ export APN_CERT=$(cat certificates/cert.pem)
$ export APN_KEY=$(cat certificates/key.pem)
$ node apn-env.js

The error you are seeing "wrong tag" is from OpenSSL and suggests a parsing error of the data contained within the certificate data itself rather than the data being loaded incorrectly from the env. Loading PEM files from environment variables works correctly