|
15 | 15 | // |
16 | 16 |
|
17 | 17 | #import "GTXAnalyticsUtils.h" |
| 18 | +#import "GTXAssertions.h" |
18 | 19 | #import "GTXLogging.h" |
19 | 20 |
|
20 | 21 | #import <CommonCrypto/CommonDigest.h> |
|
28 | 29 |
|
29 | 30 | @implementation GTXAnalyticsUtils |
30 | 31 |
|
31 | | -/** |
32 | | - @return The clientID to be used by GTXiLib analytics, this is a hash of App's bundle ID. |
33 | | - */ |
| 32 | ++ (NSString *)clientIDForBundleID:(NSString *)bundleID { |
| 33 | + // Get SHA256 value of the given string. |
| 34 | + unsigned char sha256Value[CC_SHA256_DIGEST_LENGTH]; |
| 35 | + const char *stringCPtr = [bundleID UTF8String]; |
| 36 | + CC_SHA256(stringCPtr, (CC_LONG)strlen(stringCPtr), sha256Value); |
| 37 | + |
| 38 | + // Parse SHA256 value into individual hex values. Note that Google Analytics client ID must be |
| 39 | + // 128bits long, but SHA256 is 256 bits and there is no standard way to compress hashes, in our |
| 40 | + // case we use bitwise XOR of the two 128 bit hashes inside the 256 bit hash to produce a 128bit |
| 41 | + // hash. |
| 42 | + NSMutableString *stringWithHexValues = [[NSMutableString alloc] init]; |
| 43 | + const NSInteger kClientIDSize = 16; |
| 44 | + GTX_ASSERT(kClientIDSize * 2 == CC_SHA256_DIGEST_LENGTH, |
| 45 | + @"CC_SHA256_DIGEST_LENGTH must be 32 it was %d", (int)CC_SHA256_DIGEST_LENGTH); |
| 46 | + for (int i = 0; i < kClientIDSize; i++) { |
| 47 | + [stringWithHexValues appendFormat:@"%02x", sha256Value[i] ^ sha256Value[kClientIDSize + i]]; |
| 48 | + } |
| 49 | + return stringWithHexValues; |
| 50 | +} |
| 51 | + |
34 | 52 | + (NSString *)clientID { |
35 | 53 | static NSString *clientID; |
36 | 54 | static dispatch_once_t onceToken; |
37 | 55 | dispatch_once(&onceToken, ^{ |
38 | | - NSString *bundleIDMD5 = [[NSBundle mainBundle] bundleIdentifier]; |
39 | | - if (!bundleIDMD5) { |
| 56 | + NSString *bundleID = [[NSBundle mainBundle] bundleIdentifier]; |
| 57 | + if (!bundleID) { |
40 | 58 | // If bundle ID is not available we use a placeholder. |
41 | | - bundleIDMD5 = @"<Missing Bundle ID>"; |
| 59 | + bundleID = @"<Missing Bundle ID>"; |
42 | 60 | } |
43 | 61 |
|
44 | | - // Get MD5 value of the given string. |
45 | | - unsigned char md5Value[CC_MD5_DIGEST_LENGTH]; |
46 | | - const char *stringCPtr = [bundleIDMD5 UTF8String]; |
47 | | - CC_MD5(stringCPtr, (CC_LONG)strlen(stringCPtr), md5Value); |
48 | | - |
49 | | - // Parse MD5 value into individual hex values. |
50 | | - NSMutableString *stringWithHexMd5Values = [[NSMutableString alloc] init]; |
51 | | - for (int i = 0; i < CC_MD5_DIGEST_LENGTH; i++) { |
52 | | - [stringWithHexMd5Values appendFormat:@"%02x", md5Value[i]]; |
53 | | - } |
54 | | - clientID = [stringWithHexMd5Values copy]; |
| 62 | + clientID = [self clientIDForBundleID:bundleID]; |
55 | 63 | }); |
56 | 64 |
|
57 | 65 | return clientID; |
|
0 commit comments