苹果网站推送:推包的签名验证失败,但苹果证书确定 [英] Apple website push: Signature verification of push package failed, but apple certificates are ok
问题描述
我尝试使用Codeigniter实现对Safari的Web推送通知,我正在关注 Apple Guide
I'm trying to implement Web push notifications to Safari using Codeigniter, I'm following the Apple Guide
,我创建了一个库来创建基于此 connorlacombe github项目的推包。
and I created a library to create a Push Package based in this connorlacombe github project.
这是我的库:
<?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);
}
}}
库工作,网站json,签名等,并且工作完美直到昨天,然后不工作了,当我检查日志总是说签名验证推包失败,我已经创建证书多次,但仍然同样的错误。
The library works, create a .zip with, website.json, signature, etc. and was working perfect until yesterday, then not work anymore, when I check the logs always say "Signature verification of push package failed" and I has been created the certificates more than one time, but still the same error .
请帮助。
推荐答案
href =http://stackoverflow.com/users/5413802/jack> Jack ,他的解决方案解决了我的问题:
Thanks to Jack, his solution has solved my problem:
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,您需要:
To create AppleWWDRCA.pem you need:
1 - 下载 AppleWWDRCA.cer
2 - 执行以下命令:
2 - Execute the following command:
openssl x509 -inform der -in AppleWWDRCA.cer -out AppleWWDRCA.pem
这篇关于苹果网站推送:推包的签名验证失败,但苹果证书确定的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!