mirror of
https://github.com/moonlight-stream/moonlight-ios.git
synced 2026-02-16 02:20:53 +00:00
Implement pairing for Gen 7 servers
This commit is contained in:
@@ -17,8 +17,10 @@
|
||||
+ (NSData*) getSignatureFromCert:(NSData*)cert;
|
||||
+ (NSData*) nullTerminateString:(NSData*)data;
|
||||
|
||||
- (NSData*) createAESKeyFromSalt:(NSData*)saltedPIN;
|
||||
- (NSData*) createAESKeyFromSaltSHA1:(NSData*)saltedPIN;
|
||||
- (NSData*) createAESKeyFromSaltSHA256:(NSData*)saltedPIN;
|
||||
- (NSData*) SHA1HashData:(NSData*)data;
|
||||
- (NSData*) SHA256HashData:(NSData*)data;
|
||||
- (NSData*) aesEncrypt:(NSData*)data withKey:(NSData*)key;
|
||||
- (NSData*) aesDecrypt:(NSData*)data withKey:(NSData*)key;
|
||||
- (bool) verifySignature:(NSData *)data withSignature:(NSData*)signature andCert:(NSData*)cert;
|
||||
|
||||
@@ -16,19 +16,31 @@
|
||||
#include <openssl/evp.h>
|
||||
|
||||
@implementation CryptoManager
|
||||
static const int SHA1_DIGEST_LENGTH = 20;
|
||||
static const int SHA1_HASH_LENGTH = 20;
|
||||
static const int SHA256_HASH_LENGTH = 32;
|
||||
static NSData* key = nil;
|
||||
static NSData* cert = nil;
|
||||
static NSData* p12 = nil;
|
||||
|
||||
- (NSData*) createAESKeyFromSalt:(NSData*)saltedPIN {
|
||||
- (NSData*) createAESKeyFromSaltSHA1:(NSData*)saltedPIN {
|
||||
return [[self SHA1HashData:saltedPIN] subdataWithRange:NSMakeRange(0, 16)];
|
||||
}
|
||||
|
||||
- (NSData*) createAESKeyFromSaltSHA256:(NSData*)saltedPIN {
|
||||
return [[self SHA256HashData:saltedPIN] subdataWithRange:NSMakeRange(0, 16)];
|
||||
}
|
||||
|
||||
- (NSData*) SHA1HashData:(NSData*)data {
|
||||
unsigned char sha1[SHA1_DIGEST_LENGTH];
|
||||
unsigned char sha1[SHA1_HASH_LENGTH];
|
||||
SHA1([data bytes], [data length], sha1);
|
||||
NSData* bytes = [NSData dataWithBytes:sha1 length:20];
|
||||
NSData* bytes = [NSData dataWithBytes:sha1 length:sizeof(sha1)];
|
||||
return bytes;
|
||||
}
|
||||
|
||||
- (NSData*) SHA256HashData:(NSData*)data {
|
||||
unsigned char sha256[SHA256_HASH_LENGTH];
|
||||
SHA256([data bytes], [data length], sha256);
|
||||
NSData* bytes = [NSData dataWithBytes:sha256 length:sizeof(sha256)];
|
||||
return bytes;
|
||||
}
|
||||
|
||||
|
||||
@@ -22,6 +22,6 @@
|
||||
- (id) initWithManager:(HttpManager*)httpManager andCert:(NSData*)cert callback:(id<PairCallback>)callback;
|
||||
- (NSString*) generatePIN;
|
||||
- (NSData*) saltPIN:(NSString*)PIN;
|
||||
- (void) initiatePair;
|
||||
- (void) initiatePair:(int)serverMajorVersion;
|
||||
|
||||
@end
|
||||
|
||||
@@ -41,14 +41,21 @@
|
||||
if (![[serverInfoResp getStringTag:@"state"] hasSuffix:@"_SERVER_AVAILABLE"]) {
|
||||
[_callback pairFailed:@"You must stop streaming before attempting to pair."];
|
||||
} else if (![[serverInfoResp getStringTag:@"PairStatus"] isEqual:@"1"]) {
|
||||
[self initiatePair];
|
||||
NSString* appversion = [serverInfoResp getStringTag:@"appversion"];
|
||||
if (appversion == nil) {
|
||||
[_callback pairFailed:@"Missing XML element"];
|
||||
return;
|
||||
}
|
||||
[self initiatePair: [[appversion substringToIndex:1] intValue]];
|
||||
} else {
|
||||
[_callback alreadyPaired];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void) initiatePair {
|
||||
- (void) initiatePair:(int)serverMajorVersion {
|
||||
Log(LOG_I, @"Pairing with generation %d server", serverMajorVersion);
|
||||
|
||||
NSString* PIN = [self generatePIN];
|
||||
NSData* salt = [self saltPIN:PIN];
|
||||
Log(LOG_I, @"PIN: %@, saltedPIN: %@", PIN, salt);
|
||||
@@ -69,7 +76,18 @@
|
||||
NSString* plainCert = [pairResp getStringTag:@"plaincert"];
|
||||
|
||||
CryptoManager* cryptoMan = [[CryptoManager alloc] init];
|
||||
NSData* aesKey = [cryptoMan createAESKeyFromSalt:salt];
|
||||
NSData* aesKey;
|
||||
|
||||
// Gen 7 servers use SHA256 to get the key
|
||||
int hashLength;
|
||||
if (serverMajorVersion >= 7) {
|
||||
aesKey = [cryptoMan createAESKeyFromSaltSHA256:salt];
|
||||
hashLength = 32;
|
||||
}
|
||||
else {
|
||||
aesKey = [cryptoMan createAESKeyFromSaltSHA1:salt];
|
||||
hashLength = 20;
|
||||
}
|
||||
|
||||
NSData* randomChallenge = [Utils randomBytes:16];
|
||||
NSData* encryptedChallenge = [cryptoMan aesEncrypt:randomChallenge withKey:aesKey];
|
||||
@@ -88,11 +106,18 @@
|
||||
NSData* encServerChallengeResp = [Utils hexToBytes:[challengeResp getStringTag:@"challengeresponse"]];
|
||||
NSData* decServerChallengeResp = [cryptoMan aesDecrypt:encServerChallengeResp withKey:aesKey];
|
||||
|
||||
NSData* serverResponse = [decServerChallengeResp subdataWithRange:NSMakeRange(0, 20)];
|
||||
NSData* serverChallenge = [decServerChallengeResp subdataWithRange:NSMakeRange(20, 16)];
|
||||
NSData* serverResponse = [decServerChallengeResp subdataWithRange:NSMakeRange(0, hashLength)];
|
||||
NSData* serverChallenge = [decServerChallengeResp subdataWithRange:NSMakeRange(hashLength, 16)];
|
||||
|
||||
NSData* clientSecret = [Utils randomBytes:16];
|
||||
NSData* challengeRespHash = [cryptoMan SHA1HashData:[self concatData:[self concatData:serverChallenge with:[CryptoManager getSignatureFromCert:_cert]] with:clientSecret]];
|
||||
NSData* challengeRespHashInput = [self concatData:[self concatData:serverChallenge with:[CryptoManager getSignatureFromCert:_cert]] with:clientSecret];
|
||||
NSData* challengeRespHash;
|
||||
if (serverMajorVersion >= 7) {
|
||||
challengeRespHash = [cryptoMan SHA256HashData: challengeRespHashInput];
|
||||
}
|
||||
else {
|
||||
challengeRespHash = [cryptoMan SHA1HashData: challengeRespHashInput];
|
||||
}
|
||||
NSData* challengeRespEncrypted = [cryptoMan aesEncrypt:challengeRespHash withKey:aesKey];
|
||||
|
||||
HttpResponse* secretResp = [[HttpResponse alloc] init];
|
||||
@@ -116,7 +141,14 @@
|
||||
return;
|
||||
}
|
||||
|
||||
NSData* serverChallengeRespHash = [cryptoMan SHA1HashData:[self concatData:[self concatData:randomChallenge with:[CryptoManager getSignatureFromCert:[Utils hexToBytes:plainCert]]] with:serverSecret]];
|
||||
NSData* serverChallengeRespHashInput = [self concatData:[self concatData:randomChallenge with:[CryptoManager getSignatureFromCert:[Utils hexToBytes:plainCert]]] with:serverSecret];
|
||||
NSData* serverChallengeRespHash;
|
||||
if (serverMajorVersion >= 7) {
|
||||
serverChallengeRespHash = [cryptoMan SHA256HashData: serverChallengeRespHashInput];
|
||||
}
|
||||
else {
|
||||
serverChallengeRespHash = [cryptoMan SHA1HashData: serverChallengeRespHashInput];
|
||||
}
|
||||
if (![serverChallengeRespHash isEqual:serverResponse]) {
|
||||
[_httpManager executeRequestSynchronously:[HttpRequest requestWithUrlRequest:[_httpManager newUnpairRequest]]];
|
||||
[_callback pairFailed:@"Incorrect PIN"];
|
||||
|
||||
Reference in New Issue
Block a user