【问题标题】:Documentation on "public key" returned by GKLocalPlayer generateIdentityVerificationSignatureWithCompletionHandler:?GKLocalPlayer generateIdentityVerificationSignatureWithCompletionHandler 返回的“公钥”文档:?
【发布时间】:2019-05-12 03:52:35
【问题描述】:

是否有任何来自 Apple 的文档涵盖用于生成 - [GKLocalPlayer generateIdentityVerificationSignatureWithCompletionHandler:] 返回的文件的格式或算法?

我在 SO 上看到了 few questions 关于身份验证用户的基本流程,这似乎表明该文件是一个 .cer 文件(应用程序/pkix-cert),并且它使用 DER文件格式,但我找不到任何来自 Apple 的官方文件。

我希望在 Java 中验证证书,如果有人有任何示例,我也将不胜感激。

【问题讨论】:

    标签: java game-center x509certificate


    【解决方案1】:

    ios

    [localPlayer generateIdentityVerificationSignatureWithCompletionHandler:^(NSURL *publicKeyUrl, NSData *signature, NSData *salt, uint64_t timestamp, NSError *error) {
                    if(error != nil){
                        //login failed.
                    }else{
                        NSLog(@"signature : %@", [signature base64Encoding]);
                        NSLog(@"salt : %@", [salt base64Encoding]);
                        NSLog(@"PUBLIC_KEY_URL : %@", publicKeyUrl);
                        NSLog(@"signature : %@", [signature base64EncodedStringWithOptions:0]);
                        NSLog(@"salt : %@", [salt base64EncodedStringWithOptions:0]);
                        NSLog(@"timestamp : %lld", timestamp);
    
                        NSLog(@"Gamecenter login success.");
    
                        NSMutableData *payload = [[NSMutableData alloc] init];
                        [payload appendData:[[GKLocalPlayer localPlayer].playerID dataUsingEncoding:NSUTF8StringEncoding]];
                        [payload appendData:[[[NSBundle mainBundle] bundleIdentifier] dataUsingEncoding:NSUTF8StringEncoding]];
                        uint64_t timestampBE = CFSwapInt64HostToBig(timestamp);
                        [payload appendBytes:&timestampBE length:sizeof(timestampBE)];
                        [payload appendData:salt];
    
                        NSString *ext_id = localPlayer.playerID;
                        NSString *encodedSignedData = [payload base64EncodedStringWithOptions:0];
                        NSLog(@"SIGNEDDATA : %@", encodedSignedData);
                        NSString *encodedSignature  = [signature base64Encoding];
                        NSString *publicKeyUrlStr   = [publicKeyUrl absoluteString];
    
                    }
                }];
    

    java代码是..

    public static String makeEncodedSignedDataForAppleVerify(String player_id, String bundle_id, String timestamp, String salt){
        return new String(Base64.encodeBase64(concat(player_id.getBytes(),
                bundle_id.getBytes(),
                ByteBuffer.allocate(8).putLong(Long.parseLong(timestamp)).array(), 
                Base64.decodeBase64(salt))));
    }
    
    public static boolean gamecenterUserVerify(String publicKeyUrl, String signedData, String signature){
        try{
            URL url = new URL(publicKeyUrl);
    
            HttpURLConnection urlConn = (HttpURLConnection) url.openConnection();
            HttpURLConnection httpConn = (HttpURLConnection) urlConn;
            httpConn.setAllowUserInteraction(false);
            httpConn.connect();
    
            InputStream in = httpConn.getInputStream();
            BufferedInputStream bis = new BufferedInputStream(in);
            ByteArrayBuffer baf = new ByteArrayBuffer(99999);
            int read = 0;
            int bufSize = 512;
            byte[] buffer = new byte[bufSize];
            while(true){
                read = bis.read(buffer);
                if(read==-1){
                    break;
                }
                baf.append(buffer, 0, read);
            }
    
            byte[] bytes =baf.toByteArray();
            bis.close();
            in.close();
            httpConn.disconnect();
    
            CertificateFactory cf =   CertificateFactory.getInstance("X509");
            X509Certificate c = (X509Certificate) 
            cf.generateCertificate(new ByteArrayInputStream(bytes) );
    
            PublicKey key22 = c.getPublicKey();
    
            byte[] result = Base64.decodeBase64(signedData);//;
            byte[] decodedSignature = Base64.decodeBase64(signature);
    
            Signature sig;
            try {
                sig = Signature.getInstance("SHA256withRSA");
                sig.initVerify(key22);
                sig.update(result);
                if (!sig.verify(decodedSignature)) {
                    return false;
                }else{
                    return true;
                }
            } catch (NoSuchAlgorithmException e) {
               e.printStackTrace();
            } catch (InvalidKeyException e) {
               e.printStackTrace();
            } catch (SignatureException e) {
               e.printStackTrace();
            }
        }catch(Exception e){
            e.printStackTrace();
        }
    
        return false;
    }
    
    static byte[] concat(byte[]...arrays)
    {
        // Determine the length of the result array
        int totalLength = 0;
        for (int i = 0; i < arrays.length; i++)
        {
            totalLength += arrays[i].length;
        }
    
        // create the result array
        byte[] result = new byte[totalLength];
    
        // copy the source arrays into the result array
        int currentIndex = 0;
        for (int i = 0; i < arrays.length; i++)
        {
            System.arraycopy(arrays[i], 0, result, currentIndex, arrays[i].length);
            currentIndex += arrays[i].length;
        }
    
        return result;
    }
    

    【讨论】:

      【解决方案2】:

      由于声誉低,我无法评论 chamnassi 的解决方案:chamnassi 的回答效果很好

      此外,还应添加以下检查:验证证书是否来自 Apple。快速而肮脏的解决方案是验证 URL 来自“apple.com”:

      // verify the URL: needs to have ".apple.com/" inside!
      String path = publicKeyUrl;
      path = path.substring(path.indexOf("://") + 3);  // cut protocol, e.g. "https://" from front
      path = path.substring(0, path.indexOf("/"));     // cut the URL-path part, so we only have something list "whatever.apple.com"!
      if (!path.toLowerCase().endsWith(".apple.com")) {
          // invalid certificate: not from Apple site!
          --> throw error
      }
      

      【讨论】:

        猜你喜欢
        • 2019-02-22
        • 2021-11-15
        • 2011-11-04
        • 1970-01-01
        • 1970-01-01
        • 2015-09-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多