iOS SQLite加密之SQLCipher
至于SQLCipher,我就不多说了,百度一下,你就知道。公司的iOS APP要给SQLite,今天就上网查了些资料,做了下整理,主要参考SQLCipher的官方集成文档,有不妥之处大家提出来我再改进,感谢拍砖。官方集成文档:https://www.zetetic.net/sqlcipher/ios-tutorial/。
Prerequisites
安装Xcode开发环境,不用多说了吧。
OpenSSL
本教程用苹果提供的FrameWork:CommonCrypto,可在工程,Target,Build Phases ,Link Binary 中添加,搜索 CommonCrypto即可添加。
SQLCipher
打开终端,切到你要集成sqlcipher的工程根目录下,执行下命令。从GitHub下载 SQLCipher到本地:
$ cd ~/Documents/code/SQLCipherApp
$ git clone https://github.com/sqlcipher/sqlcipher.git
Xcode Project Configuration
The SQLCipher source provides a sqlcipher.xcodeproj
project file that we‘ll add to your project to build a static library that you‘ll link from your main application target.
Add Project Reference
选择你的项目,右键,选择 "Add Files to [你的工程]";在弹出的选择窗口找到你刚才从git下载的sqlcipher路径,打开sqlcipher文件夹,选择sqlcipher.xcodeproj;
注意:不要勾选 Copy items if needed 复选框。
Configure Target Dependencies and Link Binary With Libraries
点击工程,选择TARGETS中你的工程,点击 Build Phases Tab栏。
1. 展开 Target Dependencies ,添加 + sqlcipher
静态库
2.展开 Link Binary With Libraries,添加+libsqlcipher.a库
注意:如果你的工程库中已经添加了libsqlite3.dylib
或者其他的SQLite库,请Remove掉,否则可能会提示出现重复sqlite库。
重复这些步骤在你工程的其他Target中。
Configure Build Settings
回到你的工程编辑面板,选择工程,TARGETS》你的工程Target,Build Settings Tab栏,
1.选择Header Search Paths项,双击键入新值:./sqlcipher/src。如图:
注意填写的路径。../表示上级文件夹
2.选择 Other C Flags ,双击 添加-DSQLITE_HAS_CODEC。注意Release 和 Debug的配置值一样,如下图:
注意(自己翻译吧):Hot Tip: The handling of Architectures and the meaning of the $(STANDARD_ARCHS)
build variable changes depending on the Xcode release, but currently on iOS in Xcode 6.1.1 the armv7s
architecture is not included in your build. SQLCipher supports this architecture! If you need to squeeze that much more speed out of SQLCipher on those devices, add the armv7s architecture string to your Architectures option in Build Settings (sample image here).
Integration Code
到现在为止,sqlcipher已经包含到我们的工程中了,现在我们可以使用sqlcipher来创建或打开一个加密sqlite书库了。接下来打开程序的代理类,引入sqlite3.h头文件,找到-applicationDidFinishLaunching:withOptions:代理方法,开始设置代码如下:
// // AppDelegate.m // SecureLoginDelegate // // Created by Billy Gray on 10/19/14. // Copyright (c) 2014 Zetetic. All rights reserved. // #import "AppDelegate.h" #import <sqlite3.h> @interface AppDelegate () @property (nonatomic) BOOL isLoginViewControllerDisplayed; @property (readonly) NSURL *databaseURL; @property (readonly) BOOL databaseExists; @end @implementation AppDelegate @dynamic databaseURL; @dynamic databaseExists; - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // Set up the window with loginViewController as the rootViewController for now // to avoid showing app view on launch on iOS 8 [[self window] setRootViewController:self.loginViewController]; [[self window] makeKeyAndVisible]; self.isLoginViewControllerDisplayed = YES; // Set up a SQLCipher database connection: sqlite3 *db; if (sqlite3_open([[self.databaseURL path] UTF8String], &db) == SQLITE_OK) { const char* key = [@"StrongPassword" UTF8String]; sqlite3_key(db, key, (int)strlen(key)); if (sqlite3_exec(db, (const char*) "SELECT count(*) FROM sqlite_master;", NULL, NULL, NULL) == SQLITE_OK) { NSLog(@"Password is correct, or a new database has been initialized"); } else { NSLog(@"Incorrect password!"); } sqlite3_close(db); } return YES; } - (NSURL *)databaseURL { NSArray *URLs = [[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask]; NSURL *directoryURL = [URLs firstObject]; NSURL *databaseURL = [directoryURL URLByAppendingPathComponent:@"secure.db"]; return databaseURL; } - (BOOL)databaseExists { BOOL exists = NO; NSError *error = nil; exists = [[self databaseURL] checkResourceIsReachableAndReturnError:&error]; if (exists == NO && error != nil) { NSLog(@"Error checking availability of database file: %@", error); } return exists; } @end
SecureLoginDelegate-AppDelegate.m hosted with ? by GitHub
OK,编译Run你的App,配置不错的话就能运行成功了,在控制台你若能看到打印如下的日志内容:
虽然我们建议你用sqlite3_bind_*
API 来避免一些陷阱,你也可以执行PRAGMA key = ‘some key‘;
as SQL。
下面还有一段英文自己看吧:
The call to sqlite3_key or "PRAGMA key" should occur as the first operation after opening the database. In most cases SQLCipher uses PBKDF2, a salted and iterated key derivation function, to obtain the encryption key. Alternately, an application can tell SQLCipher to use a specific binary key in blob notation (note that SQLCipher requires exactly 256 bits of key material), for example:
PRAGMA key = "x‘2DD29CA851E7B56E4697B0E1F08507293D761A05CE4D1B628663F411A8086D99‘";
Once the key is set SQLCipher will automatically encrypt all data in the database! Note that if you don‘t set a key then SQLCipher will operate identically to a standard SQLite database.
After the application is wired up to use SQLCipher, take a peek at the resulting data files to make sure everything is in order. An ordinary SQLite database will look something like the following under hexdump. Note that the file type, schema, and data are clearly readable.
% hexdump -C plaintext.db 00000000 53 51 4c 69 74 65 20 66 6f 72 6d 61 74 20 33 00 |SQLite format 3.| 00000010 04 00 01 01 00 40 20 20 00 00 00 04 00 00 00 00 |.....@ ........| ... 000003b0 00 00 00 00 24 02 06 17 11 11 01 35 74 61 62 6c |....$......5tabl| 000003c0 65 74 32 74 32 03 43 52 45 41 54 45 20 54 41 42 |et2t2.CREATE TAB| 000003d0 4c 45 20 74 32 28 61 2c 62 29 24 01 06 17 11 11 |LE t2(a,b)$.....| 000003e0 01 35 74 61 62 6c 65 74 31 74 31 02 43 52 45 41 |.5tablet1t1.CREA| 000003f0 54 45 20 54 41 42 4c 45 20 74 31 28 61 2c 62 29 |TE TABLE t1(a,b)| ... 000007d0 00 00 00 14 02 03 01 2d 02 74 77 6f 20 66 6f 72 |.......-.two for| 000007e0 20 74 68 65 20 73 68 6f 77 15 01 03 01 2f 01 6f | the show..../.o| 000007f0 6e 65 20 66 6f 72 20 74 68 65 20 6d 6f 6e 65 79 |ne for the money|
Fire up the SQLCipher application in simulator and look for the application database files under/Users/billy/Library/Developer/CoreSimulator/Devices/<SOME ID NUMBER>/data/Containers/Data/Application/<SOME ID NUMBER>/Documents
(step through the code in the debugger and enter po [self.databaseURL path]
for the exact path). Try running hexdump on the application database. With SQLCipher the output should looks completely random, with no discerning characteristics at all.
% hexdump -C sqlcipher.db 00000000 1b 31 3c e3 aa 71 ae 39 6d 06 f6 21 63 85 a6 ae |.1<..q.9m..!c...| 00000010 ca 70 91 3e f5 a5 03 e5 b3 32 67 2e 82 18 97 5a |.p.>.....2g....Z| 00000020 34 d8 65 95 eb 17 10 47 a7 5e 23 20 21 21 d4 d1 |4.e....G.^# !!..| ... 000007d0 af e8 21 ea 0d 4f 44 fe 15 b7 c2 94 7b ee ca 0b |..!..OD.....{...| 000007e0 29 8b 72 93 1d 21 e9 91 d4 3c 99 fc aa 64 d2 55 |).r..!...<...d.U| 000007f0 d5 e9 3f 91 18 a9 c5 4b 25 cb 84 86 82 0a 08 7f |..?....K%.......| 00000800
See Also
All applications that make use of cryptography, including those that use SQLCipher or iOS internal libraries like CommonCrypto and Keychain, must provide documentation to Apple that demonstrates review by the Department of Commerce (DOC) Bureau of Industry and Security (BIS) and classification of the application a mass market encryption item.
Information on the PBKDF2 key derivation function is available at http://en.wikipedia.org/wiki/PBKDF2
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。