详解ios中的SQL数据库文件加密 (使用sqlcipher)

时间:2022-11-28 16:33:20

今天本想写一片 gae+*+switchysharp 的指南的!但是突然翻出了前段时间写的关于ios中的sql数据库文件加密的代码,于是乎决定今天就先讲讲这个!~ 那么*将放在周末,后续的文章中除了文件加密,还有传输数据加密,感兴趣的童鞋 敬请留意。

言归正传,sql的文件加密,我们首先要用到一个库,它就是大名鼎鼎的sqlcipher,  奉上连接:http://sqlcipher.net,在ios里 我们需要看的文档是这一篇http://sqlcipher.net/ios-tutorial/,文档是全英文的,在此,不详细阐述,只按步骤教大家怎么做,至于为什么做的问题,就需要自己去寻找答案了!
1.下载需要的库 这里我们总共需要3个目录的文件,分别是sqlcipher,openssl-xcode,openssl-1.0.0e。
首先下载第一个

?
1
2
3
% cd ~/documents/code//命令行cd到你要下载的目录
% curl -o openssl-1.0.0e.tar.gz http://www.openssl.org/source/openssl-1.0.0e.tar.gz//下载
% tar xzf openssl-1.0.0e.tar.gz //解压缩

附:

sqlcipher uses the widely trusted and peer-reviewed openssl library for all cryptographic functions including the aes-256 algorithm, pseudo random number generation, and pbkdf2 key derivation. openssl isn't framework that is usable directly on the iphone so we will setup our project to build and link against it as a static library.

download the 1.0.x stable version from http://www.openssl.org/source/ and extract it to a folder on your system. since the same openssl source tree may be shared across multiple sqlcipher projects, it's a good idea to place this in some shared location outside of your project folder. justs make a note of the source directory path for later.

(看不懂英文的童鞋也不用着急,跟着继续做就好了,也很好理解)

openssl是套开源的ssl套件,其函数库是以c語言所写,实现基本的傳輸層資料加密功能。

第二个

?
1
2
% cd ~/documents/code/sqlcipherapp
% git clone https://github.com/sqlcipher/sqlcipher.git

从远端服务器将其 clone 下来,这里推荐放到和上一个文件同一个目录 方便管理

这个就是 sqlcipher 的project code了

第三个

?
1
2
% cd ~/documents/code/sqlcipherapp
% git clone https://github.com/sqlcipher/openssl-xcode.git

这个是我们需要动态编译进工程的文件

至此我们需要的文件 就准备好了

接下来 打开你的工程进行配置,

(这里我是自己单独写了一个工具用来加密并生成!后面会附上我的源码)

1.将你下载的3个目录拷贝进你的工程目录

2.点击你xcode的设置页,选择locations ->source trees

详解ios中的SQL数据库文件加密 (使用sqlcipher)

点击+号  settingname and display name 均设为  “openssl_src”       path设置为你工程目录下openssl-1.0.0e的所在路径

3.添加子项目的引用

将刚才下载的文件里的openssl.xcodeproj 和sqlcipher.xcodeproj (分别在openssl-xcode文件和sqlcipher文件下)添加到你的主工程下,建立引用,直接看图吧!

详解ios中的SQL数据库文件加密 (使用sqlcipher)

4,接下来 配置编译依赖的库,这是必须的!~

点击你的工程targets 进入build phases ->target dependencies,添加图中的两个项目

详解ios中的SQL数据库文件加密 (使用sqlcipher)

接下来点击同一个页面下的link binary with libraries添加这两个库

详解ios中的SQL数据库文件加密 (使用sqlcipher)

至此 还有最后一步,设置编译设置

点击你的工程project->build settings ->搜索architectures进行设置

我这里由于是mac程序看起来会是这样

详解ios中的SQL数据库文件加密 (使用sqlcipher)

ios的话 会是这样

详解ios中的SQL数据库文件加密 (使用sqlcipher)

(关于这里的设置,如果又不明白的地方 请google)

接下来 还是在同页面 搜索“other c flags”

进行如下配置

详解ios中的SQL数据库文件加密 (使用sqlcipher)

至此整个过程就打工告成了

接下来讲述使用

首先在需要的文件内 import<sqlite3.h>

下面 示范一个 创建or打开数据库的函数

?
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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
-(bool) opendatabase
{
  if (sqlite3_open([[self datafilepath:db_name] utf8string], &_database) == sqlite_ok) {
    const char* key = [@",66c9a^n" utf8string];  //数据库文件加密
    sqlite3_key(_database, key, (int)strlen(key));   //数据库文件加密
    nslog(@"\n===数据库打开or创建成功===\n");
    return yes;
  }else{
    nslog(@"\n===数据库打开失败===\n");
  }
  return no;
}
db_name 是定义的 数据库文件名的宏",66c9a^n" 是你要设置的数据库密钥 sqlite3_key(_database, key, (int)strlen(key));这个方法里就包含了 加解密的过程!~是不是非常简单呢嘿嘿接下来 附上自己的工程 源代码有需要的童鞋,就自己看看吧!里面有详细的注释, 也简单的实现了几个方便数据库操作的函数
//////////////////////////////////////////////////////////
#import <foundation/foundation.h>
#import <sqlite3.h>
#define db_name @"xxxxxxx.db"              //数据库文件名
@interface sqlitehelp :nsobject
@propertysqlite3 *database;            //数据库句柄
@propertysqlite3_stmt *statement;         //sql语句
@property char *errmsg;
-(bool) opendatabase;               //打开数据库 这个函数一般不直接调用,而是直接调用对数据库操作的函数
-(void) closedatabase;               //关闭数据库 这个函数一般不直接调用,而是直接调用对数据库操作的函数
-(nsstring *) datafilepath:(nsstring *)filename;  //返回数据库存储路径 这个函数一般不直接调用,而是直接调用对数据库操作的函数
/**
 * 说明: 给定一个sql语句 插入或者编辑一个数据
 * 语句格式 :
 * 插入:[insert (文件名)values(data1, data2, data3, ...);]
 * 编辑:[update(文件名) set (字段名)=(修改后的数据) where(字段名)=(修改前的数据);]
 */
-(bool) insertorupdatedata:(nsstring *)sql;
      
-(nsmutablearray *) getusers;           //以数组的形势,获取所有用户
-(int) getcountofdatabase;             //获取当前数据库的数量
@end
////////////////////////////////////////////////////
#import "sqlitehelp.h"
@implementation sqlitehelp
@synthesize database =_database;
@synthesize statement =_statement;
@synthesize errmsg =_errmsg;
-(bool) opendatabase
{
  if (sqlite3_open([[selfdatafilepath:db_name]utf8string], &_database) ==sqlite_ok) {
    constchar* key = [@",66c9a^n"utf8string];  //数据库文件加密
    sqlite3_key(_database, key, (int)strlen(key));   //数据库文件加密
    nslog(@"\n===数据库打开or创建成功===\n");
    returnyes;
  }else{
    nslog(@"\n===数据库打开失败===\n");
  }
  return no;
   
}
-(void) closedatabase
{
  sqlite3_close(_database);
}
-(nsstring *) datafilepath:(nsstring *)filename
{
  nsarray *paths =nssearchpathfordirectoriesindomains(nsdocumentdirectory,
                            nsuserdomainmask,
                            yes);
  nsstring *documentsdirectory = [pathsobjectatindex:0];
  return [documentsdirectorystringbyappendingpathcomponent:filename];
}
-(bool) insertorupdatedata:(nsstring *)sql
{
  if ([selfopendatabase]) {
    if (sqlite3_exec(_database, [sqlutf8string],nil, &_statement, &_errmsg) !=sqlite_ok) {
      nslog(@"\n===插入数据失败===\n");
      nslog(@"\n==sql error:%s",_errmsg);
      returnno;
    }else{
      nslog(@"\n===插入数据成功===\n");
      returnyes;
    }
     
  }
  sqlite3_close(_database);
  return no;
}
-(nsmutablearray *) seedatabase
{
  nsmutablearray *users = [[nsmutablearrayalloc]init];
  nsstring *sql = [nsstringstringwithformat:@"select * from t_relive"];
  if ([selfopendatabase]) {
    if (sqlite3_prepare_v2(_database, [sqlutf8string], -1, &_statement,nil) ==sqlite_ok) {
      while (sqlite3_step(_statement) ==sqlite_row ) {
//        user *user = [[question alloc] init];
        int name =sqlite3_column_int(_statement,0);
//        [user setname:[nsstring stringwithutf8string:name]];
        int index =sqlite3_column_int(_statement,1);
//        [user setid:[[nsstring stringwithutf8string:index] intvalue]];
//        [users addobject: user];
        nslog(@"%i=%i",name,index);
      }
      sqlite3_finalize(_statement);
    }
  }
  sqlite3_close(_database);
  return users;
}
-(int) getcountofdatabase
{
  int count =0;
  nsstring *sql = [nsstringstringwithformat:@"select * from user"];
  if ([selfopendatabase]) {
    if (sqlite3_prepare_v2(_database, [sqlutf8string], -1, &_statement,nil) ==sqlite_ok) {
      while (sqlite3_step(_statement) ==sqlite_row) {
        count ++;
      }
      sqlite3_finalize(_statement);
    }
  }
  return count;
}
@end
/////////////////////////////////////////////////////////////////
这里实现 输入sql表 生成数据库,可以在控制台查错
#import "appdelegate.h"
#import "sqlitehelp.h"
@implementation appdelegate
- (void)applicationdidfinishlaunching:(nsnotification *)anotification
{
  // insert code here to initialize your application
  [selfbuilddatabase];
  [selfinsertdatabase];
}
- (void) builddatabase
{
  nserror *error;
  nsstring *textfile = [nsstringstringwithcontentsoffile:[[nsbundlemainbundle]pathforresource:@"schema.sqlite.tables.sql"oftype:nil]encoding:nsutf8stringencodingerror:&error];
  if (textfile ==nil) {
    nslog(@"error reading text file. %@", [errorlocalizedfailurereason]);
  }
  nsarray *row = [textfilecomponentsseparatedbystring:@";"];
  nsinteger count = [rowcount];
  sqlitehelp *t = [sqlitehelpnew];
  for (int i=0; i<count; i++) {
    nsstring *tempstring = [nsstringstringwithformat:@"%@;",row[i]];
    nslog(@"%@",tempstring);
    [tinsertorupdatedata:tempstring];
  }
   
   
   
}
-(void) insertdatabase
{
  nserror *error;
  nsstring *textfile = [nsstringstringwithcontentsoffile:[[nsbundlemainbundle]pathforresource:@"schema.sqlite.data.sql"oftype:nil]encoding:nsutf8stringencodingerror:&error];
  if (textfile ==nil) {
    nslog(@"error reading text file. %@", [errorlocalizedfailurereason]);
  }
  nsarray *row = [textfilecomponentsseparatedbystring:@";"];
  nsinteger count = [rowcount];
  sqlitehelp *t = [sqlitehelpnew];
  for (int i=0; i<count; i++) {
    nsstring *tempstring = [nsstringstringwithformat:@"%@;",row[i]];
    nslog(@"%@",tempstring);
    [tinsertorupdatedata:tempstring];
  }
   
}
@end

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。

原文链接:http://blog.csdn.net/kuai0705/article/details/8931996