alexandercerutti / passkit-generator

The easiest way to generate custom Apple Wallet passes in Node.js

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

getAsBuffer() fails with "Cannot read property 'length' of undefined"

AlexisBian opened this issue · comments

Hi,
Thanks for your work and hope everything goes well!

I am using this library in lambda and i got "Cannot read property 'length' of undefined" when I call getAsBuffer() or getAsStream()

Here is my code:

async createApplePassCard(S3,modelFile, userID, balance) {
        console.log(modelFile)
        const pass = await PKPass.from({
            model: modelFile,
            certificates: {
                wwdr: fs.readFileSync(this.wwdr).toString(),
                signerCert: fs.readFileSync(this.signerCert).toString(),
                signerKey: fs.readFileSync(this.signerKey).toString(),
                signerKeyPassphrase: this.signerKeyPassPhrase,
            },
        }, {
            serialNumber: userID
        });
        pass.setBarcodes(userID); 
        pass.primaryFields.push({
            "key": "balance",
            "label": "Balance",
            "value": balance
        });
        pass.secondaryFields.push({
            "key": "cardID",
            "label": "cardID",
            "value": userID
        });
        const buffer = pass.getAsBuffer() // goes wrong here
    }

And it is Error Message:

{
  "errorType": "TypeError",
  "errorMessage": "Cannot read property 'length' of undefined",
  "trace": [
    "TypeError: Cannot read property 'length' of undefined",
    "    at Object.ctx.start (/opt/nodejs/node_modules/node-forge/lib/hmac.js:79:24)",
    "    at Object.module.exports.forge.pbkdf2.pkcs5.pbkdf2 (/opt/nodejs/node_modules/node-forge/lib/pbkdf2.js:136:7)",
    "    at Object.pki.pbe.getCipherForPBES2 (/opt/nodejs/node_modules/node-forge/lib/pbe.js:854:24)",
    "    at Object.pki.pbe.getCipher (/opt/nodejs/node_modules/node-forge/lib/pbe.js:757:20)",
    "    at Object.pki.decryptPrivateKeyInfo (/opt/nodejs/node_modules/node-forge/lib/pbe.js:372:24)",
    "    at Object.pki.decryptRsaPrivateKey (/opt/nodejs/node_modules/node-forge/lib/pbe.js:616:16)",
    "    at parseCertificates (/opt/nodejs/node_modules/passkit-generator/lib/Signature.js:91:45)",
    "    at Object.create (/opt/nodejs/node_modules/passkit-generator/lib/Signature.js:30:45)",
    "    at PKPass.[pass.close] (/opt/nodejs/node_modules/passkit-generator/lib/PKPass.js:474:43)",
    "    at PKPass.getAsBuffer (/opt/nodejs/node_modules/passkit-generator/lib/PKPass.js:489:42)"
  ]
}

I am not sure what goes wrong. if it is possible would you please take a look at it? Thanks a lot!🙏
Alexis

Hey there @AlexisBian!
Thanks for using passkit-generator!

I'm not very sure of what is happening, but my suspect is directed towards that .toString() on wwdr, signerCert and signerKey calls.

I mean, I don't know if those .toString() make the string invalid somehow. I guess you used it because  fs.readFileSync was returning you a Buffer instead of a string.

I can suggest you to separate and log and see if something changes. Something like this.

const wwdr = fs.readFileSync(this.wwdr);
const signerCert = fs.readFileSync(this.signerCert);
const signerKey = fs.readFileSync(this.signerKey);
const signerKeyPassphrase = this.signerKeyPassPhrase;

console.log("RAW WWDR", wwdr, "tostring:", wwdr.toString());
console.log("RAW signerCert", signerCert, "tostring:", signerCert.toString());
console.log("RAW signerKey", signerKey, "tostring:", signerKey.toString());

const pass = await PKPass.from({
    model: modelFile,
    certificates: {
        wwdr,
        signerCert,
        signerKey,
        signerKeyPassphrase,
    },
}, {
    serialNumber: userID
});

Also, you might want to set the encoding to ensure they are strings without the need to convert them.

const wwdr = fs.readFileSync(this.wwdr, { encoding: "utf-8" });
const signerCert = fs.readFileSync(this.signerCert, { encoding: "utf-8" });
const signerKey = fs.readFileSync(this.signerKey, { encoding: "utf-8" });
const signerKeyPassphrase = this.signerKeyPassPhrase;

And check if the content changes somehow.

Let me know!

Hi @alexandercerutti Thanks for your quick response! I figure it out.
The certificates part is the source of the problem but not toString() Part. I found if I pass certs through the function"createApplePassCard" it would work but if I pass certs through the constructor function it does not work.
I am not good at js so I am not sure why it happened.

Here is the code which works

class ApplePassCard {
    constructor() {
    }
    async createApplePassCard(certs, S3, modelFile, userID, balance) {
        const wwdr = certs.wwdr
        const signerCert = certs.signerCert
        const signerKey = certs.signerKey
        const signerKeyPassphrase = certs.signerKeyPassphrase
        try{
        const pass = await PKPass.from({
            model: modelFile,
            certificates: {
                wwdr: fs.readFileSync(wwdr).toString(),
                signerCert:fs.readFileSync(signerCert).toString(),
                signerKey:fs.readFileSync(signerKey).toString(),
                signerKeyPassphrase:signerKeyPassphrase,
            },
        }, {
            // keys to be added or overridden
            serialNumber: userID
        });
        pass.setBarcodes(userID); // Random value
        pass.primaryFields.push({
            "key": "balance",
            "label": "Balance",
            "value": balance
        });
        pass.secondaryFields.push({
            "key": "cardID",
            "label": "cardID",
            "value": userID
        });
        const buffer = pass.getAsBuffer()
        ···
        }
}

Thanks again!

Sorry for the delay in my response, I thought to have answered you back eheh!
Glad you solved it. However, what you are saying to me sounds really weird, you know?

Sadly I don't have a full context here, so I'm not quite sure about what is happening, but it feels like it should be the same thing.

Guess we could close this now! Let me know if this should be re-opened 👍.

Thank you again for using passkit-generator