草庐IT

php - 苹果官网推送: Signature verification of push package failed, 但是苹果证书没问题

coder 2024-04-30 原文

我正在尝试使用 Codeigniter 向 Safari 实现 Web 推送通知,我正在关注 Apple Guide

我创建了一个库来创建基于此 connorlacombe 的推送包github项目。

这是我的图书馆:

<?php if ( ! defined('BASEPATH')) exit("No direct script access allowed");class Apple_utils {

var $certificate_path;
var $certificate_password;
var $dir;
var $raw_files = array(
    "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",
    "website.json"
);

public function __construct($config = array())
{
    if (count($config) != 0){
        $this->initialize($config);
    }
    log_message("debug", "Apple Class Initialized");
}

public function initialize($config = array())
{
    if (empty($config["certificate_path"]) || empty($config["certificate_password"]) || empty($config["dir"])) return FALSE;
    $this->certificate_path = $config["certificate_path"];
    $this->certificate_password = $config["certificate_password"];
    $this->dir = $config["dir"];
    return $this;
}

// Creates the push package, and returns the path to the archive.
public function create_push_package($id) 
{        
    list($usec, $sec) = explode(" ", microtime());
$now = ((float)$usec + (float)$sec);

//DELETING OLD DIR
    $this->_delete_old_files($this->dir . "tmp/", $now);

    $package_dir = $this->dir . "tmp/" . $now;
    if (!mkdir($package_dir)) return FALSE;
    @chmod($package_dir, 0755);

    $this->_copy_raw_push_package_files($package_dir, $id);

    if (!$this->_create_manifest($package_dir)) return FALSE;

    if (!$this->_create_signature($package_dir)) return FALSE;

    $package_path = $this->_package_raw_data($package_dir);

    return $package_path;
}

private function _copy_raw_push_package_files($package_dir, $id) 
{
    mkdir($package_dir . "/icon.iconset");
    foreach ($this->raw_files as $raw_file) {
        copy($this->dir . "pushPackage/" . $raw_file, $package_dir . "/" . $raw_file);
        if ($raw_file == "website.json") {
    $wjson = file_get_contents($package_dir . "/". $raw_file);
    unlink($package_dir . "/". $raw_file);
    $ff = fopen($package_dir . "/". $raw_file, "x");
    fwrite($ff, str_replace(array("{BASE_URL}", "{AUTHTOKEN}"), array(rtrim(base_url(), "/"), "authenticationToken_".$id), $wjson)); 
    fclose($ff);
        }
    }
}

private function _create_manifest($package_dir) 
{
    // Obtain SHA1 hashes of all the files in the push package
    $manifest_data = array();
    foreach ($this->raw_files as $raw_file) {
        $manifest_data[$raw_file] = sha1(file_get_contents($package_dir . "/" . $raw_file));
    }
    file_put_contents($package_dir . "/manifest.json", json_encode( (object)$manifest_data ));
    return TRUE;
}

private function _create_signature($package_dir) 
{
    // Load the push notification certificate
    $pkcs12 = file_get_contents($this->certificate_path);
    $certs = array();
    if(!openssl_pkcs12_read($pkcs12, $certs, $this->certificate_password)){
        return FALSE;
    }

    $signature_path = $package_dir . "/signature";

    // Sign the manifest.json file with the private key from the certificate
    $cert_data = openssl_x509_read($certs["cert"]);
    $private_key = openssl_pkey_get_private($certs["pkey"], $this->certificate_password);
    openssl_pkcs7_sign($package_dir . "/manifest.json", $signature_path, $cert_data, $private_key, array(), PKCS7_BINARY | PKCS7_DETACHED);

    // Convert the signature from PEM to DER
    $signature_pem = file_get_contents($signature_path);
    $matches = array();
    if (!preg_match("~Content-Disposition:[^\n]+\s*?([A-Za-z0-9+=/\r\n]+)\s*?-----~", $signature_pem, $matches)){
        return FALSE;
    }
    $signature_der = base64_decode($matches[1]);
    file_put_contents($signature_path, $signature_der);
    return TRUE;
}

private function _package_raw_data($package_dir) 
{

    $CI = &get_instance();
    $CI->load->library("zip");

    $raw_files = $this->raw_files;
    $raw_files[] = "manifest.json";
    $raw_files[] = "signature";
    foreach ($raw_files as $raw_file) {
        $CI->zip->add_data($raw_file, file_get_contents($package_dir . "/" .$raw_file));
    }
    ob_end_clean(); //I HAVE TO PUT THIS HERE BECAUSE IF NOT THE ZIP CAN NOT BE OPENED
    $CI->zip->download( "Website.pushpackage.zip" );
}

function _delete_old_files($dir, $now)
{
    $expiration = 300; //seconds

    $current_dir = @opendir($dir);

while ($filename = @readdir($current_dir)){
        if ($filename != "." && $filename != ".." && $filename != "index.html"){
    $name = str_replace(".zip", "", $filename);

    if (($name + $expiration) < $now) $this->_delete_file($this->dir . "tmp/" . $filename);
        }
}

@closedir($current_dir);
}

function _delete_file($file)
{
    @chmod($file, 0755);
    if (is_dir($file)){
        $dir = @opendir($file); 
        while ($filename = @readdir($dir)){
    if ($filename != "." && $filename != ".."){
                $this->_delete_file($file . "/" . $filename);
    }
        }   
        @closedir($dir);
        @rmdir($file);
    }else{
        @unlink($file);
    }  
}}

图书馆工作,创建一个 .zip,带有 website.json,签名等,直到昨天工作完美,然后不再工作,当我检查日志时总是说“推送包的签名验证失败”并且我已经创建了不止一次证书,但仍然是同样的错误。

请帮忙。

最佳答案

感谢Jack , 他的 solution解决了我的问题:

openssl_pkcs7_sign("$package_dir/manifest.json", $signature_path, $cert_data, $private_key, array(), PKCS7_BINARY | PKCS7_DETACHED,"/path/to/certificate/AppleWWDRCA.pem");

要创建 AppleWWDRCA.pem,您需要:

1 - 下载 AppleWWDRCA.cer

2 - 执行以下命令:

openssl x509 -inform der -in AppleWWDRCA.cer -out AppleWWDRCA.pem

关于php - 苹果官网推送: Signature verification of push package failed, 但是苹果证书没问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35430205/

有关php - 苹果官网推送: Signature verification of push package failed, 但是苹果证书没问题的更多相关文章

  1. ruby - 为什么 4.1%2 使用 Ruby 返回 0.0999999999999996?但是 4.2%2==0.2 - 2

    为什么4.1%2返回0.0999999999999996?但是4.2%2==0.2。 最佳答案 参见此处:WhatEveryProgrammerShouldKnowAboutFloating-PointArithmetic实数是无限的。计算机使用的位数有限(今天是32位、64位)。因此计算机进行的浮点运算不能代表所有的实数。0.1是这些数字之一。请注意,这不是与Ruby相关的问题,而是与所有编程语言相关的问题,因为它来自计算机表示实数的方式。 关于ruby-为什么4.1%2使用Ruby返

  2. arrays - Ruby 数组 += vs 推送 - 2

    我有一个数组数组,想将元素附加到子数组。+=做我想做的,但我想了解为什么push不做。我期望的行为(并与+=一起工作):b=Array.new(3,[])b[0]+=["apple"]b[1]+=["orange"]b[2]+=["frog"]b=>[["苹果"],["橙子"],["Frog"]]通过推送,我将推送的元素附加到每个子数组(为什么?):a=Array.new(3,[])a[0].push("apple")a[1].push("orange")a[2].push("frog")a=>[[“苹果”、“橙子”、“Frog”]、[“苹果”、“橙子”、“Frog”]、[“苹果”、“

  3. ruby - 为什么 `middleman serve` 有效,但是 `middleman build` 编译这个 Sass 失败? - 2

    当我刚刚运行middleman时服务,all.css编译得很好,只包含对+box-shadow(none)的调用:/*line1,/home/yang/asdf/source/stylesheets/content.css.sass*/div{-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;}但是当我构建网站时,我得到了这个Sass/Compass错误:$middlemanbuildSlim::EmbeddedEngineisdeprecated,itiscalledSlim::EmbeddedinSlim2.0

  4. ruby-on-rails - 这个 C 和 PHP 程序员如何学习 Ruby 和 Rails? - 2

    按照目前的情况,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visitthehelpcenter指导。关闭9年前。我来自C、php和bash背景,很容易学习,因为它们都有相同的C结构,我可以将其与我已经知道的联系起来。然后2年前我学了Python并且学得很好,Python对我来说比Ruby更容易学。然后从去年开始,我一直在尝试学习Ruby,然后是Rails,我承认,直到现在我还是学不会,讽刺的是那些打着简单易学的烙印,但是对于我这样一个老练的程序员来说,我只是无法将它

  5. ruby - gem 推送结果为 "package metadata is missing" - 2

    我正在尝试将我更新的gem推送到ruby​​gems.com并得到以下结果。~/dev/V2/V2GPTI(master)$gembuildv2gpti.gemspecSuccessfullybuiltRubyGemName:v2gptiVersion:0.2File:v2gpti-0.2-universal-darwin-13.gem~/dev/V2/V2GPTI(master)$gempushv2gpti.gemspecERROR:Whileexecutinggem...(Gem::Package::FormatError)packagemetadataismissinginv2g

  6. ruby - 从 Ruby 连接到适用于 Windows Phone 8 的 Microsoft 推送通知服务 - 2

    我们正在开发一个需要推送通知的WP8应用程序。为了测试它,我们使用CURL命令行运行推送通知POST请求,确保它实际连接,使用客户端SSL证书进行身份验证并发送正确的数据。我们确实知道,当我们收到对设备的推送时,这项工作是有效的。这是我们一直用于测试目的的CURL命令:curl--certclient_cert.pem-v-H"Content-Type:text/xml"-H"X-WindowsPhone-Target:Toast"-H"X-NotificationClass:2"-XPOST-d"MytitleMysubtitle"https://db3.notify.live.ne

  7. ruby - 如何在特定队列中推送作业并使用 sidekiq 限制工作人员数量? - 2

    我知道我们可以做到:sidekiq_optionsqueue:"Foo"但在这种情况下,Worker只分配给一个队列:“Foo”。我需要在特定队列中分配作业(而不是worker)。使用Resque很容易:Resque.enqueue_to(queue_name,my_job)另外,为了并发问题,我需要限制每个队列的Worker数量为1。我该怎么做? 最佳答案 您可能会使用https://github.com/brainopia/sidekiq-limit_fetch然后:Sidekiq::Client.push({'class'=>

  8. ruby-on-rails - 为 rails 中的 javascript 生成完整的 url(类似于 javascript_path,但是是 url) - 2

    如何生成指向javascript文件的绝对链接。我想应该有类似下面的东西(不幸的是它似乎不可用):javascript_url'main'#->'http://localhost:3000/javascripts/main.js'代替:javascript_path'main'#->'/javascripts/main.js'我需要绝对URL,因为该javascript文件将用于书签。另外我需要相同的css文件。谢谢,德米特里。 最佳答案 javascript和css文件的绝对URL现在在Rails4中可用ActionView::H

  9. ruby-on-rails - 您已经激活了 spring 1.3.6,但是您的 Gemfile 需要 spring 1.3.3。 ( gem ::加载错误) - 2

    我今天遇到了同样的问题,有一个建议:在您的命令前添加bundleexec可能会解决此问题。前置bundleexec没有帮助(我已经这样做了)。springstop和springrestart没有帮助。我需要做的:bundleupdatespring这对我有用。在之前的gemlock文件中使用spring版本是否有更好的解决方案? 最佳答案 我删除gemfile.lock并运行bundle通常会清除一切。否则只需从Gemfile中删除gem"spring"并运行bundle 关于ruby-

  10. ruby-on-rails - Bundler::RubyVersionMismatch: 你的 Ruby 版本是 1.9.3,但是你的 Gemfile 指定了 2.0.0 - 2

    我正在使用带有Pow、Ruby、Rails和一堆有用的gem的Mac。每当我尝试打开我的应用程序时,我最近都会遇到此错误。Bundler::RubyVersionMismatch:您的Ruby版本为1.9.3,但您的Gemfile指定为2.0.0我明白这个错误,但我找不到为什么它没有在这里使用正确的版本。一些有用的信息:堆栈跟踪Bundler::RubyVersionMismatch:YourRubyversionis1.9.3,butyourGemfilespecified2.0.0~/.rvm/gems/ruby-2.0.0-p247/gems/bundler-1.3.5/lib/

随机推荐