第三方服务器用PHP验证GameCenter GKLocalPlayer返回的签名

来源:互联网 发布:淘宝开店装修店铺2016 编辑:程序博客网 时间:2024/06/07 17:12

       项目中需要接入苹果GameCenter。第三方服务器不能单纯依靠从GameCenter获取到PlayerID依靠从作为判断玩家的唯一标识,所以通常需要对玩家进行另外的验证。苹果官方给出了解答方案:https://developer.apple.com/library/mac/documentation/GameKit/Reference/GKLocalPlayer_Ref/index.html#//apple_ref/occ/instm/GKLocalPlayer/generateIdentityVerificationSignatureWithCompletionHandler

                            

大致说下参考了网上一些资料后自己实践的过程

       首先是客户端调用[GKLocalPlayergenerateIdentityVerificationSignatureWithCompletionHandler]会获得四个返回值publicKeyUrl,signature, salt, timestamp这里解释下四个参数

publicKeyUrl是一个公钥的下载地址,NSURL类型,可直接转成NSString类型,进而再转成string类型供PHP传参

timestamp是一个uint64_t类型的时间戳,同样先转NSString再转string使用。

重点是signature和salt,他们是NSData类型,需要使用base64Encode将其转化为NSString:

NSString*string = [signature base64EncodedStringWithOptions:0];  salt同理。然后在转为String传给php做参数。(此处尤其注意编码格式)

好,基础数据已备齐,将其传给PHP端,按文档要求进行操作验证。参数例:

$request['publicKeyUrl']= 'https://static.gc.apple.com/public-key/gc-prod-2.cer';$request['playerID']= 'G:1234567890';$request['signature']= 'aqMcUTjC26YuCcHUuSLqCkOA2LhujkdinDCV/3BQyloEyg0NJkAVLn4fM+ScIMbS+JI3HDwyQhLT7tdwN2BtQTjSTvyV509fy7c+SLcWxVZzxt8YxN4VNJHEo3meG9bdQ9gozAUfnkBzMwke5hpCJJOhMYNmy/pB284CuuLvNi00GiAnx5Ij2ZfPi8QEg7NRTfyOGiHPfQ5Ahb1lf7G3VmOaXJ0PWq1UoHHRNShC1deaPWClyUuVyiI7c0OudIig7sibV8TNLXBKORXEExGgSswTYKDOjPQ/Wzk02ZckZtBebZgvYgomPR37odT+5F9NH0nx1oblmHiBaqwsedrftg==';$request['timestamp']= 1463472175011;$request['salt'] = 'ejNzcg==';

简单处理下参数,注意signature和salt需用base64_decode进行解码:

$playerID= $request['playerID'];$bundleID= 'com.abcedf.wasd';$signature= base64_decode($request['signature']);$timestamp= $request['timestamp'];$salt= base64_decode($request['salt']);


参照网上大神的操作,对timestamp进行处理:

//Timestamp is unsigned 64-bit integer big endian

$highMap = 0xffffffff00000000;$lowMap = 0x00000000ffffffff;$higher = ($timestamp & $highMap)>>32;$lower = $timestamp & $lowMap;$timestamp = pack('NN', $higher, $lower);

 

然后 $data = $playerID.$bundleID.$timestamp.$salt;

接下来下载并解析公钥:

$public_key_url= $request['publicKeyUrl'];$ssl_certificate= file_get_contents($public_key_url);$pem= chunk_split(base64_encode($ssl_certificate), 64, "\n");$pem= "-----BEGIN CERTIFICATE-----\n" . $pem . "-----END CERTIFICATE-----\n";$pubkeyid= openssl_pkey_get_public($pem);

最后按文档进行签名验证:

// 此处注意苹果的验证已由过去的OPENSSL_ALGO_SHA1变更为OPENSSL_ALGO_SHA256,而OPENSSL_ALGO_SHA256是PHP5.4.8以上才支持的算法。

$ok= openssl_verify($data, $signature, $pubkeyid, OPENSSL_ALGO_SHA256);openssl_free_key($pubkeyid);if($ok == 1) {  echo “Singnature is good.”;}elseif ($ok == 0) {  echo “Singnature is bad.”;}else {  echo “Singnature is error.”;} 


另外,强调下,以上代码在本地编译器上编译失败,但是通过网页方式运行可以成功。

主要参考:

http://stackoverflow.com/questions/17408729/how-to-authenticate-the-gklocalplayer-on-my-third-party-server

http://stackoverflow.com/questions/24621839/how-to-authenticate-the-gklocalplayer-on-my-third-party-server-using-php

 

次要参考:

https://segmentfault.com/q/1010000002705803  (方法和回答都有待验证。)




1 0
原创粉丝点击