dsajdgjadwqe3247382 2014-06-18 21:20
浏览 77

如何在PHP中检查Apple AppReceipt服务器端的UID哈希?

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

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.

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.

  • 写回答

1条回答 默认 最新

  • dongzhuo3376 2014-06-18 21:20
    关注

    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.

    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.

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

    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
    ";
    }
    else {
         echo "KO
    ";
    }
    
    echo "</pre>
    ";
    
    
    //*******************************************************
    
    function hextobin($hexstr) { 
        $n = strlen($hexstr); 
        $sbin = '';   
         for ($i = 0; $i < $n; $i += 2) $sbin .= pack("H*", substr($hexstr,$i,2));
        return $sbin; 
    }
    
    
    ?>
    
    评论

报告相同问题?

悬赏问题

  • ¥15 素材场景中光线烘焙后灯光失效
  • ¥15 请教一下各位,为什么我这个没有实现模拟点击
  • ¥15 执行 virtuoso 命令后,界面没有,cadence 启动不起来
  • ¥50 comfyui下连接animatediff节点生成视频质量非常差的原因
  • ¥20 有关区间dp的问题求解
  • ¥15 多电路系统共用电源的串扰问题
  • ¥15 slam rangenet++配置
  • ¥15 有没有研究水声通信方面的帮我改俩matlab代码
  • ¥15 ubuntu子系统密码忘记
  • ¥15 保护模式-系统加载-段寄存器