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

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

  下载 sqlcipher

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

  下载 openssl-1.0.0e

  1. curl -o openssl-1.0.0e.tar.gz http://www.openssl.org/source/openssl-1.0.0e.tar.gz
  2. //解压
  3. 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>

  1. //打开数据库的函数
  2. +(BOOL) OpenDB {
  3. NSArray *pathArr = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
  4. NSString *docPaths = [pathArr objectAtIndex:];
  5. NSString *dbPath = [docPaths stringByAppendingFormat:@"/myDB.db"];
  6. int status = sqlite3_open([dbPath UTF8String], &GB_DB);
  7.  
  8. if (status != SQLITE_OK)
  9. {
  10. LOG_CINFO(@"打开数据库出错!");
  11. DB_Opened = NO;
  12. return DB_Opened;
  13. }
  14. DB_Opened = YES;
  15. sqlite3_stmt *statement;
  16. #if UseASE
  17. //验证sql语句是否成功
  18. const char *key = [[GlobalData GetInstance].GB_DBKey UTF8String];
  19. sqlite3_key(GB_DB, key, strlen(key));
  20. #endif
  21. if(sqlite3_prepare_v2(GB_DB, [sql UTF8String], -, &statement, nil) != SQLITE_OK)
  22. {
  23. LOG_CINFO(@"创建表格失败!");
  24. return NO;
  25. }
  26.  
  27. int success = sqlite3_step(statement);
  28. sqlite3_finalize(statement);
  29. //[MyDataBase CloseDB];
  30. if (success != SQLITE_DONE)
  31. {
  32. LOG_CINFO(@"在创建表格的过程中出错,创建没有进行完!");
  33. return NO;
  34. }
  35. return YES;
  36. }
  1. //创建需要的数据表
  2. + (void)CreateNeedTable {
  3. @autoreleasepool {
  4.  
  5. //插入用户信息表
  6. LocalDataBase *userTb = [LocalDataBase GetTableWithType:@"user" HasUser:NO];
  7. //先创建
  8. [userTb CreateTableWithKeys:[NSArray arrayWithObjects:@"userid", nil] OtherNeeds:[NSArray arrayWithObjects:@"siteid",@"username",@"password",@"mobilePhone",@"name", nil] Data:nil];
  9. }
  1. //根据参数创建表,keys是主键,needs是那些非主键,但是必须需要的,如需要用它来排序,搜索的字段,data为数据项的整个data形式,用data是为了减少字段数
  2. -(BOOL) CreateTableWithKeys:(NSArray *)keys OtherNeeds:(NSArray *)needs Data:(NSString *)data {
  3. //如果有信息,说明注册成功了已经
  4. if(self.myTableInfo)
  5. {
  6. return YES;
  7. }
  8.  
  9. //首先确保数据库是打开的
  10. if (![LocalDataBase OpenDB])
  11. {
  12. return NO;
  13. }
  14.  
  15. //把所有非数据的字段写到一个数组中
  16.  
  17. NSMutableArray *allArr = [NSMutableArray arrayWithCapacity:10];
  18. if ([keys count] > 0)
  19. {
  20. [allArr addObjectsFromArray:keys];
  21. }
  22.  
  23. if ([needs count] > 0)
  24. {
  25. [allArr addObjectsFromArray:needs];
  26. }
  27.  
  28. if (self.hasUser)
  29. {
  30. [allArr insertObject:@"userName" atIndex:0];
  31. }
  32.  
  33. int keysCount = [allArr count];
  34.  
  35. if (self.myTableInfo == nil)
  36. {
  37. self.myTableInfo = [NSMutableArray arrayWithCapacity:keysCount+1];
  38. }
  39. //插入数据
  40. for(int i = 0; i < keysCount;++i)
  41. {
  42. NSString *key = [allArr objectAtIndex:i];
  43. [self.myTableInfo addObject:[NSDictionary dictionaryWithObjectsAndKeys:@"text",@"type", key,@"key", nil]];
  44. }
  45.  
  46. //创建sql语句
  47. NSMutableString *cSql = [NSMutableString stringWithFormat:@"create table if not exists %@ (",self.myTableName];
  48.  
  49. //把非数据类型的字段加入sql语句
  50. for(NSString *key in allArr)
  51. {
  52. [cSql appendFormat:@"%@ text,",key];
  53. }
  54.  
  55. //把数据类型的字段加入Sql语句
  56. if (data != nil)
  57. {
  58. [cSql appendFormat:@"%@ blob,",data];
  59. [self.myTableInfo addObject:[NSDictionary dictionaryWithObjectsAndKeys:@"blob",@"type", data,@"key", nil]];
  60. }
  61.  
  62. //添加主键
  63. [cSql appendString:@"primary key("];
  64.  
  65. int keyCount = [keys count];
  66. if (keyCount > 0)//有多个主键的情况
  67. {
  68. for(int i = 0; i < keyCount - 1; ++i)
  69. {
  70. NSString *key = [keys objectAtIndex:i];
  71. [cSql appendFormat:@"%@,",key];
  72. }
  73.  
  74. if(self.hasUser)
  75. {
  76. [cSql appendString:@"userName,"];
  77. }
  78. [cSql appendFormat:@"%@)",[keys objectAtIndex:keyCount - 1]];
  79. }
  80. else
  81. {
  82. // if (keyCount == 1)//只有一个主键的情况
  83. // {
  84. // [cSql appendFormat:@"%@)",[keys objectAtIndex:0]];
  85. // }
  86. // else
  87. {
  88. if(self.hasUser)
  89. {
  90. [cSql appendString:@"userName)"];
  91. }
  92. }
  93. }
  94.  
  95. [cSql appendString:@")"];
  96.  
  97. LOG_CINFO(@"========sql 语句 创建表=========");
  98. LOG_CINFO(cSql);
  99.  
  100. {
  101. NSMutableDictionary *dic = (NSMutableDictionary *)[GlobalFunc ParseDicFromFile:@"dbInfo.plist"];
  102. if (dic == nil)
  103. {
  104. dic = [NSMutableDictionary dictionaryWithCapacity:1];
  105. }
  106. [dic setObject:self.myTableInfo forKey:self.myTableName];
  107. [GlobalFunc WriteDicToFile:dic FileName:@"dbInfo.plist"];
  108. }
  109.  
  110. return [LocalDataBase CreateTableWithSql:cSql];
  111. }
  1. //向表中插入数据
  2. -(BOOL) InsertDataWithDic:(NSDictionary *)dic Replace:(BOOL) replace {
  3. // 打开数据库
  4. if (!DB_Opened)
  5. {
  6. if(![LocalDataBase OpenDB])
  7. {
  8. LOG_CINFO(@"插入数据失败,打开数据库出错!");
  9. return NO;
  10. }
  11. }
  12.  
  13. NSMutableDictionary *tmpDic = [NSMutableDictionary dictionaryWithDictionary:dic];
  14. if (self.hasUser)
  15. {
  16. [tmpDic setObject:[GlobalData GetInstance].GB_UserName forKey:@"userName"];
  17. }
  18.  
  19. NSMutableArray *allKeys = [NSMutableArray arrayWithArray:[tmpDic allKeys]];
  20.  
  21. NSMutableString *cSql = nil;
  22. //生成插入语句
  23. if (replace)
  24. {
  25. cSql = [NSMutableString stringWithFormat:@"insert or REPLACE into %@(",self.myTableName];
  26. }
  27. else
  28. {
  29. cSql = [NSMutableString stringWithFormat:@"insert into %@(",self.myTableName];
  30. }
  31.  
  32. int keysCount = [allKeys count];
  33.  
  34. if (keysCount > 0)
  35. {
  36. for(int i = 0; i < keysCount-1;++i)
  37. {
  38. [cSql appendFormat:@"%@,",[allKeys objectAtIndex:i]];
  39. }
  40.  
  41. [cSql appendFormat:@"%@)",[allKeys objectAtIndex:keysCount -1]];
  42. }
  43. else
  44. {
  45. return NO;
  46. }
  47.  
  48. [cSql appendString:@" values("];
  49.  
  50. for(int i = 0; i<keysCount -1; ++i)
  51. {
  52. [cSql appendString:@"?,"];
  53. }
  54. [cSql appendString:@"?)"];
  55.  
  56. LOG_CINFO(@"========sql 语句 插入表=========");
  57. LOG_CINFO(cSql);
  58.  
  59. //测试sql 语句是否正确
  60. sqlite3_stmt *statement;
  61.  
  62. const char *insertStatement = [cSql UTF8String];
  63. #if UseASE
  64. //验证sql语句是否成功
  65. const char *key = [[GlobalData GetInstance].GB_DBKey UTF8String];
  66. sqlite3_key(GB_DB, key, strlen(key));
  67. #endif
  68. if(sqlite3_prepare_v2(GB_DB, insertStatement, -1, &statement, NULL) != SQLITE_OK)
  69. {
  70. LOG_CINFO(@"向表格中插入数据失败,可能Sql语句不正确!");
  71. [GlobalFunc ShowNormalAlert:[NSString stringWithFormat:@"向表格中插入数据失败,可能Sql语句不正确,表名为%@",self.myTableName]];
  72. return NO;
  73. }
  74.  
  75. for(int i = 0; i < keysCount;++i)
  76. {
  77. NSString *key = [allKeys objectAtIndex:i];
  78.  
  79. id value = [tmpDic objectForKey:key];
  80.  
  81. //如果是Data类型
  82. if ([value isKindOfClass:[NSData class]])
  83. {
  84. sqlite3_bind_blob(statement, i+1, [value bytes], [value length], NULL);
  85. }
  86. else//是字符串类型
  87. {
  88. sqlite3_bind_text(statement, i+1, [value UTF8String], -1, NULL);
  89. }
  90. }
  91.  
  92. int success = sqlite3_step(statement);
  93. // 释放资源
  94. sqlite3_finalize(statement);
  95.  
  96. if (success == SQLITE_ERROR)
  97. {
  98. LOG_CINFO(@"向表格中插入数据失败,未知原因提前结束!");
  99. [GlobalFunc ShowNormalAlert:[NSString stringWithFormat:@"向表格中插入数据失败,未知原因提前结束,表名为%@",self.myTableName]];
  100. return NO;
  101. }
  102. LOG_CINFO(@"向表格中插入数据成功!");
  103. return YES;
  104.  
  105. }
  1. //更新表字段,key是要更新的字段名称,newValue是更新后要设计的值,where是条件(sql语句中的),condition是满足更新的条件,use是否使用用户名为条件
  2. -(BOOL) UpdateRecordWithKey:(NSString *)key Value:(NSString *)newValue Where:(NSString *)where Condition:(NSString *)condition UseUser:(BOOL)use {
  3. if(![LocalDataBase OpenDB])
  4. {
  5. return NO;
  6. }
  7. @try
  8. {
  9. NSString *tmpUpdateSql = nil;
  10.  
  11. if (use && self.hasUser)
  12. {
  13. tmpUpdateSql = [NSString stringWithFormat:@"UPDATE %@ SET %@ = ? where %@ = ? and userName = ?",self.myTableName,key,where];
  14. }
  15. else
  16. {
  17. tmpUpdateSql = [NSString stringWithFormat:@"UPDATE %@ SET %@ = ? where %@ = ?",self.myTableName,key,where];//@"UPDATE tb_bulletlist SET has_read = ? where bulletin_code = ? and user_name=?";
  18. }
  19. sqlite3_stmt *statement;
  20.  
  21. LOG_CINFO(@"========sql 语句 更新表=========");
  22. LOG_CINFO(tmpUpdateSql);
  23. #if UseASE
  24. //验证sql语句是否成功
  25. const char *key = [[GlobalData GetInstance].GB_DBKey UTF8String];
  26. sqlite3_key(GB_DB, key, strlen(key));
  27. #endif
  28. if(sqlite3_prepare_v2(GB_DB, [tmpUpdateSql UTF8String], -1, &statement, nil) != SQLITE_OK)
  29. {
  30. LOG_CINFO(@"更新数据失败!");
  31. [GlobalFunc ShowNormalAlert:[NSString stringWithFormat:@"更新数据失败,表名为%@",self.myTableName]];
  32. return NO;
  33. }
  34.  
  35. sqlite3_bind_text(statement, 1, [newValue UTF8String], -1, NULL);
  36. sqlite3_bind_text(statement, 2, [condition UTF8String], -1, NULL);
  37.  
  38. if (use && self.hasUser)
  39. {
  40. sqlite3_bind_text(statement, 3, [[GlobalData GetInstance].GB_UserName UTF8String], -1, NULL);
  41. }
  42. int success = sqlite3_step(statement);
  43.  
  44. sqlite3_finalize(statement);
  45. //[MyDataBase CloseDB];
  46. if (success != SQLITE_DONE)
  47. {
  48. LOG_CINFO(@"更新数据失败,未知原因提前结束!");
  49. [GlobalFunc ShowNormalAlert:[NSString stringWithFormat:@"更新数据失败,未知原因提前结束,表名为%@",self.myTableName]];
  50. return NO;
  51. }
  52.  
  53. }
  54. @catch (NSException *e)
  55. {
  56. // LOG_CERR(e);
  57. }
  58.  
  59. return YES;
  60. }
  1. //根据传入的关键字和关键字的值,得到一条记录,如果不存在这条记录,返回为nil,估也可用来判断是否存在某条记录,use是否使用用户名为条件
  2. -(NSMutableDictionary *) GetOneRecordWithKeys:(NSArray *)keys Values:(NSArray *)values UseUser:(BOOL)use {
  3. if ([keys count] != [values count])
  4. {
  5. // [GlobalFunc ShowNormalAlert:[NSString stringWithFormat:@"GetOneRecordWithKeys 数据查询参数keys与values个数不一致,表名为%@",self.myTableName]];
  6.  
  7. return nil;
  8. }
  9.  
  10. // 打开数据库
  11. if (!DB_Opened)
  12. {
  13. if(![LocalDataBase OpenDB])
  14. {
  15. LOG_CINFO(@"查询数据失败,打开数据库出错!");
  16. return nil;
  17. }
  18. }
  19.  
  20. NSMutableString *cSql = [NSMutableString stringWithFormat:@"select * from %@ where ",self.myTableName];
  21. if (use && self.hasUser)
  22. {
  23. [cSql appendFormat:@"userName = '%@' and ",[GlobalData GetInstance].GB_UserName];
  24. }
  25.  
  26. int keyCount = [keys count];
  27. for (int i = 0; i < keyCount; ++i)
  28. {
  29. if (i == 0)
  30. {
  31. [cSql appendFormat:@"%@ = '%@'",[keys objectAtIndex:i],[values objectAtIndex:i]];
  32. }
  33. else
  34. {
  35. [cSql appendFormat:@" and %@ = '%@'",[keys objectAtIndex:i],[values objectAtIndex:i]];
  36. }
  37.  
  38. }
  39.  
  40. NSArray *tmpArr = [self GetDataArrWithSql:cSql];
  41.  
  42. if ([tmpArr count] == 0)
  43. {
  44. return nil;
  45. }
  46. else
  47. {
  48. return [tmpArr objectAtIndex:0];
  49. }
  50. }

  如果在编译时提示: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. mvc分页生成静态页,mvc生成静态页

    http://blog.csdn.net/xxj_jing/article/details/7899125 分页生成静态页 http://www.cnblogs.com/luanyilin/archi ...

  2. (转)实例详解CSS中position的fixed属性使用

    关于fixed属性,在什么情况下需要用,怎么用,首先,我们应该先了解下fixed属性的说明:fixed总是以body为定位时的对象,总是根据浏览器的窗口来进行元素的定位,通过"left&qu ...

  3. 对list代理扩展功能

    package 动态代理扩展List; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; imp ...

  4. python 3.6 import pymysql错误

    在3.x之后可以用pymysql来代替之前的mysqldb模块. 首先安装pip: 终端命令: easy_install pip 随后成功安装pip 继续输入命令 pipinstall PyMySQL ...

  5. 跨平台渲染框架尝试 - Texture管理

    纹理是渲染器重要的资源,也是比较简单的资源.本文将详细讨论纹理资源的管理. 在资源管理概述中提到,资源就是一堆内存和CPU与GPU的访问权限.纹理管理在资源管理之上,要负责如何使用者一堆内存构造纹理对 ...

  6. [android]android开发中的运行错误之:adb.exe

    调试的时候出现一下错误: The connection to adb is down, and a servera error has occured.You must restart adb and ...

  7. 解决方案:elipse一直loading descriptor for...

    1,问题描述: 打开eclipse,一直在loading descriptor for...,eclipse假死,什么操作都做不了 2,环境描述: Java Compiler:1.8 Jdk :1.8 ...

  8. android的编译和运行过程深入分析

    android的编译和运行过程深入分析 作者: 字体:[增加 减小] 类型:转载 首先来看一下使用Java语言编写的Android应用程序从源码到安装包的整个过程,此过程对了解android的编译和运 ...

  9. Equations(hdu 1496 二分查找+各种剪枝)

    Equations Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total S ...

  10. POJ 1564 Sum It Up(DFS)

    Sum It Up Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Submit St ...