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

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

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

% 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語言所写,实现基本的傳輸層資料加密功能。

第二个

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

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

这个就是 sqlcipher 的project code了

第三个

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

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

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

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

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

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

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

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

3.添加子项目的引用

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

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

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

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

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

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

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

iOS的话 会是这样

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

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

进行如下配置

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

接下来讲述使用

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

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

-(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

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

时间: 2016-12-05

iOS中MD5加密算法的介绍和使用

前言 软件开发过程中,对数据进行加密是保证数据安全的重要手段,常见的加密有Base64加密和MD5加密.Base64加密是可逆的,MD5加密目前来说一般是不可逆的. MD5生成的是固定的128bit,即128个0和1的二进制位,而在实际应用开发中,通常是以16进制输出的,所以正好就是32位的16进制,说白了也就是32个16进制的数字. MD5主要特点是 不可逆,相同数据的MD5值肯定一样,不同数据的MD5值不一样(也不是绝对的,但基本是不能一样的). MD5算法还具有以下性质: 1.压缩性:任意

ios常见加密解密方法(RSA、DES 、AES、MD5)

最近做了一个移动项目,是有服务器和客户端类型的项目,客户端是要登录才行的,服务器也会返回数据,服务器是用Java开发的,客户端要同时支持多平台(Android.iOS),在处理iOS的数据加密的时候遇到了一些问题.起初采取的方案是DES加密,老大说DES加密是对称的,网络抓包加上反编译可能会被破解,故采取RSA方式加密.RSA加密时需要公钥和私钥,客户端保存公钥加密数据,服务器保存私钥解密数据.(iOS端公钥加密私钥解密.java端公钥加密私钥解密,java端私钥加密公钥解密都容易做到,iOS不

iOS中使用RSA加密详解

在iOS中使用RSA加密解密,需要用到.der和.p12后缀格式的文件,其中.der格式的文件存放的是公钥(Public key)用于加密,.p12格式的文件存放的是私钥(Private key)用于解密. 首先需要先生成这些文件,然后再将文件导入工程使用,不多说,开始做! 一.使用openssl生成所需秘钥文件 生成环境是在mac系统下,使用openssl进行生成,首先打开终端,按下面这些步骤依次来做: 1. 生成模长为1024bit的私钥文件private_key.pem openssl g

一行代码实现IOS 3DES加密解密

3DES(或称为Triple DES)是三重数据加密算法(TDEA,Triple Data Encryption Algorithm)块密码的通称.它相当于是对每个数据块应用三次DES加密算法.由于计算机运算能力的增强,原版DES密码的密钥长度变得容易被暴力破解:3DES即是设计用来提供一种相对简单的方法,即通过增加DES的密钥长度来避免类似的攻击,而不是设计一种全新的块密码算法. 3DES又称Triple DES,是DES加密算法的一种模式,它使用3条56位的密钥对数据进行三次加密.数据加密标

iOS中使用MD5加密字符串

1,新建NSString的分类,记得添加加密所需的头文件#import <CommonCrypto/CommonDigest.h> , NSString+MD5.h: #import <Foundation/Foundation.h> #import <CommonCrypto/CommonDigest.h> @interface NSString (MD5) + (NSString *)md5To32bit:(NSString *)str; @end 2,编写加密方法

iOS给密码进行加密的方法

一,工程图. 二,代码. #import "ViewController.h" #import "Base64CodeByteFunc.h" @interface ViewController () @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typic

简单讲解iOS应用开发中的MD5加密的相关使用

一.简单说明 1.说明 在开发应用的时候,数据的安全性至关重要,而仅仅用POST请求提交用户的隐私数据,还是不能完全解决安全问题. 如:可以利用软件(比如Charles)设置代理服务器,拦截查看手机的请求数据 "青花瓷"软件 因此:提交用户的隐私数据时,一定不要明文提交,要加密处理后再提交 2.常见的加密算法 MD5 \ SHA \ DES \ 3DES \ RC2和RC4 \ RSA \ IDEA \ DSA \ AES 3.加密算法的选择 一般公司都会有一套自己的加密方案,按照公司

Android、iOS和Java通用的AES128加密解密示例代码

前言 移动端越来越火了,我们在开发过程中,总会碰到要和移动端打交道的场景,比如android和iOS的打交道.为了让数据交互更安全,我们需要对数据进行加密传输. 这篇文章给大家分享AES的加密和解密.Android和ios通用的AES加密算法.大家可以直接集成到自己的项目.服务器接口如果是用Java写的话.整个框架都完美了.如果是.NET编写的后台接口的话.得改造一下哦 IOS加密 /*加密方法*/ (NSString *)AES256EncryptWithPlainText:(NSString

iOS常用加密算法介绍和代码实践

iOS系统库中定义了软件开发中常用的加解密算法,接口为C语言形式.具体包括了以下几个大类: #include <CommonCrypto/CommonCryptor.h> //常用加解密算法 #include <CommonCrypto/CommonDigest.h> //摘要算法 #include <CommonCrypto/CommonHMAC.h> #include <CommonCrypto/CommonKeyDerivation.h> #inclu

总结iOS开发中的断点续传与实践

前言 断点续传概述 断点续传就是从文件上次中断的地方开始重新下载或上传数据,而不是从文件开头.(本文的断点续传仅涉及下载,上传不在讨论之内)当下载大文件的时候,如果没有实现断点续传功能,那么每次出现异常或者用户主动的暂停,都会去重头下载,这样很浪费时间.所以项目中要实现大文件下载,断点续传功能就必不可少了.当然,断点续传有一种特殊的情况,就是 iOS 应用被用户 kill 掉或者应用 crash,要实现应用重启之后的断点续传.这种特殊情况是本文要解决的问题. 断点续传原理 要实现断点续传 , 服

Java实现常用加密算法——单向加密算法MD5和SHA

本文主要介绍了Java实现常用加密算法--单向加密算法MD5和SHA,具体如下: 1.Java的安全体系架构 1.1 Java的安全体系架构介绍 Java中为安全框架提供类和接口.JDK 安全 API 是 Java 编程语言的核心 API,位于 java.security 包(及其子包),以及sun.securityAPI包(及其子包)中.设计用于帮助开发人员在程序中同时使用低级和高级安全功能. JDK 1.1 中第一次发布的 JDK 安全中引入了"Java 加密体系结构"(JCA),

Android常用的数据加密方式代码详解

前言 Android 很多场合需要使用到数据加密,比如:本地登录密码加密,网络传输数据加密,等.在android 中一般的加密方式有如下: 亦或加密  AES加密  RSA非对称加密  MD5加密算法 当然还有其他的方式,这里暂且介绍以上四种加密算法的使用方式. 亦或加密算法 什么是亦或加密? 亦或加密是对某个字节进行亦或运算,比如字节 A^K = V,这是加密过程; 当你把 V^K得到的结果就是A,也就是 V^K = A,这是一个反向操作过程,解密过程. 亦或操作效率很高,当然亦或加密也是比较

iOS常用算法之两个有序数组合并(要求时间复杂度为0(n))

思路: 常规思路: 先将一个数组作为合并后的数组, 然后遍历第二个数组的每项元素, 一一对比, 直到找到合适的, 就插入进去; 简单思路: 设置数组C, 对比A和B数组的首项元素, 找到最小的, 就放入数组C,依次进行下去. 代码如下: - (NSArray *)mergeOrderArrayWithFirstArray: (NSMutableArray *)array1 secondArray: (NSMutableArray *)array2 { // 全为空不处理 if (!array1.

iOS AFNetworking中cookie重定向代码

// 1. 取出需要同步的url (登录请求中返回的重定向地址) BESTHttpItem *httpItem = [BESTHttpHelper sharedHelper].curHttpItem; NSString *url = [NSString stringWithFormat:@"%@/#/login", httpItem.frontend_addr]; // 2. 取出当前的headerFields NSDictionary *headerFields = [NSHTTPC

ReactiveCocoa代码实践之-UI组件的RAC信号操作

相关阅读: ReactiveCocoa代码实践之-更多思考 ReactiveCocoa代码实践之-RAC网络请求重构这一节是自己对网络层的一些重构,本节是自己一些代码小实践做出的一些demo程序,基本涵盖大多数UI控件操作. 一.用UISlider实现调色板 假设我们现在做一个demo,上面有一个View用来展示颜色,下面有三个UISlider滑竿分别控制RGB的色值,随着不同滑竿的拖动上面view的颜色会随之改变. 可以先脑补一下不用RAC该怎么写. 如果使用RAC只需要将三个信号包装起来用适

iOS 获得现在的时间代码

一, 代码. - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. //获得现在的时间 [self currentTime]; } #pragma -mark -functions //计算现在的时间 - (void)currentTime { //时间格式 NSDateFormatter *dateFormatter

iOS 图片旋转方法实例代码

通过 CGImage 或 CIImage 旋转特定角度 UIImage可通过CGImage或CIImage初始化,初始化方法分别为init(cgImage: CGImage, scale: CGFloat, orientation: UIImageOrientation)和init(ciImage: CIImage, scale: CGFloat, orientation: UIImageOrientation).通过UIImageOrientation的不同取值,可以使图片旋转90.180.2

python数据类型_元组、字典常用操作方法(介绍)

元组 Python的元组与列表类似,不同之处在于元组的元素不能修改. 元组使用小括号,列表使用方括号. 元组创建很简单,只需要在括号中添加元素,并使用逗号隔开即可. tp=(1,2,3,'a','b') a = 'hello world' #这样定义是str类型 b = ('hello world') #定义元组时,如果只有一个元素,那么b的类型就是str c = ('hello world',) print(type(c)) 元组只有count和index方法,如下: tp = ('127.0