Apple是否有任何文档涵盖用于生成- [GKLocalPlayer generateIdentityVerificationSignatureWithCompletionHandler:]
返回的文件的格式或算法?
我在SO上看到了关于验证用户的基本流程的few questions,这似乎表明该文件是.cer文件(application / pkix-cert),并且它使用DER文件格式,但我找不到Apple官方的任何内容。
我希望用Java验证证书,如果有人有任何例子,那么我也非常感激。
答案 0 :(得分:2)
[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:×tampBE 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];
}
}];
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;
}
答案 1 :(得分:0)
由于声誉不佳,我不能对chamnassi的解决方案发表评论:chamnassi的答案很有效
此外,还应添加以下检查:验证证书是否来自Apple。快速&amp;脏解决方案是验证URL源自&#34; apple.com&#34;:
// 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
}