在公司产品上线前, 准备把数据库加密掉, 本来是几行代码的事情, 倒腾了几个小时......
1. 加密操作
网上大多数方法的做法是, 直接修改FMDatabase.h
方法, 我认为直接修改第三方库的源码, 是不科学的, 我的做法是创建新类, 继承自FMDatabase, 重写相应的方法, 在需要加密的地方, 添加加密用的语句.
2. 错误方式
原来项目中已经通过cocoapod集成了FMDB
框架. 刚开始我的做法是, 在Profile上直接加上pod 'FMDB/SQLCipher' #数据库加密
, 这时候Profile中同时包含 pod 'FMDB' #数据库`` pod 'FMDB/SQLCipher'
, 安装之后, 不管怎么测试, 总是无法读写数据库, 耗了好长时间, 最终发现, 删除 ``pod 'FMDB'` 之后, 就可以正常读写了......
cocoapod集成SQLCipher时候, Profile加入 'FMDB/SQLCipher' 即可!!
3. 为了实现加密重写的方法
#pragma mark - 对FMDataBase加密, 使用 SQLCipher, 通过重载方法 实现加密
#import "sqlite3.h"
@implementation FMCipherDataBase
static NSString *DB_SECRETKEY = @"123456";
+ (instancetype)databaseWithPath:(NSString *)inPath cipherKey:(NSString *)cipherKey {
FMCipherDataBase *database = [super databaseWithPath:inPath];
DB_SECRETKEY = cipherKey;
return database;
}
- (const char*)sqlitePath {
if (!_databasePath) {
return ":memory:";
}
if ([_databasePath length] == 0) {
return ""; // this creates a temporary database (it's an sqlite thing).
}
return [_databasePath fileSystemRepresentation];
}
- (BOOL)open {
if (_db) {
return YES;
}
int err = sqlite3_open([self sqlitePath], (sqlite3**)&_db );
if(err != SQLITE_OK) {
NSLog(@"error opening!: %d", err);
return NO;
} else {
[self setKey:DB_SECRETKEY];
}
if (_maxBusyRetryTimeInterval > 0.0) {
// set the handler
[self setMaxBusyRetryTimeInterval:_maxBusyRetryTimeInterval];
}
return YES;
}
- (BOOL)openWithFlags:(int)flags vfs:(NSString *)vfsName {
#if SQLITE_VERSION_NUMBER >= 3005000
if (_db) {
return YES;
}
int err = sqlite3_open_v2([self sqlitePath], (sqlite3**)&_db, flags, [vfsName UTF8String]);
if(err != SQLITE_OK) {
NSLog(@"error opening!: %d", err);
return NO;
} else {
[self setKey:DB_SECRETKEY];
}
if (_maxBusyRetryTimeInterval > 0.0) {
// set the handler
[self setMaxBusyRetryTimeInterval:_maxBusyRetryTimeInterval];
}
return YES;
#else
NSLog(@"openWithFlags requires SQLite 3.5");
return NO;
#endif
}
@end
详情请参考: https://github.com/hell03W/FMDBHelper