How to authenticate the GKLocalPlayer on my 'third party server'?

后端 未结 10 443
鱼传尺愫
鱼传尺愫 2020-11-30 02:53

iOS7 introduced new GKLocalPlayer method generateIdentityVerificationSignatureWithCompletionHandler().

Does anyone know how to use it for good? I assum

10条回答
  •  醉酒成梦
    2020-11-30 03:29

    Thanks for the code samples, here comes golang solution:

    func DownloadCert(url string) []byte {
        b, err := inet.HTTPGet(url)
        if err != nil {
            log.Printf("http request error %s", err)
            return nil
        }
        return b
    }
    
    
    func VerifySig(sSig, sGcId, sBundleId, sSalt, sTimeStamp string, cert []byte) (err error) {
        sig, err := base64.StdEncoding.DecodeString(sSig)
        if err != nil {
            return
        }
        salt, err := base64.StdEncoding.DecodeString(sSalt)
        if err != nil {
            return
        }
        timeStamp, err := strconv.ParseUint(sTimeStamp, 10, 64)
        if err != nil {
            return
        }
    
        payload := new(bytes.Buffer)
        payload.WriteString(sGcId)
        payload.WriteString(sBundleId)
        binary.Write(payload, binary.BigEndian, timeStamp)
        payload.Write(salt)
    
        return verifyRsa(cert, sig, payload.Bytes())
    }
    
    func verifyRsa(key, sig, content []byte) error {
        cert, err := x509.ParseCertificate(key)
        if err != nil {
            log.Printf("parse cert error %s", err)
            return err
        }
        pub := cert.PublicKey.(*rsa.PublicKey)
    
        h := sha256.New()
        h.Write(content)
        digest := h.Sum(nil)
    
        err = rsa.VerifyPKCS1v15(pub, crypto.SHA256, digest, sig)
        return err
    }
    

    a little http helper

    func HTTPGet(fullUrl string) (content []byte, err error) {
        log.Printf("http get url %s", fullUrl)
        resp, err := http.Get(fullUrl)
        if err != nil {
            log.Printf("url can not be reached %s,%s", fullUrl, err)
            return
        }
    
        if resp.StatusCode != http.StatusOK {
            return nil, errors.New("ERROR_STATUS_NOT_OK")
        }
        body := resp.Body
        content, err = ioutil.ReadAll(body)
        if err != nil {
            log.Printf("url read error %s, %s", fullUrl, err)
            return
        }
        body.Close()
        return
    }
    

    test code

    func TestVerifyFull(t *testing.T) {
        cert := DownloadCert("https://sandbox.gc.apple.com/public-key/gc-sb-2.cer")
        if cert == nil {
            log.Printf("cert download error ")
        }
        sig := "sig as base64"
        salt := "salt as base64"
        timeStamp := "1442816155502"
        gcId := "G:12345678"
        bId := "com.xxxx.xxxx"
        err := VerifySig(sig, gcId, bId, salt, timeStamp, cert)
        log.Printf("result %v", err)
    }
    

    a little function to validate the cert download url. Prevent to download from any where anything

    func IsValidCertUrl(fullUrl string) bool {
        //https://sandbox.gc.apple.com/public-key/gc-sb-2.cer
        uri, err := url.Parse(fullUrl)
        if err != nil {
            log.Printf("not a valid url %s", fullUrl)
            return false
        }
    
        if !strings.HasSuffix(uri.Host, "apple.com") {
            log.Printf("not a valid host %s", fullUrl)
            return false
        }
    
        if path.Ext(fullUrl) != ".cer" {
            log.Printf("not a valid ext %s, %s", fullUrl, path.Ext(fullUrl))
            return false
        }
        return true
    }
    

提交回复
热议问题