NSuserdefaults 数据保存安全性[黑科技分析]

NSuserdefaults 是一种IOS常用的数据持久化的方式,操作简便,配合NSCoding 和NSKeyedArchiver,很容易将数据model转化成NSData直接存储在NSuserdefaults。那使用NSuserdefaults保存数据,数据的安全性如何呢?

NSuserdefaults 的本质是使用了plist存储数据,将存储在NSuserdefaults中的数据写入了一个以Bundle Identifier的plist中。

下面是一个简单的例子。

@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

当打开plist时,可以看到存储下来的数据按照 NSuserdefaults 写入的数据类型被保存下来。

其中在例子代码中使用saveLoginInfo保存的数据,如下所示。看是在plist中保存时二进制的数据,那么此段数据是否很容易被破解呢?

<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进行了encode。按照道理讲,在不知道类参数的情况下,是无法从这一段二进制数据中恢复出原来被加密的数据。

但是实际操作会是如何呢?假设在只拿到这个plist文件,不知道TestInfo情况下。进行逐步分析。

    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];

        }
    }

首先将plist数据复制到info.plist中,读入内存转化为NSData,因为不知道数据从什么类型转化来的,就先用NSString作为数据类型。

NSString *logininfo=[NSKeyedUnarchiver unarchiveObjectWithData:data];

不出意味,因为类型不匹配,报错,但是从出错信息中,可以看出原来这段数据的类型为TestInfo。

2016-05-05 20:02:03.260 PanNaviControllerDemo[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‘

把这段数据编码为NSString会怎么样?

            NSString *str =[[NSString alloc] initWithData:data   encoding:NSASCIIStringEncoding];
            NSLog(@"%@",str);
2016-05-05 20:11:05.130 NSUserDefaultsDataSaveDemo[48898:1151203] bplist00?&‘T$topX$objectsX$versionY$archiver?Troot€?   

U$nullù
XpassportVticketUphoneSage]uiofdsaouiSHJV$classUemailVisLGBTXusername

因为OC语言的特点,参数命名上讲究可读性,所以在这段NSSting中大概可以猜出TestInfo的若干属性(大写字母分隔),如passport、ticket、phone、age、email、username。

[uiofdsaouiSHJ、isLGBT]是我故意写的两个命名不规范的属性。

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

因为对NSuserdefaults保存数据有疑虑,做了以上的试验。证明了NSuserdefaults数据保存安全性差,在使用encodeObject之前,需要使用自己的加密算法进行加密,即使被分析出类后,也不至于读出明文数据。

例子代码

时间: 2024-08-27 07:09:54

NSuserdefaults 数据保存安全性[黑科技分析]的相关文章

4大特点解析华为云数据湖“黑科技”

4大特点解析华为云数据湖"黑科技"如果有人问数据湖是什么,我会告诉他们,是"桶装水"的集合.随着企业业务的发展,数据出现井喷,数据量呈几何增长,数据来源和类型更加多元化.传统数据仓库就如同"桶装水商店",已经承载不了全部水体,因此需要一个可以满足存储需求的,新的架构作为大数据的支撑.这就是数据湖.它汇聚不同数据源的溪流,包括大量无序的非结构化数据(文本.图像.声音.网页等).我们把它倒入数据湖,然后开始探索该数据.我们希望这是一个包含所有数据的,

[分享黑科技]纯js突破localstorage存储上线,远程抓取图片,并转码base64保存本地,最终实现整个网站所有静态资源离线到用户手机效果却不依赖浏览器的缓存机制,单页应用最新黑科技

好久没有写博客了,想到2年前答应要放出源代码的也没放出来,最近终于有空先把纯js实现无限空间大小的本地存储的功能开源了,项目地址https://github.com/xueduany/localstore,demo见http://xueduany.github.io/localstore/,下面给大家简单说说大概原理,具体细节和异常处理后面有机会在单独说 先说下突破本地localStorage的原理,官方原话是这么说的http://www.w3.org/TR/2013/PR-webstorage

android黑科技系列——Wireshark和Fiddler分析Android中的TLS协议包数据(附带案例样本)

一.前言 在之前一篇文章已经介绍了一款网络访问软件的破解教程,当时采用的突破口是应用程序本身的一个漏洞,就是没有关闭日志信息,我们通过抓取日志获取到关键信息来找到突破口进行破解的.那篇文章也说到了,如果这个app应用没有日志信息,我们该怎么办呢?那么这时候就需要采用抓包来寻找突破口了. 二.安装Fiddler证书 我们通过Fiddler连接手机进行抓包查看,应用访问数据信息都是用的HTTPS协议,也就是加密的数据,我们可能无法查看,比较麻烦,本文就来讲解如何查看这些加密数据了. 首先我们知道Fi

dedecms新建内容模型“把数据保存到数据库附加表时出错‘xxx’出错”错误的原因分析和解决方案(转)

把数据保存到数据库附加表 `bc_addonarticle17` 时出错,请把相关信息提交给DedeCms官方.INSERT INTO `bc_addonarticle17`(aid,typeid,redirecturl,templet,userip,body, ) Values( 11 , 11 , , , 127 0 0 1, )You have an error in your 今天在使用dedecms之梦系统进行建站的时候,使用新创建的自定义内容模型来添加文章的时候出现了错误,错误描述如

今年黑科技趋势最具的五个看点

CES 2017年人工智能引爆全球最火黑科技盛会 CES 2017 1月5日-8日在美国拉斯维加斯举行,数千家企业.几十万人将参与到这次科技的狂欢秀中.本文为埃森哲技术总监带来的关于本年度CES 的5大看点.他认为:人工智能将统治本年度的CES,变得无处不在.另外,他还分析了智能助理.物联网安全.虚拟现实等多个领域在本届大会上的表现. 2017 年国际消费电子展(CES 2017)将于1月5号拉开帷幕,在这个荒漠之城举办为期5天的展会,保守估计会吸引超过177000名参会者. 这也是一年之中唯一

【转载】史上最全:TensorFlow 好玩的技术、应用和你不知道的黑科技

[导读]TensorFlow 在 2015 年年底一出现就受到了极大的关注,经过一年多的发展,已经成为了在机器学习.深度学习项目中最受欢迎的框架之一.自发布以来,TensorFlow 不断在完善并增加新功能,直到在这次大会上发布了稳定版本的 TensorFlow V1.0.这次是谷歌第一次举办的TensorFlow开发者和爱好者大会,我们从主题演讲.有趣应用.技术生态.移动端和嵌入式应用多方面总结这次大会上的Submit,希望能对TensorFlow开发者有所帮助. TensorFlow:面向大

[黑科技]常数优化的一些技巧

感谢wys和小火车普及这些技巧qwq 这篇文章大概没什么营养 我们来看一道十分简单的题目: 设n=131072,输入两个长度为n的数列和,要求输出一个长度为n的数列. 其中,. 首先我们来讲讲这题怎么做. 如果数据是随机的,那么有一种神奇的做法:在a和b中分别挑出最大的p个元素,对于每个i暴力枚举每个p进行更新,这样的复杂度是O(np)的,正确性我不会分析= = 那么数据不是随机的...那么估计没有什么快速的算法,不如暴力! 以下的运行时间均为在我的渣渣笔记本中测试得到,仅供参考.测试环境Ubu

Android黑科技,读取用户短信+修改系统短信数据库

安卓系统比起ios系统最大的缺点,相信大家都知道,就是系统安全问题.这篇博客就秀一波“黑科技”. 读取用户短信 Android应用能读取用户手机上的短信,相信已经不是什么新鲜事,比如我们收到的短信验证码,一些app马上就能自动获取并填上验证码,省去我们手动填写验证码.原理就是通过Android的ContentProvider组件间接访问系统的短信数据库,获取所有短信内容.下面来演示一下. 布局很简单,如下: 代码如下: public class MainActivity extends Acti

【学习总结】iOS 数据保存几种方式总结

在iOS开发过程中,不管是做什么应用,都会碰到数据保存的问题.将数据保存到本地,能够让程序的运行更加流畅,不会出现让人厌恶的菊花形状,使得用户体验更好.下面介绍一下数据保存的方式: NSKeyedArchiver:采用归档的形式来保存数据,该数据对象需要遵守NSCoding协议,并且该对象对应的类必须提供encodeWithCoder:和initWithCoder:方法.前一个方法告诉系统怎么对对象进行编码,而后一个方法则是告诉系统怎么对对象进行解码. NSUserDefaults:用来保存应用