gpt4 book ai didi

java - 如何使用 Java JDK 1.7 在我的第三方服务器上验证 GKLocalPlayer?

转载 作者:可可西里 更新时间:2023-11-01 04:46:46 25 4
gpt4 key购买 nike

使用Apple的Game Center认证验证步骤outlined here ,下面的验证逻辑是用Java实现的。然而,这总是失败。

import java.net.URL;

import java.nio.ByteBuffer;

import java.nio.ByteOrder;

import java.security.KeyPair;

import java.security.KeyPairGenerator;

import java.security.MessageDigest;

import java.security.PrivateKey;

import java.security.PublicKey;

import java.security.SecureRandom;

import java.security.Signature;

import java.security.cert.Certificate;

import java.security.cert.CertificateFactory;

import java.security.spec.AlgorithmParameterSpec;

import java.util.Arrays;

import javax.crypto.Cipher;

import javax.xml.bind.DatatypeConverter;

public class Verifier {

public static void main(String[] args) {

verify1();

}



public static void verify1() {

try {

byte[] playerID = "G:90082947".getBytes("UTF-8");

byte[] bundleID = "com.appledts.GameCenterSamples".getBytes("UTF-8");



long ts = 1392078336714L;

final ByteBuffer tsByteBuffer = ByteBuffer.allocate(8);

tsByteBuffer.order(ByteOrder.BIG_ENDIAN);

tsByteBuffer.putLong(ts);

byte[] timestamp = tsByteBuffer.array();



byte[] salt = DatatypeConverter.parseBase64Binary("xmvbZQ==");



byte[] sigToCheck = DatatypeConverter.parseBase64Binary("AmyNbm+7wJOjXv6GXI/vAEcl6gSX1AKxPr3GeExSYCiaxVaAeIvC23TWtp1/Vd/szfq1r1OzwrvkHeSSiskWMsMXaGQWUmiGtCnf9fqBU75T5PwNLCj4H9Nd5QENCMV/CFgVyGEi4X6Wlp18kqJPk/ooS6jLJwcWIe6DyrR1bQHl6YzKTfB4ACl2JEccBDz8dArKTrh4vFcQF4a+DtERm283Y2ue1DwG8lqWrYhsRO5v7vrW3lVpn5t25QXc+Y35zJ/il+lZJxKAgASwrKaq3G8RStdkeXCER23fSYhTmbLFqkFRWnmzu38hmLt5/iivUbm8NgELXP0SyQoYLMvfmA==");



ByteBuffer dataBuffer = ByteBuffer.allocate(playerID.length+bundleID.length+8+salt.length)

.put(playerID)

.put(bundleID)

.put(timestamp)

.put(salt);





Certificate cert = CertificateFactory.getInstance("X.509")

.generateCertificate(new URL("https://sandbox.gc.apple.com/public-key/gc-sb.cer").openConnection().getInputStream());





Signature sig = Signature.getInstance("SHA1withRSA");

sig.initVerify(cert);



sig.update(dataBuffer);



final boolean verify = sig.verify(sigToCheck);

System.out.println("signature verifies: " + verify);



} catch (Exception e) {

e.printStackTrace();

}

}

}

从 iOS 7 客户端向服务器传输数据时没有丢失位。这是通过将二进制位从 xCode 和 Java 写入一个文件,生成它们的十六进制,并查看是否有任何差异(注意,差异仅显示文件名差异)来验证的:

$ xxd -i salt_Java.txt salt_java.xxd

$ xxd -i salt_xcode.txt salt_xcode.xxd

$ xxd -i sigToCheck_Java.txt sigToCheck_java.xxd

$ xxd -i sigToCheck_xcode.txt sigToCheck_xcode.xxd

$ diff salt_java.xxd salt_xcode.xxd

1c1

< unsigned char salt_Java_txt[] = {

---

> unsigned char salt_xcode_txt[] = {

4c4

< unsigned int salt_Java_txt_len = 4;

---

> unsigned int salt_xcode_txt_len = 4;

$ diff sigToCheck_java.xxd sigToCheck_xcode.xxd

1c1

< unsigned char sigToCheck_Java_txt[] = {

---

> unsigned char sigToCheck_xcode_txt[] = {

25c25

< unsigned int sigToCheck_Java_txt_len = 256;

---

> unsigned int sigToCheck_xcode_txt_len = 256;

$

我认为这失败是因为底层 Java 库 Signature class使用,因为 Objective-C solution listed here似乎成功地验证了相同的凭据。

我的下一次尝试是使用 Java 的 [Cipher] 和 [MessageDigest] 库而不是 [Signature] 库,但这也失败了。我怀疑在使用提供的签名位检查签名摘要位之前还缺少其他步骤。

final MessageDigest md = MessageDigest.getInstance("SHA1");

byte[] digest = md.digest(dataBuffer.array());

// RSA decrypt

Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");

cipher.init(Cipher.DECRYPT_MODE, cert);

byte[] decrypted = cipher.doFinal(sigToCheck);



System.out.println("signature verifies: " + Arrays.equals(digest, decrypted));

是否有验证数字签名的替代方法或上面发布的解决方案中的任何漏洞?

最佳答案

问题似乎出在您传递给 Signature.update() 的 ByteBuffer 上。如果您通过更改传递底层数组

sig.update(dataBuffer);

sig.update(dataBuffer.array());

验证似乎成功了。基于the documentation for Signature.update(ByteBuffer) ,我怀疑这是因为它试图从您在缓冲区中写入的最后位置读取数据,但没有找到任何数据。

关于java - 如何使用 Java JDK 1.7 在我的第三方服务器上验证 GKLocalPlayer?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21888201/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com