一键加密
资源加密可以极大提升过审率,完美解决资源文件被标记问题。
工具对文件进行加密以及生成解密代码,具体解密逻辑需要自行实现!!!
工具对文件进行加密以及生成解密代码,具体解密逻辑需要自行实现!!!
工具对文件进行加密以及生成解密代码,具体解密逻辑需要自行实现!!!
解密
加密后,会在加密目录生成解密代码文件。需要根据项目自行对文件进行解密处理。
如果加密了 mainBundle 的 png 图片,需要在Xcode -> build settings 把 STRIP_PNG_TEXT 和 COMPRESS_PNG_FILES 设置为NO,否则Xcode会自动把加密后的png图片优化
解密流程
- 把读取资源的逻辑封装到一个函数,方便批量处理
- 如果开启了文件名混淆,需要先还原文件名,注意修改文件名不会修改文件名后缀
- 加载已加密文件data,通过解密函数解密data
- 通过data读取资源
解密文件代码
解密文件包含解密data的函数,如果开启了文件名混淆,则会多2个还原文件名的函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14
|
+ (NSString *)encryptName:(NSString *)name;
+ (NSString *)decryptName:(NSString *)name;
+ (NSData *)decryptData:(NSData *)data;
|
解密示例
比如原本加载图片的代码
1 2
| NSString *path = [[NSBundle mainBundle] pathForResource:@"person" ofType:@"png"]; _imageView.image = [UIImage imageWithContentsOfFile:path];
|
经过加密后需要通过解密data读取图片
1 2 3 4
| NSString *path = [[NSBundle mainBundle] pathForResource:@"person" ofType:@"png"]; NSData *data = [NSData dataWithContentsOfFile:path]; NSData *decryptData = [DecryptManager decryptData:data]; _imageView.image = [UIImage imageWithData:decryptData];
|
上面只是示例,最好是封装成函数,传入文件路径或文件名,返回解密后data,再通过data加载资源
文件名混淆
开启会修改所选文件的文件名(不修改文件后缀),生成文件名映射文件,映射文件也会经过加密处理,映射文件只保存文件名的映射规则,不包含后缀,注意需要处理加密目录内的映射文件路径
混淆出来的文件名来自于大量AppStore线上应用统计出来的最常用文件名,同时经过差异化处理
还原文件名示例
直接还原
1 2
| NSString *path = [[NSBundle mainBundle] pathForResource:@"person" ofType:@"png"]; _imageView.image = [UIImage imageWithContentsOfFile:path];
|
通过混淆前文件名,获取混淆后文件名再读取
1 2 3 4 5
| NSString *name = [DecryptManager encryptName:@"person"]; NSString *path = [[NSBundle mainBundle] pathForResource:name ofType:@"png"]; NSData *data = [NSData dataWithContentsOfFile:path]; NSData *decryptData = [DecryptManager decryptData:data]; _imageView.image = [UIImage imageWithData:decryptData];
|
整个目录还原
比如说我们对 res 目录所有文件进行了加密并混淆文件名,那么可以先把整个目录解密到app(比如 Document),同时还原文件名,只需要在读取的时候改变读取的目录即可
原本加载res目录内资源的代码
1 2 3
| NSString *dir = [[NSBundle mainBundle] pathForResource:@"res" ofType:@""]; NSString *path = [dir stringByAppendingPathComponent:@"person.png"]; _imageView.image = [UIImage imageWithContentsOfFile:path];
|
1.首次启动先把res目录解密到Document同时还原文件名
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| - (void)decryptDir { NSString *dir = [[NSBundle mainBundle] pathForResource:@"res" ofType:@""]; NSArray *subFiles = [[NSFileManager defaultManager] subpathsAtPath:dir]; NSString *toDir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject stringByAppendingPathComponent:@"res"]; [[NSFileManager defaultManager] createDirectoryAtPath:toDir withIntermediateDirectories:YES attributes:nil error:nil]; for (NSString *subFile in subFiles) { NSString *path = [dir stringByAppendingPathComponent:subFile]; NSString *name = path.lastPathComponent.stringByDeletingPathExtension; NSString *toName = [DecryptManager decryptName:name]; NSString *subDir = toDir; NSString *midDir = [subFile stringByDeletingLastPathComponent]; if (midDir.length > 0) { subDir = [subDir stringByAppendingPathComponent:midDir]; if (![[NSFileManager defaultManager] fileExistsAtPath:subDir]) { [[NSFileManager defaultManager] createDirectoryAtPath:subDir withIntermediateDirectories:YES attributes:nil error:nil]; } } NSString *toPath = [[subDir stringByAppendingPathComponent:toName] stringByAppendingPathExtension:path.pathExtension]; NSData *data = [NSData dataWithContentsOfFile:path]; NSData *descryptData = [DecryptManager decryptData:data]; [descryptData writeToFile:toPath atomically:YES]; } }
|
2.读取解密后的文件
1 2 3
| NSString *dir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject stringByAppendingPathComponent:@"res"]; NSString *path = [dir stringByAppendingPathComponent:@"person.png"]; _imageView.image = [UIImage imageWithContentsOfFile:path];
|
选择最合适的方式
解密和还原文件名等操作具体选择哪种方式需要根据项目来决定,同时需要注意解密文件的耗时,具体解密的逻辑可以根据项目自行优化