我們把自己的程序發(fā)布到 app store,但是不能保證每一個用戶都是從 app store 下載官方 app,也不能保證每一個用戶都不越獄。 換句話說,我們無法保證程序運行環(huán)境在 MAC 管控策略下就絕對的安全。 所以,在有些情況下,尤其是和錢有關(guān)系的 app ,我們有必要在和服務(wù)器通信時,讓服務(wù)器知道客戶端到底是不是官方正版的 app 。
何以判斷自己是不是正版 app 呢? hackers 們破解你的 app ,無非就 2 個地方可以動,1 個是二進制,1 個是資源文件。
二進制都重新編譯過了自然肯定是盜版……
有些低級的 hackers 喜歡修改人家的資源文件然后貼上自己的廣告,或者給用戶錯誤的指引……修改資源文件是不需要重新編譯二進制的。
因此,我們有必要在敏感的請求報文中,增加正版應(yīng)用的二進制和資源文件的標(biāo)識,讓服務(wù)器知道,此請求是否來自正版的未經(jīng)修改的 app 。 在沙盒中,我們可以讀到自己程序的二進制,也可以讀到資源文件簽名文件,這兩個文件都不算大,我們可以對其取 md5 值然后以某種組合算法得到一個標(biāo)記字符串,然后發(fā)給服務(wù)器。
我封裝了相關(guān)文件的讀取地址
@implementation WQPathUtilities
+ (NSString *)directory:(NSSearchPathDirectory)dir
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(dir, NSUserDomainMask, YES);
NSString *dirStr = [paths objectAtIndex:0];
return dirStr;
}
+ (NSString *)documentsDirectory
{
return [WQPathUtilities directory:NSDocumentDirectory];
}
+ (NSString *)cachesDirectory
{
return [WQPathUtilities directory:NSCachesDirectory];
}
+ (NSString *)tmpDirectory
{
return NSTemporaryDirectory();
}
+ (NSString *)homeDirectory
{
return NSHomeDirectory();
}
+ (NSString *)codeResourcesPath
{
NSString *excutableName = [[NSBundle mainBundle] infoDictionary][@"CFBundleExecutable"];
NSString *tmpPath = [[WQPathUtilities documentsDirectory] stringByDeletingLastPathComponent];
NSString *appPath = [[tmpPath stringByAppendingPathComponent:excutableName]
stringByAppendingPathExtension:@"app"];
NSString *sigPath = [[appPath stringByAppendingPathComponent:@"_CodeSignature"]
stringByAppendingPathComponent:@"CodeResources"];
return sigPath;
}
+ (NSString *)binaryPath
{
NSString *excutableName = [[NSBundle mainBundle] infoDictionary][@"CFBundleExecutable"];
NSString *tmpPath = [[WQPathUtilities documentsDirectory] stringByDeletingLastPathComponent];
NSString *appPath = [[tmpPath stringByAppendingPathComponent:excutableName]
stringByAppendingPathExtension:@"app"];
NSString *binaryPath = [appPath stringByAppendingPathComponent:excutableName];
return binaryPath;
}
@end
#import "CommonCrypto/CommonDigest.h"
+(NSString *)md5WithString:(NSString *)string
{
const charchar *cStr = [string UTF8String];
unsigned char result[CC_MD5_DIGEST_LENGTH];
CC_MD5(cStr, strlen(cStr), result);
return [[NSString stringWithFormat:@"%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",
result[0], result[1], result[2], result[3],
result[4], result[5], result[6], result[7],
result[8], result[9], result[10], result[11],
result[12], result[13], result[14], result[15]
] lowercaseString];
}
這樣做就 100% 安全了嗎?
答案是:不……
所謂魔高一尺,道高一丈,不過也能阻止一些低級的 hack 手段了~