如何在PHP中检查Apple AppReceipt服务器端的UID哈希? [英] How-to check the UID hash of an Apple AppReceipt server side in PHP?

查看:189
本文介绍了如何在PHP中检查Apple AppReceipt服务器端的UID哈希?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我问这个问题是为了分享解决方案代码。

I'm asking this question in order to share a solution code.

背景信息:Apple在iOS 7中引入了AppReceipt。也适用于OS X IAP。此收据是PKCS#7容器(asn.1),其有效负载也是asn.1结构化的。
来自Apple的文档指示如何控制设备上的收据的有效性并解析它以检查是否已为当前设备发出。
还有通过联系Apple服务器通过应用程序服务器验证收据的说明。但在后一种情况下,Apple返回的json数据不包括识别发起设备的信息。以前使用transactionReceipt的IAP协议模型在json中包含了identifierForVendor UID。

Context: Apple introduced the AppReceipt in iOS 7. It is also present for OS X IAP. This receipt is a PKCS#7 container (asn.1) with a payload which is also asn.1 structured. Documentation from Apple instructs how to control the validity of the receipt on-device and to parse it to check that is has been issued for the current device. There are also instructions to validate the receipt through an application server by contacting Apple server. In that latter case though, the returned json data from Apple does not include information identifying the originating device. Previous IAP protocol model with transactionReceipt included the identifierForVendor UID in the json.

问题:如何使用PHP解析服务器上的二进制收据以检查UID哈希,以确保此收据属于此设备?这可以在将收据发送到Apple服务器之前或之后完成。

Question: How to parse the binary receipt on a server, using PHP, to check the UID hash, to ensure this receipt belongs to this device? This may be done before or after sending the receipt to Apple server.

推荐答案

此脚本仅检查哈希而不是整体收据签名有效期。这项工作留给Apple发送给他们的文件收据。

This script only check for the hash and not the whole receipt signature validity. This work is left to Apple by sending them the receipt as documented.

哈希检查直接改编自C中Apple记录的示例代码。这里的棘手任务是从二进制收据中找到正确的信息。

The hash check is directly adapted from the Apple documented example code in C. The tricky task here being to find the right pieces of information out of the binary receipt.

此代码使用 Kris Bailey的ASN1解析器,链接也在源代码中。

This code is using an ASN1 parser by Kris Bailey, link is also in the source code.

您需要在解析器脚本代码中更改一条注释:注释行#189和取消注释#190。解析器脚本中的最后一个函数也是未使用的,可以删除。

You need to change one comment in the parser script code: comment line #189 and uncomment #190. Also the last function in the parser script is unused and can be deleted.

<?php

//$vendID should be a binary string. If you have the vendorID as an ASCII string, convert it back
// $vendID = hex2bin(str_replace('-', '', $vendID_string)); //PHP 5.4+
$vendID = hextobin(str_replace('-', '', $vendID_string));     //PHP 5.3- function below

require_once 'ans1.php'; //donwnload from http://www.phpkode.com/source/s/mistpark-server/library/asn1.php
$asn_parser = new ASN_BASE;
//parse the receipt binary string
$pkcs7 = $asn_parser->parseASNString($receipt->bin);
// $asn_parser->printASN($pkcs7); //uncomment this line to print and inspect PKCS7 container

//target the payload object inside the container
$payload_sequence = $pkcs7[0]->asnData[1]->asnData[0]->asnData[2]->asnData;
//control the OID of payload
if ($payload_sequence[0]->asnData != '1.2.840.113549.1.7.1') {
     echo "invalide payload OID";
     exit;
}
//the payload octet_string is itself an ASN1 structure. Parse it.
$payload = $asn_parser->parseASNString($payload_sequence[1]->asnData[0]->asnData);
// $asn_parser->printASN($payload); //uncomment this line to print and inspect payload ASN structure
$payload_attributes = $payload[0]->asnData; //array of ASN_SEQUENCE

foreach ($payload_attributes as $attr) {
     $type = $attr->asnData[0]->asnData;
     switch ($type) {
        case 2:
            $bundle_id = $attr->asnData[2]->asnData;
            break;
        // case 3:
        //     $bundle_version = $attr->asnData[2]->asnData;
        //     break;
        case 4:
            $opaque = $attr->asnData[2]->asnData;
            break;
        case 5:
            $hash = $attr->asnData[2]->asnData;
               break;          
     default:
          break;
     }
}
//compute the hash
$hash_loc = sha1($vendID . $opaque . $bundle_id, true);
//control hash equality
if ($hash_loc == $hash) {
     echo "OK\n";
}
else {
     echo "KO\n";
}

echo "</pre>\n";


//*******************************************************

function hextobin($hexstr) { 
    $n = strlen($hexstr); 
    $sbin = '';   
     for ($i = 0; $i < $n; $i += 2) $sbin .= pack("H*", substr($hexstr,$i,2));
    return $sbin; 
}


?>

这篇关于如何在PHP中检查Apple AppReceipt服务器端的UID哈希?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆