首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何在我的“第三方服务器”上验证GKLocalPlayer?

如何在我的“第三方服务器”上验证GKLocalPlayer?
EN

Stack Overflow用户
提问于 2013-07-01 23:56:47
回答 8查看 10.9K关注 0票数 21

iOS7引入了新的GKLocalPlayer方法generateIdentityVerificationSignatureWithCompletionHandler()

有没有人知道如何用它来做好事?我假设在Apple服务器端会有一些公共API。

EN

回答 8

Stack Overflow用户

发布于 2014-01-03 03:04:53

以下是C# WebApi服务器端版本:

代码语言:javascript
运行
复制
public class GameCenterController : ApiController
{
    // POST api/gamecenter
    public HttpResponseMessage Post(GameCenterAuth data)
    {
        string token;
        if (ValidateSignature(data, out token))
        {
            return Request.CreateResponse(HttpStatusCode.OK, token);
        }
        return Request.CreateErrorResponse(HttpStatusCode.Forbidden, string.Empty);
    }

    private bool ValidateSignature(GameCenterAuth auth, out string token)
    {
        try
        {
            var cert = GetCertificate(auth.PublicKeyUrl);
            if (cert.Verify())
            {
                var csp = cert.PublicKey.Key as RSACryptoServiceProvider;
                if (csp != null)
                {
                    var sha256 = new SHA256Managed();
                    var sig = ConcatSignature(auth.PlayerId, auth.BundleId, auth.Timestamp, auth.Salt);
                    var hash = sha256.ComputeHash(sig);

                    if (csp.VerifyHash(hash, CryptoConfig.MapNameToOID("SHA256"), Convert.FromBase64String(auth.Signature)))
                    {
                        // Valid user.
                        // Do server related user management stuff.
                        return true;
                    }
                }
            }

            // Failure
            token = null;
            return false;
        }
        catch (Exception ex)
        {
            // Log the error
            token = null;
            return false;
        }
    }

    private static byte[] ToBigEndian(ulong value)
    {
        var buffer = new byte[8];
        for (int i = 0; i < 8; i++)
        {
            buffer[7 - i] = unchecked((byte)(value & 0xff));
            value = value >> 8;
        }
        return buffer;
    }

    private X509Certificate2 GetCertificate(string url)
    {
        var client = new WebClient();
        var rawData = client.DownloadData(url);
        return new X509Certificate2(rawData);
    }

    private byte[] ConcatSignature(string playerId, string bundleId, ulong timestamp, string salt)
    {
        var data = new List<byte>();
        data.AddRange(Encoding.UTF8.GetBytes(playerId));
        data.AddRange(Encoding.UTF8.GetBytes(bundleId));
        data.AddRange(ToBigEndian(timestamp));
        data.AddRange(Convert.FromBase64String(salt));
        return data.ToArray();
    }
}


public class GameCenterAuth
{
    public string PlayerId { get; set; }
    public string BundleId { get; set; }
    public string Name { get; set; }
    public string PublicKeyUrl { get; set; }
    public string Signature { get; set; }
    public string Salt { get; set; }
    public ulong Timestamp { get; set; }
}
票数 12
EN

Stack Overflow用户

发布于 2013-12-06 18:20:21

谢谢,@odyth。谢谢,@莱昂内尔。我想在这里添加Python版本(基于您的版本)。它有一个小缺陷-苹果证书没有被验证-在pyOpenSSL绑定上没有这样的API。

代码语言:javascript
运行
复制
import urllib2
import OpenSSL
import struct

def authenticate_game_center_user(gc_public_key_url, app_bundle_id, gc_player_id, gc_timestamp, gc_salt, gc_unverified_signature):
    apple_cert = urllib2.urlopen(gc_public_key_url).read()
    gc_pkey_certificate = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_ASN1, apple_cert)

    payload = gc_player_id.encode('UTF-8') + app_bundle_id.encode('UTF-8') + struct.pack('>Q', int(gc_timestamp)) + gc_salt

    try:
        OpenSSL.crypto.verify(gc_pkey_certificate, gc_unverified_signature, payload, 'sha1')
        print 'Signature verification is done. Success!'
    except Exception as res:
        print res

public_key_url = 'https://sandbox.gc.apple.com/public-key/gc-sb.cer'
player_GC_ID = 'G:1870391344'
timestamp = '1382621610281'
your_app_bundle_id = 'com.myapp.bundle_id'

with open('./salt.dat', 'rb') as f_salt:
    with open('./signature.dat', 'rb') as f_sign:
        authenticate_game_center_user(public_key_url, your_app_bundle_id, player_GC_ID, timestamp, f_salt.read(), f_sign.read())
票数 3
EN

Stack Overflow用户

发布于 2015-01-08 04:00:01

添加了Python的答案,但使用了PyCrypto 2.6 (这是Google App Engine解决方案)。还要注意的是,这里没有在下载后验证公共证书,类似于上面使用OpenSSL的python答案。这一步真的有必要吗?如果我们检查到公钥URL是去往一个苹果域名,并且它使用的是ssl (https),这不是意味着它不会受到中间人攻击吗?

无论如何,这是代码。注意:在连接和使用之前,二进制文本被重新转换为二进制。此外,我还必须更新我的本地python安装以使用PyCrypto 2.6,然后才能工作:

代码语言:javascript
运行
复制
from Crypto.PublicKey import RSA 
from Crypto.Signature import PKCS1_v1_5
from Crypto.Hash import SHA
from base64 import b64decode 
from Crypto.Util.asn1 import DerSequence
from binascii import a2b_base64
import struct
import urlparse

def authenticate_game_center_user(gc_public_key_url, app_bundle_id, gc_player_id, gc_timestamp, gc_salt, gc_unverified_signature):

    apple_cert = urllib2.urlopen(gc_public_key_url).read()

    #Verify the url is https and is pointing to an apple domain.
    parts = urlparse.urlparse(gc_public_key_url)
    domainName = ".apple.com"
    domainLocation = len(parts[1]) - len(domainName)
    actualLocation = parts[1].find(domainName)
    if parts[0] != "https" or domainName not in parts[1] or domainLocation != actualLocation:
        logging.warning("Public Key Url is invalid.")
        raise Exception

    cert = DerSequence()
    cert.decode(apple_cert)
    tbsCertificate = DerSequence()
    tbsCertificate.decode(cert[0])
    subjectPublicKeyInfo = tbsCertificate[6]

    rsakey = RSA.importKey(subjectPublicKeyInfo) 
    verifier = PKCS1_v1_5.new(rsakey) 

    payload = gc_player_id.encode('UTF-8') 
    payload = payload + app_bundle_id.encode('UTF-8')
    payload = payload + struct.pack('>Q', int(gc_timestamp))
    payload = payload + b64decode(gc_salt)
    digest = SHA.new(payload)

    if verifier.verify(digest, b64decode(gc_unverified_signature)):
        print "The signature is authentic."
    else:
        print "The signature is not authentic."
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/17408729

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档