iOS Sqlite加密(FMDB/SQLCipher)
/** * 对数据库加密 * * @param path path description * * @return return value description */ + (BOOL)encryptDatabase:(NSString *)path; /** * 对数据库解密 * * @param path path description * * @return return value description */ + (BOOL)unEncryptDatabase:(NSString *)path; /** * 修改数据库秘钥 * * @param dbPath dbPath description * @param originKey originKey description * @param newKey newKey description * * @return return value description */ + (BOOL)changeKey:(NSString *)dbPath originKey:(NSString *)originKey newKey:(NSString *)newKey;
+ (BOOL)encryptDatabase:(NSString *)path { NSString *sourcePath = path; NSString *targetPath = [NSString stringWithFormat:@"%@.tmp.db", path]; if([self encryptDatabase:sourcePath targetPath:targetPath]) { NSFileManager *fm = [[NSFileManager alloc] init]; [fm removeItemAtPath:sourcePath error:nil]; [fm moveItemAtPath:targetPath toPath:sourcePath error:nil]; return YES; } else { return NO; } } + (BOOL)unEncryptDatabase:(NSString *)path { NSString *sourcePath = path; NSString *targetPath = [NSString stringWithFormat:@"%@.tmp.db", path]; if([self unEncryptDatabase:sourcePath targetPath:targetPath]) { NSFileManager *fm = [[NSFileManager alloc] init]; [fm removeItemAtPath:sourcePath error:nil]; [fm moveItemAtPath:targetPath toPath:sourcePath error:nil]; return YES; } else { return NO; } } + (BOOL)encryptDatabase:(NSString *)sourcePath targetPath:(NSString *)targetPath { const char* sqlQ = [[NSString stringWithFormat:@"ATTACH DATABASE '%@' AS encrypted KEY '%@';", targetPath, kEncryptKey] UTF8String]; sqlite3 *unencrypted_DB; if (sqlite3_open([sourcePath UTF8String], &unencrypted_DB) == SQLITE_OK) { // Attach empty encrypted database to unencrypted database sqlite3_exec(unencrypted_DB, sqlQ, NULL, NULL, NULL); // export database sqlite3_exec(unencrypted_DB, "SELECT sqlcipher_export('encrypted');", NULL, NULL, NULL); // Detach encrypted database sqlite3_exec(unencrypted_DB, "DETACH DATABASE encrypted;", NULL, NULL, NULL); sqlite3_close(unencrypted_DB); return YES; } else { sqlite3_close(unencrypted_DB); NSAssert1(NO, @"Failed to open database with message '%s'.", sqlite3_errmsg(unencrypted_DB)); return NO; } } + (BOOL)unEncryptDatabase:(NSString *)sourcePath targetPath:(NSString *)targetPath { const char* sqlQ = [[NSString stringWithFormat:@"ATTACH DATABASE '%@' AS plaintext KEY '';", targetPath] UTF8String]; sqlite3 *encrypted_DB; if (sqlite3_open([sourcePath UTF8String], &encrypted_DB) == SQLITE_OK) { sqlite3_exec(encrypted_DB, [[NSString stringWithFormat:@"PRAGMA key = '%@';", kEncryptKey] UTF8String], NULL, NULL, NULL); // Attach empty unencrypted database to encrypted database sqlite3_exec(encrypted_DB, sqlQ, NULL, NULL, NULL); // export database sqlite3_exec(encrypted_DB, "SELECT sqlcipher_export('plaintext');", NULL, NULL, NULL); // Detach unencrypted database sqlite3_exec(encrypted_DB, "DETACH DATABASE plaintext;", NULL, NULL, NULL); sqlite3_close(encrypted_DB); return YES; } else { sqlite3_close(encrypted_DB); NSAssert1(NO, @"Failed to open database with message '%s'.", sqlite3_errmsg(encrypted_DB)); return NO; } } + (BOOL)changeKey:(NSString *)dbPath originKey:(NSString *)originKey newKey:(NSString *)newKey { sqlite3 *encrypted_DB; if (sqlite3_open([dbPath UTF8String], &encrypted_DB) == SQLITE_OK) { sqlite3_exec(encrypted_DB, [[NSString stringWithFormat:@"PRAGMA key = '%@';", originKey] UTF8String], NULL, NULL, NULL); sqlite3_exec(encrypted_DB, [[NSString stringWithFormat:@"PRAGMA rekey = '%@';", newKey] UTF8String], NULL, NULL, NULL); sqlite3_close(encrypted_DB); return YES; } else { sqlite3_close(encrypted_DB); NSAssert1(NO, @"Failed to open database with message '%s'.", sqlite3_errmsg(encrypted_DB)); return NO; } }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构