如何从第三方node.js服务器验证Game Center用户

时间:2014-02-05 07:06:13

标签: ios node.js authentication ssl-certificate game-center

我一直在尝试使用新的iOS Game Center GKPlayer方法generateIdentityVerificationSignatureWithCompletionHandler,因此我们可以安全地依赖Game Center凭据进行身份验证。我们使用Node.js作为后端服务器,我一直在尝试验证签名,但无济于事。

以下是我所拥有的服务器端代码 - 如果有人可以查看缺少的内容,那将不胜感激。这个问题在这里得到了一些回答:How to authenticate the GKLocalPlayer on my 'third party server'?,但Node.js还没有特别解决。请注意,下面的代码不能确保具有签名权限的证书的有效性。

    //Client sends the payload below
    //json.playerId - UTF-8 string
    //json.bundleId - UTF-8 string
    //json.timestamp - Hex string
    //json.salt - base64 encoded
    //json.publicKeyURL - UTF-8 string
    //json.signature - base64 encoded
    var json = JSON.parse(req.body);
    console.log(JSON.stringify(json));
    //get the certificate
    getCertificate(json.publicKeyURL, function(cert){
        //read file from fs for now, since getCertificate returns cert in DER format
        fs = require('fs');
        fs.readFile('/gc-sb.pem', 'utf8', function (err,data) {
            if (err) {
                console.log(err);
            } else {
                console.log(data);
            var verifier = crypto.createVerify("sha1WithRSAEncryption");
            verifier.write(json.playerId, "utf8");
            verifier.write(json.bundleId, "utf8");
            verifier.write(json.hexTimestamp, "hex");
            verifier.write(json.salt, "base64");
            var isValid = verifier.verify(data, json.signature, "base64");

            console.log("isvalid: " + isValid);
            }
        });
    });

我发现在node.js中使用crypto模块的一件事是它似乎想要PEM格式的证书,我相信从Apple检索的格式是DER。在我弄清楚如何将DER文件转换为PEM之前,我暂时使用

转换它
openssl x509 -in gc-sb.cer -inform der -outform pem -out gc-sb.pem

对我来说最重要的是能够首先验证签名。转换证书并对签名机构进行验证将在稍后进行:)

编辑:我已经弄明白了 - 我正在对playerId,bundleId,timestamp和salt进行哈希处理,然后使用哈希值作为验证信息。我需要将这些信息放入验证程序中,以便在没有SHA-1哈希的情况下进行验证(因为验证程序将负责处理它)。我已将上面的代码修改为“使其正常工作”。希望这可以帮助遇到这种情况的任何人。

3 个答案:

答案 0 :(得分:1)

以下是使用nodejs验证游戏中心身份的方法。它还可以将der证书格式转换为pem。

var crypto = require('crypto');
var request = require('request');
var ref = require('ref');

var token = require('./test.json');

request({url: token.publicKeyURL, encoding: null}, function (error, response, body) {
    if (!error && response.statusCode == 200) {

        var verifier = crypto.createVerify("sha1");
        verifier.update(token.playerId, "utf8");
        verifier.update(token.bundleId, "utf8");

        var buf = ref.alloc('uint64');
        ref.writeUInt64BE(buf, 0, token.timestamp.toString());

        verifier.update(buf);
        verifier.update(token.salt, 'base64');

        var pmd = '-----BEGIN CERTIFICATE-----';

        var base64 = body.toString('base64');
        var size = base64.length;

        for (var i = 0; i < size; i = i + 64) {
            var end = i + 64 < size ? i + 64 : size;
            pmd = pmd + '\n' + base64.substring(i, end);
        }

        pmd = pmd + '\n-----END CERTIFICATE-----';

        var valid = verifier.verify(pmd, token.signature, "base64");

        console.log(valid);

    }
});

答案 1 :(得分:1)

所以今天我们注意到需要SHA256来验证用户,SHA1失败。

答案 2 :(得分:1)