iOS開發(fā)-----Userdefault 真的安全?

NSuserdefaults 是一種IOS常用的數(shù)據(jù)持久化的方式,操作簡便,配合NSCoding 和NSKeyedArchiver,很容易將數(shù)據(jù)model轉(zhuǎn)化成NSData直接存儲(chǔ)在NSuserdefaults。那使用NSuserdefaults保存數(shù)據(jù),數(shù)據(jù)的安全性如何呢?

NSuserdefaults 的本質(zhì)是使用了plist存儲(chǔ)數(shù)據(jù),將存儲(chǔ)在NSuserdefaults中的數(shù)據(jù)寫入了一個(gè)以Bundle Identifier的plist中。
下面是一個(gè)簡單的例子。
<pre>
@interface TestInfo : NSObject<NSCoding>
@property (nonatomic,retain) NSString *username;
@property (nonatomic,retain) NSString *phone;
@property (nonatomic,retain) NSString *ticket;
@property (nonatomic,retain) NSString *email;
@property (nonatomic,retain) NSString *passport;
//混淆
@property (nonatomic,retain) NSString *uiofdsaouiSHJ;
@property (nonatomic,assign) BOOL isLGBT;
@property (nonatomic,retain) NSNumber *age;
-(void)saveLoginInfo;
@end

@implementation TestInfo
-(id)initWithCoder:(NSCoder *)aDecoder{
if (self=[self init]) {
self.username=[aDecoder decodeObjectForKey:@"username"];
self.uiofdsaouiSHJ=[aDecoder decodeObjectForKey:@"uiofdsaouiSHJ"];
self.phone = [aDecoder decodeObjectForKey:@"phone"];
self.email = [aDecoder decodeObjectForKey:@"email"];
self.passport = [aDecoder decodeObjectForKey:@"passport"];
self.ticket = [aDecoder decodeObjectForKey:@"ticket"];
self.isLGBT = [[aDecoder decodeObjectForKey:@"passport"] boolValue];
self.age = [aDecoder decodeObjectForKey:@"ticket"];
}
return self;
}
-(void)encodeWithCoder:(NSCoder *)aCoder{
[aCoder encodeObject:_username forKey:@"username"];
[aCoder encodeObject:_uiofdsaouiSHJ forKey:@"uiofdsaouiSHJ"];
[aCoder encodeObject:_phone forKey:@"phone"];
[aCoder encodeObject:_email forKey:@"email"];
[aCoder encodeObject:_passport forKey:@"passport"];
[aCoder encodeObject:_ticket forKey:@"ticket"];
[aCoder encodeObject:[NSNumber numberWithBool:_isLGBT] forKey:@"isLGBT"];
[aCoder encodeObject:_age forKey:@"age"];
}
-(void)saveLoginInfo{

NSUserDefaults *cache=[NSUserDefaults standardUserDefaults];

NSString *gameKeyStr = [NSString stringWithFormat:@"CC_userinfos"];
NSData *logininfo=[NSKeyedArchiver archivedDataWithRootObject:self];
NSMutableArray *array = [[NSMutableArray alloc] init];
[array addObject:logininfo];

[cache setObject:array forKey:gameKeyStr];

}
@end
</pre>

當(dāng)打開plist時(shí),可以看到存儲(chǔ)下來的數(shù)據(jù)按照 NSuserdefaults 寫入的數(shù)據(jù)類型被保存下來。
NSuserdefaults 數(shù)據(jù)保存安全性[黑科技分析]

其中在例子代碼中使用saveLoginInfo保存的數(shù)據(jù),如下所示。看是在plist中保存時(shí)二進(jìn)制的數(shù)據(jù),那么此段數(shù)據(jù)是否很容易被破解呢?

<62706c69 73743030 d4010203 04050623 24582476 65727369 6f6e5824 6f626a65 63747359 24617263 68697665 72542474 6f701200 0186a0ab 07080f0d 0910110a 1b1c1d55 246e756c 6cd9090a 0b0c0d0e 0f101112 13141516 1718191a 5570686f 6e655674 69636b65 74566973 4c474254 5624636c 6173735d 75696f66 6473616f 75695348 4a536167 65587573 65726e61 6d655565 6d61696c 58706173 73706f72 74800480 07800880 0a800380 09800280 05800609 1017d21e 1f20215a 24636c61 73736e61 6d655824 636c6173 73657358 54657374 496e666f a2202258 4e534f62 6a656374 5f100f4e 534b6579 65644172 63686976 6572d125 2654726f 6f748001 00080011 001a0023 002d0032 00370043 0049005c 00620069 00700077 00850089 00920098 00a100a3 00a500a7 00a900ab 00ad00af 00b100b3 00b400b6 00bb00c6 00cf00d8 00db00e4 00f600f9 00fe0000 00000000 02010000 00000000 00270000 00000000 00000000 00000000 0100>
按照encodeWithCoder來說,NSObject使用了NSCoder進(jìn)行了encode。按照道理講,在不知道類參數(shù)的情況下,是無法從這一段二進(jìn)制數(shù)據(jù)中恢復(fù)出原來被加密的數(shù)據(jù)。

但是實(shí)際操作會(huì)是如何呢?假設(shè)在只拿到這個(gè)plist文件,不知道TestInfo情況下。進(jìn)行逐步分析。

<pre>
NSString *infoPath = [[NSBundle mainBundle] pathForResource:@"Info" ofType:@"plist"];
NSMutableDictionary *data = [[NSMutableDictionary alloc] initWithContentsOfFile:infoPath];
NSArray *cachearray=[data objectForKey:@"CC_userinfos"];

if (cachearray) {
    for (int i=0; i<cachearray.count; i++) {
        NSData *data=[cachearray objectAtIndex:i];

        NSString *logininfo=[NSKeyedUnarchiver unarchiveObjectWithData:data];


    }
}

</pre>

首先將plist數(shù)據(jù)復(fù)制到info.plist中,讀入內(nèi)存轉(zhuǎn)化為NSData,因?yàn)椴恢罃?shù)據(jù)從什么類型轉(zhuǎn)化來的,就先用NSString作為數(shù)據(jù)類型。

<pre>
NSString *logininfo=[NSKeyedUnarchiver unarchiveObjectWithData:data];
</pre>

不出意味,因?yàn)轭愋筒黄ヅ洌瑘?bào)錯(cuò),我是特意新建沒有這個(gè)mode 的項(xiàng)目(從逆向的角度出發(fā)) 可以知道是一個(gè) 叫TestInfo 的對(duì)象

<pre>
2016-05-05 20:02:03.260 NSUserDefaultsDataSaveDemo[48761:1143922] *** Terminating app due to uncaught exception 'NSInvalidUnarchiveOperationException', reason: '*** -[NSKeyedUnarchiver decodeObjectForKey:]: cannot decode object of class (TestInfo) for key (root); the class may be defined in source code or a library that is not linked'
</pre>

把這段數(shù)據(jù)編碼為NSString會(huì)怎么樣?

<pre>
NSString *str =[[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];
NSLog(@"%@",str);
</pre>

<pre>
2016-05-05 20:11:05.130 NSUserDefaultsDataSaveDemo[48898:1151203] bplist00???????&'T$topX$objectsX$versionY$archiver???Troot€??
??
?????U$nullù?
???????????????XpassportVticketUphoneSage]uiofdsaouiSHJV$classUemailVisLGBTXusername
</pre>
因?yàn)镺C語言的特點(diǎn),參數(shù)命名上講究可讀性,所以在這段NSSting中大概可以猜出TestInfo的若干屬性(大寫字母分隔),如passport、ticket、phone、age、email、username。
[uiofdsaouiSHJ、isLGBT]是我故意寫的兩個(gè)命名不規(guī)范的屬性。

大概猜出屬性的名字后,重新initWithCoder方法,便得到TestInfo的明文。

因?yàn)閷?duì)NSuserdefaults保存數(shù)據(jù)有疑慮,做了以上的試驗(yàn)。證明了NSuserdefaults數(shù)據(jù)保存安全性差,在使用encodeObject之前,需要使用自己的加密算法進(jìn)行加密,即使被分析出類后,也不至于讀出明文數(shù)據(jù)。

例子代碼https://github.com/kaka2928/NSUserDefaultsDataSaveDemo

以上就是NSuserdefaults 數(shù)據(jù)保存安全性的全文介紹,希望對(duì)您學(xué)習(xí)和使用ios應(yīng)用開發(fā)有所幫助.

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容