Push-уведомления Safari - проверка подписи push-пакета не удалась - PullRequest
0 голосов
/ 12 июня 2019

Я потрепал свои волосы в течение недели, пытаясь заставить push-уведомления Safari работать на MacOS.Я выполнил шаги, перечисленные здесь: https://developer.apple.com/library/archive/documentation/NetworkingInternet/Conceptual/NotificationProgrammingGuideForWebsites/PushNotifications/PushNotifications.html#//apple_ref/doc/uid/TP40013225-CH3-SW24 и здесь: https://medium.com/@rossbulat/safari-push-notifications-complete-setup-ef57f19bbb89, реализовал конечную точку для обслуживания zip-пакета и конечную точку ведения журнала, но я получаю сообщение об ошибке «Проверка подписи push-пакета не удалась».

Я использую nodejs для создания zip-пакета и подписания файла манифеста.

Код для этого:

const fs = require('fs');
const path = require('path');
const crypto = require('crypto');
const child_process = require('child_process');
const rimraf = require('rimraf');

const archiver = require('archiver');
const websiteName = 'mywebsite.com';
const websiteFolder = 'mywebsite.com';
const websitePushID = 'web.com.mywebsite';
const allowedDomains = [
  'https://www.mywebsite.nl',
  'https://www.mywebsite.com'
];
const webServiceURL = 'https://api.mywebsite.com';
const urlFormatString = 'https://www.mywebsite.com/%@';
const authenticationToken = '3F2UyWU8VfJ6EHGZqd5TMteQ';
const certP12 = '../cert/certificate.p12';
const wwdrca = '../cert/AppleWWDRCA.pem';
const certPasswd = 'my password'; //p12 password

const raw_files = [
  'website.json',
  'icon.iconset/icon_16x16.png',
  'icon.iconset/icon_16x16@2x.png',
  'icon.iconset/icon_32x32.png',
  'icon.iconset/icon_32x32@2x.png',
  'icon.iconset/icon_128x128.png',
  'icon.iconset/icon_128x128@2x.png'
];

const website = {
  websiteName,
  websitePushID,
  allowedDomains,
  urlFormatString,
  authenticationToken,
  webServiceURL
};
const manifest = {};

const createZip = () => {
  return new Promise((resolve, reject) => {
    const basePath = `${__dirname}/${websiteFolder}.pushpackage`;
    console.log('website.json', `${basePath}/website.json`);

    fs.writeFileSync(`${basePath}/website.json`, JSON.stringify(website));
    console.log('manifest.json');

    raw_files.forEach(file => {
      const sha512 = crypto.createHash('sha512');
      sha512.update(fs.readFileSync(`${basePath}/${file}`), 'binary');
      manifest[file] = {
        hashType: 'sha512',
        hashValue: sha512.digest('hex')
      };

    });

    fs.writeFileSync(`${basePath}/manifest.json`, JSON.stringify(manifest));
    child_process.execSync(`openssl pkcs12 -in ${path.join(__dirname, certP12)} -nocerts -out private.pem -passin pass:${certPasswd} -passout pass:${certPasswd}`);
    child_process.execSync(`openssl pkcs12 -in ${path.join(__dirname, certP12)} -clcerts -nokeys -out cert.pem -passin pass:${certPasswd}`);

    child_process.execSync(`openssl smime -binary -sign -certfile ${path.join(__dirname, wwdrca)} -signer ${path.join(__dirname, '../cert', 'certificate.pem')} -inkey private.pem -in ${basePath}/manifest.json -out ${basePath}/signature -outform DER -passin pass:${certPasswd}`);

    raw_files.push('manifest.json');

    raw_files.push('signature');
    if(fs.existsSync(`${basePath}.zip`)) {
      fs.unlinkSync(`${basePath}.zip`);

    }

    const archive = archiver('zip');
    const output = fs.createWriteStream(`${basePath}.zip`);

    archive.pipe(output);

    console.log('building Package');

    raw_files.forEach(file => archive.append(fs.createReadStream(`${basePath}/${file}`), {name: file}));

    archive.on('finish', () => {
      console.log('finished');
      return resolve();
    });

    console.log('finalize');

    archive.finalize((err, bytes) => {
      if(err) {
        throw err;
      }

      console.log(`${bytes} total bytes`);

      fs.unlink('cert.pem');
      fs.unlink('private.pem');
      rimraf.sync(basePath);
    });

  });
};

module.exports = createZip;

Поскольку проверка подписи не проходит, проблемадолжно быть в этой строке:

child_process.execSync(`openssl smime -binary -sign -certfile ${path.join(__dirname, wwdrca)} -signer ${path.join(__dirname, '../cert', 'certificate.pem')} -inkey private.pem -in ${basePath}/manifest.json -out ${basePath}/signature -outform DER -passin pass:${certPasswd}`);

Для аргумента -signer я впервые использовал cert.pem, сгенерированный в предыдущей строке:

child_process.execSync(`openssl pkcs12 -in ${path.join(__dirname, certP12)} -clcerts -nokeys -out cert.pem -passin pass:${certPasswd}`);

Но я думаю, что это необходимобыть файлом certificate.pem, который я сгенерировал из файла certificate.p12 с помощью этой команды:

openssl pkcs12 -in certificate.p12 -out certificate.pem -nodes

Однако это не решает проблему.Я несколько раз следовал инструкциям, чтобы получить правильные сертификаты, и я почти уверен, что сделал это правильно, но я далеко не эксперт по сертификатам, так что, возможно, я что-то там не так сделал.Возможно, кто-то может проверить приведенный выше код, чтобы увидеть, является ли он правильным.

Любая помощь очень ценится, поскольку у моей головы едва хватает волос, чтобы вырвать ... спасибо!

...