Xcode中集成了免费的sqlite,但是不提供加密的模块,突然有一天,蛋疼的客户要求把数据进行加密,于是乎就寻找使用简单并且可以把数据迁移过度到加密数据库的框架。
  SQLCipher是第三方的开源框架,实现对sqlite的加密,官网链接:http://sqlcipher.net。下面开始下载并导入框架。(使用命令行下载)
一、使用SQLCipher需要3个文件:sqlcipher,openssl-xcode,openssl-1.0.0e
  下载 openssl-xcode
  

cd ~/Documents/code/SQLCipherApp
git clone https://github.com/sqlcipher/openssl-xcode.git

  下载 sqlcipher

cd ~/Documents/code/SQLCipherApp
git clone https://github.com/sqlcipher/sqlcipher.git

  下载 openssl-1.0.0e

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

   把这三个目录拷贝到工程目录中

二.配置Xcode

  1、打开Xcode 的设置页,进入locations ->source trees  ,点击+号添加项目 ,settingname 和 display name 均设为  “OPENSSL_SRC”  path设置为你工程目录下openssl-1.0.0e的所在路径。比如我的路径是:/Users/henry/Documents/工程公用/SQLCipherApp/openssl-1.0.0e

  

     2、添加项目的引用 ,将文件里的openssl.xcodeproj 和sqlcipher.xcodeproj (分别在openssl-xcode文件和sqlcipher文件下)添加到你的主工程下,建立引用
     3、配置编译库,进入项目的工程TARGETS,进入build phases ->target dependencies,添加图中的两个项目
  
 
link binary with libraries添加这两个库
 
 
 
三、下面举个使用的例子
首先需要引入头文件 import<sqlite3.h>

//打开数据库的函数
+(BOOL) OpenDB {
NSArray *pathArr = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *docPaths = [pathArr objectAtIndex:];
NSString *dbPath = [docPaths stringByAppendingFormat:@"/myDB.db"];
int status = sqlite3_open([dbPath UTF8String], &GB_DB); if (status != SQLITE_OK)
{
LOG_CINFO(@"打开数据库出错!");
DB_Opened = NO;
return DB_Opened;
}
DB_Opened = YES;
sqlite3_stmt *statement;
#if UseASE
//验证sql语句是否成功
const char *key = [[GlobalData GetInstance].GB_DBKey UTF8String];
sqlite3_key(GB_DB, key, strlen(key));
#endif
if(sqlite3_prepare_v2(GB_DB, [sql UTF8String], -, &statement, nil) != SQLITE_OK)
{
LOG_CINFO(@"创建表格失败!");
return NO;
} int success = sqlite3_step(statement);
sqlite3_finalize(statement);
//[MyDataBase CloseDB];
if (success != SQLITE_DONE)
{
LOG_CINFO(@"在创建表格的过程中出错,创建没有进行完!");
return NO;
}
return YES;
}
//创建需要的数据表
+ (void)CreateNeedTable {
@autoreleasepool { //插入用户信息表
LocalDataBase *userTb = [LocalDataBase GetTableWithType:@"user" HasUser:NO];
//先创建
[userTb CreateTableWithKeys:[NSArray arrayWithObjects:@"userid", nil] OtherNeeds:[NSArray arrayWithObjects:@"siteid",@"username",@"password",@"mobilePhone",@"name", nil] Data:nil];
}
//根据参数创建表,keys是主键,needs是那些非主键,但是必须需要的,如需要用它来排序,搜索的字段,data为数据项的整个data形式,用data是为了减少字段数
-(BOOL) CreateTableWithKeys:(NSArray *)keys OtherNeeds:(NSArray *)needs Data:(NSString *)data {
//如果有信息,说明注册成功了已经
if(self.myTableInfo)
{
return YES;
} //首先确保数据库是打开的
if (![LocalDataBase OpenDB])
{
return NO;
} //把所有非数据的字段写到一个数组中 NSMutableArray *allArr = [NSMutableArray arrayWithCapacity:10];
if ([keys count] > 0)
{
[allArr addObjectsFromArray:keys];
} if ([needs count] > 0)
{
[allArr addObjectsFromArray:needs];
} if (self.hasUser)
{
[allArr insertObject:@"userName" atIndex:0];
} int keysCount = [allArr count]; if (self.myTableInfo == nil)
{
self.myTableInfo = [NSMutableArray arrayWithCapacity:keysCount+1];
}
//插入数据
for(int i = 0; i < keysCount;++i)
{
NSString *key = [allArr objectAtIndex:i];
[self.myTableInfo addObject:[NSDictionary dictionaryWithObjectsAndKeys:@"text",@"type", key,@"key", nil]];
} //创建sql语句
NSMutableString *cSql = [NSMutableString stringWithFormat:@"create table if not exists %@ (",self.myTableName]; //把非数据类型的字段加入sql语句
for(NSString *key in allArr)
{
[cSql appendFormat:@"%@ text,",key];
} //把数据类型的字段加入Sql语句
if (data != nil)
{
[cSql appendFormat:@"%@ blob,",data];
[self.myTableInfo addObject:[NSDictionary dictionaryWithObjectsAndKeys:@"blob",@"type", data,@"key", nil]];
} //添加主键
[cSql appendString:@"primary key("]; int keyCount = [keys count];
if (keyCount > 0)//有多个主键的情况
{
for(int i = 0; i < keyCount - 1; ++i)
{
NSString *key = [keys objectAtIndex:i];
[cSql appendFormat:@"%@,",key];
} if(self.hasUser)
{
[cSql appendString:@"userName,"];
}
[cSql appendFormat:@"%@)",[keys objectAtIndex:keyCount - 1]];
}
else
{
// if (keyCount == 1)//只有一个主键的情况
// {
// [cSql appendFormat:@"%@)",[keys objectAtIndex:0]];
// }
// else
{
if(self.hasUser)
{
[cSql appendString:@"userName)"];
}
}
} [cSql appendString:@")"]; LOG_CINFO(@"========sql 语句 创建表=========");
LOG_CINFO(cSql); {
NSMutableDictionary *dic = (NSMutableDictionary *)[GlobalFunc ParseDicFromFile:@"dbInfo.plist"];
if (dic == nil)
{
dic = [NSMutableDictionary dictionaryWithCapacity:1];
}
[dic setObject:self.myTableInfo forKey:self.myTableName];
[GlobalFunc WriteDicToFile:dic FileName:@"dbInfo.plist"];
} return [LocalDataBase CreateTableWithSql:cSql];
}
//向表中插入数据
-(BOOL) InsertDataWithDic:(NSDictionary *)dic Replace:(BOOL) replace {
// 打开数据库
if (!DB_Opened)
{
if(![LocalDataBase OpenDB])
{
LOG_CINFO(@"插入数据失败,打开数据库出错!");
return NO;
}
} NSMutableDictionary *tmpDic = [NSMutableDictionary dictionaryWithDictionary:dic];
if (self.hasUser)
{
[tmpDic setObject:[GlobalData GetInstance].GB_UserName forKey:@"userName"];
} NSMutableArray *allKeys = [NSMutableArray arrayWithArray:[tmpDic allKeys]]; NSMutableString *cSql = nil;
//生成插入语句
if (replace)
{
cSql = [NSMutableString stringWithFormat:@"insert or REPLACE into %@(",self.myTableName];
}
else
{
cSql = [NSMutableString stringWithFormat:@"insert into %@(",self.myTableName];
} int keysCount = [allKeys count]; if (keysCount > 0)
{
for(int i = 0; i < keysCount-1;++i)
{
[cSql appendFormat:@"%@,",[allKeys objectAtIndex:i]];
} [cSql appendFormat:@"%@)",[allKeys objectAtIndex:keysCount -1]];
}
else
{
return NO;
} [cSql appendString:@" values("]; for(int i = 0; i<keysCount -1; ++i)
{
[cSql appendString:@"?,"];
}
[cSql appendString:@"?)"]; LOG_CINFO(@"========sql 语句 插入表=========");
LOG_CINFO(cSql); //测试sql 语句是否正确
sqlite3_stmt *statement; const char *insertStatement = [cSql UTF8String];
#if UseASE
//验证sql语句是否成功
const char *key = [[GlobalData GetInstance].GB_DBKey UTF8String];
sqlite3_key(GB_DB, key, strlen(key));
#endif
if(sqlite3_prepare_v2(GB_DB, insertStatement, -1, &statement, NULL) != SQLITE_OK)
{
LOG_CINFO(@"向表格中插入数据失败,可能Sql语句不正确!");
[GlobalFunc ShowNormalAlert:[NSString stringWithFormat:@"向表格中插入数据失败,可能Sql语句不正确,表名为%@",self.myTableName]];
return NO;
} for(int i = 0; i < keysCount;++i)
{
NSString *key = [allKeys objectAtIndex:i]; id value = [tmpDic objectForKey:key]; //如果是Data类型
if ([value isKindOfClass:[NSData class]])
{
sqlite3_bind_blob(statement, i+1, [value bytes], [value length], NULL);
}
else//是字符串类型
{
sqlite3_bind_text(statement, i+1, [value UTF8String], -1, NULL);
}
} int success = sqlite3_step(statement);
// 释放资源
sqlite3_finalize(statement); if (success == SQLITE_ERROR)
{
LOG_CINFO(@"向表格中插入数据失败,未知原因提前结束!");
[GlobalFunc ShowNormalAlert:[NSString stringWithFormat:@"向表格中插入数据失败,未知原因提前结束,表名为%@",self.myTableName]];
return NO;
}
LOG_CINFO(@"向表格中插入数据成功!");
return YES; }
//更新表字段,key是要更新的字段名称,newValue是更新后要设计的值,where是条件(sql语句中的),condition是满足更新的条件,use是否使用用户名为条件
-(BOOL) UpdateRecordWithKey:(NSString *)key Value:(NSString *)newValue Where:(NSString *)where Condition:(NSString *)condition UseUser:(BOOL)use {
if(![LocalDataBase OpenDB])
{
return NO;
}
@try
{
NSString *tmpUpdateSql = nil; if (use && self.hasUser)
{
tmpUpdateSql = [NSString stringWithFormat:@"UPDATE %@ SET %@ = ? where %@ = ? and userName = ?",self.myTableName,key,where];
}
else
{
tmpUpdateSql = [NSString stringWithFormat:@"UPDATE %@ SET %@ = ? where %@ = ?",self.myTableName,key,where];//@"UPDATE tb_bulletlist SET has_read = ? where bulletin_code = ? and user_name=?";
}
sqlite3_stmt *statement; LOG_CINFO(@"========sql 语句 更新表=========");
LOG_CINFO(tmpUpdateSql);
#if UseASE
//验证sql语句是否成功
const char *key = [[GlobalData GetInstance].GB_DBKey UTF8String];
sqlite3_key(GB_DB, key, strlen(key));
#endif
if(sqlite3_prepare_v2(GB_DB, [tmpUpdateSql UTF8String], -1, &statement, nil) != SQLITE_OK)
{
LOG_CINFO(@"更新数据失败!");
[GlobalFunc ShowNormalAlert:[NSString stringWithFormat:@"更新数据失败,表名为%@",self.myTableName]];
return NO;
} sqlite3_bind_text(statement, 1, [newValue UTF8String], -1, NULL);
sqlite3_bind_text(statement, 2, [condition UTF8String], -1, NULL); if (use && self.hasUser)
{
sqlite3_bind_text(statement, 3, [[GlobalData GetInstance].GB_UserName UTF8String], -1, NULL);
}
int success = sqlite3_step(statement); sqlite3_finalize(statement);
//[MyDataBase CloseDB];
if (success != SQLITE_DONE)
{
LOG_CINFO(@"更新数据失败,未知原因提前结束!");
[GlobalFunc ShowNormalAlert:[NSString stringWithFormat:@"更新数据失败,未知原因提前结束,表名为%@",self.myTableName]];
return NO;
} }
@catch (NSException *e)
{
// LOG_CERR(e);
} return YES;
}
//根据传入的关键字和关键字的值,得到一条记录,如果不存在这条记录,返回为nil,估也可用来判断是否存在某条记录,use是否使用用户名为条件
-(NSMutableDictionary *) GetOneRecordWithKeys:(NSArray *)keys Values:(NSArray *)values UseUser:(BOOL)use {
if ([keys count] != [values count])
{
// [GlobalFunc ShowNormalAlert:[NSString stringWithFormat:@"GetOneRecordWithKeys 数据查询参数keys与values个数不一致,表名为%@",self.myTableName]]; return nil;
} // 打开数据库
if (!DB_Opened)
{
if(![LocalDataBase OpenDB])
{
LOG_CINFO(@"查询数据失败,打开数据库出错!");
return nil;
}
} NSMutableString *cSql = [NSMutableString stringWithFormat:@"select * from %@ where ",self.myTableName];
if (use && self.hasUser)
{
[cSql appendFormat:@"userName = '%@' and ",[GlobalData GetInstance].GB_UserName];
} int keyCount = [keys count];
for (int i = 0; i < keyCount; ++i)
{
if (i == 0)
{
[cSql appendFormat:@"%@ = '%@'",[keys objectAtIndex:i],[values objectAtIndex:i]];
}
else
{
[cSql appendFormat:@" and %@ = '%@'",[keys objectAtIndex:i],[values objectAtIndex:i]];
} } NSArray *tmpArr = [self GetDataArrWithSql:cSql]; if ([tmpArr count] == 0)
{
return nil;
}
else
{
return [tmpArr objectAtIndex:0];
}
}

  如果在编译时提示:No architectures to compile for (ARCHS=armv6,armv7, VALID_ARCHS=armv7 armv7s则将在Bulid Settings选项下面的Architectures和Valid Architectures里面都改成一样(例如:都填写 armv6 armv7),问题解决。 对于警告 :warning: implicit declaration of function 'sqlite3_key' is invalid in C99 只需要将Bulid Settings选项下的C Language Dialect 改为:C89[-std-c89] 就可以,即使用c89标准

或者去掉项目中的arm64

以上只是贴出代码的一部分,可能看起来有些吃力,稍后会把一个完整的使用数据库的类整理出来。

本文参考:http://blog.csdn.net/kuai0705/article/details/8931996

使用SQLCipher加密数据库的更多相关文章

  1. 数据库开源框架之sqlcipher加密数据库

    访问github链接:https://github.com/sqlcipher/android-database-sqlcipher 访问 http://sqlcipher.net/sqlcipher ...

  2. ios开发FMDB导入SQLCipher加密数据库

    转:http://www.2cto.com/kf/201407/315727.html [iOS]FMDB/SQLCipher数据库加解密,迁移

  3. iOS 使用FMDB SQLCipher给数据库加密

    关于SQLite,SQLCipher和FMDB SQLite是一个轻量的.跨平台的.开源的数据库引擎,它的在读写效率.消耗总量.延迟时间和整体简单性上具有的优越性,使其成为移动平台数据库的最佳解决方案 ...

  4. 日常破解--从XCTF的app3题目简单了解安卓备份文件以及sqliteCipher加密数据库

    一.题目来源     题目来源:XCTF app3题目 二.解题过程     1.下载好题目,下载完后发现是.ab后缀名的文件,如下图所示:     2.什么是.ab文件?.ab后缀名的文件是Andr ...

  5. 解密TDE加密数据库

    1 找到加密的数据库,new query 2 执行sql 语句:ALTER DATABASE  database_name SET ENCRYPTION OFF; DROP DATABASE ENCR ...

  6. SrpingDruid数据源加密数据库密码

    前言 在工作中遇到这样一个问题:开发过程中将数据库的账号.密码等信息配置在了一个单独的properties配置文件中(使用明文).但运维人员要求在配置文件中的密码一律不得出现明文. 环境 Spring ...

  7. 在asp.net中使用加密数据库联接字符串

    在我们发布网站时,加密web.config,这样可以有效保证数据库用户和密码安全,其步骤如下: 1.添加密钥 执行:C:\WINDOWS\Microsoft.NET\Framework\v2.0.50 ...

  8. spring boot 配置文件加密数据库用户名/密码

    这篇文章为大家分享spring boot的配置文件properties文件里面使用经过加密的数据库用户名+密码,因为在自己做过的项目中,有这样的需求,尤其是一些大公司,或者说上市公司,是不会把这些敏感 ...

  9. Java加密数据库

    一.背景 数据库配置以明文方式展示如图,会造成安全隐患,如果有黑客入侵会造成密码泄露,信息窃取和破坏等. 二.加密步骤 1.对数据库信息加密: 对数据库中的账号和密码信息进行加密(选择一种算法)然后替 ...

随机推荐

  1. HttpURLConnection 下载代码

    private int downloadFile(final String apkurl, final String apkname) { Log.e(LOGTAG, "downloadAp ...

  2. 在JS中调用JAVA变量

    在JS中调用JAVA变量可以,方法是:var JS变量名 = “<%=JAVA变量名 %>”<%中间写java代码,跟在JSP中一样%>在JAVA中 ,无法调用JS变量

  3. 基于C#—WPF的扫雷游戏

    自学教材:<C#入门经典(第六版)>,1月28日购入,1月29日到2月9日学习了前十六章,由于有C语言基础,在语法阶段学习起来比较轻松,不过在接触到面向对象的时候遇到了一些困难,对于一些概 ...

  4. Myeclipse6.5配置反编译插件

    PS:jad.exe位置与Myeclipse6.5安装目录平行

  5. Java 学习 第一篇

    1:Java文档注释:使用javadoc工具可以提取程序中文档注释来生成API文档:javadoc命令的基本用法:javadoc 选项 java源文件/包javadoc -d {} -windowti ...

  6. 三星S5驱动安装

    三星S5的驱动安装一定要先用原装的数据线链接电脑,在电脑里面安装完驱动之后,以后才能每次都用正常的数据线链接 不然的话会提示某些驱动安装不正常..

  7. mysql null值转换

    1.如果为空返回0 select ifnull(null,0) 2.如果为空返回0,否则返回1 select if(isnull(col),0,1) as col.

  8. Ubuntu14.0.4 64位 ADT 连接手机调试问题

    1:使用 lsusb 命令查看USB 设备 y@y:~$ lsusbBus 001 Device 002: ID 8087:8000 Intel Corp. Bus 001 Device 001: I ...

  9. 基于新唐M0的XXTEA加密解密算法源码

    /*-------------------------------------------------------------------------------------------------- ...

  10. Qt之HTTPS登录(集成QNetworkAccessManager提前修改QSslConfiguration,然后post)

    简述 HTTPS(全称:Hyper Text Transfer Protocol over Secure Socket Layer),是以安全为目标的HTTP通道,简单讲是HTTP的安全版.即HTTP ...