下载
一键加密
资源加密可以极大提升过审率,完美解决资源文件被标记问题。
工具对文件进行加密以及生成解密代码,具体解密逻辑需要自行实现!!!
工具对文件进行加密以及生成解密代码,具体解密逻辑需要自行实现!!!
工具对文件进行加密以及生成解密代码,具体解密逻辑需要自行实现!!!
解密
加密后,会在加密目录生成解密代码文件。需要根据项目自行对文件进行解密处理。
如果加密了 mainBundle 的 png 图片,需要在Xcode -> build settings 把 STRIP_PNG_TEXT 和 COMPRESS_PNG_FILES 设置为NO,否则Xcode会自动把加密后的png图片优化
解密流程
- 把读取资源的逻辑封装到一个函数,方便批量处理
- 如果开启了文件名混淆,需要先还原文件名,注意修改文件名不会修改文件名后缀
- 加载已加密文件data,通过解密函数解密data
- 通过data读取资源
解密文件代码
解密文件包含解密data的函数,如果开启了文件名混淆,则会多2个还原文件名的函数
/// 获取混淆后的文件名
/// @param name 混淆前文件名
/// @return 混淆后文件名
+ (NSString *)encryptName:(NSString *)name;
/// 还原混淆的文件名
/// @param name 混淆后文件名
/// @return 混淆前文件名
+ (NSString *)decryptName:(NSString *)name;
/// 文件数据解密
/// @param data 加密的data
/// @return 解密后的data
+ (NSData *)decryptData:(NSData *)data;
解密示例
比如原本加载图片的代码
NSString *path = [[NSBundle mainBundle] pathForResource:@"person" ofType:@"png"];
_imageView.image = [UIImage imageWithContentsOfFile:path];
经过加密后需要通过解密data读取图片
NSString *path = [[NSBundle mainBundle] pathForResource:@"person" ofType:@"png"];
NSData *data = [NSData dataWithContentsOfFile:path];
NSData *decryptData = [DecryptManager decryptData:data]; // 解密data
_imageView.image = [UIImage imageWithData:decryptData];
上面只是示例,最好是封装成函数,传入文件路径或文件名,返回解密后data,再通过data加载资源
文件名混淆
开启会修改所选文件的文件名(不修改文件后缀),生成文件名映射文件,映射文件也会经过加密处理,映射文件只保存文件名的映射规则,不包含后缀,注意需要处理加密目录内的映射文件路径
混淆出来的文件名来自于大量AppStore线上应用统计出来的最常用文件名,同时经过差异化处理
还原文件名示例
直接还原
NSString *path = [[NSBundle mainBundle] pathForResource:@"person" ofType:@"png"];
_imageView.image = [UIImage imageWithContentsOfFile:path];
通过混淆前文件名,获取混淆后文件名再读取
NSString *name = [DecryptManager encryptName:@"person"]; // 通过原文件名读取混淆后文件名
NSString *path = [[NSBundle mainBundle] pathForResource:name ofType:@"png"];
NSData *data = [NSData dataWithContentsOfFile:path];
NSData *decryptData = [DecryptManager decryptData:data]; // 解密data
_imageView.image = [UIImage imageWithData:decryptData];
整个目录还原
比如说我们对 res 目录所有文件进行了加密并混淆文件名,那么可以先把整个目录解密到app(比如 Document),同时还原文件名,只需要在读取的时候改变读取的目录即可
原本加载res目录内资源的代码
NSString *dir = [[NSBundle mainBundle] pathForResource:@"res" ofType:@""];
NSString *path = [dir stringByAppendingPathComponent:@"person.png"];
_imageView.image = [UIImage imageWithContentsOfFile:path];
1.首次启动先把res目录解密到Document同时还原文件名
// 首次启动把res目录解密到 Document
- (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];
// 解密data
NSData *data = [NSData dataWithContentsOfFile:path];
NSData *descryptData = [DecryptManager decryptData:data];
[descryptData writeToFile:toPath atomically:YES];
}
}
2.读取解密后的文件
NSString *dir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject stringByAppendingPathComponent:@"res"];
NSString *path = [dir stringByAppendingPathComponent:@"person.png"];
_imageView.image = [UIImage imageWithContentsOfFile:path];
选择最合适的方式
解密和还原文件名等操作具体选择哪种方式需要根据项目来决定,同时需要注意解密文件的耗时,具体解密的逻辑可以根据项目自行优化