首页 > ios > 自制的Sqlcipher和OpenSSL framework的实战应用

自制的Sqlcipher和OpenSSL framework的实战应用

  按照老传统首先得感谢一番,就把需要对我帮助过的部分参考给亮出来:

  1. sqlcipher配置 http://sqlcipher.net/ios-tutorial/
  2. sqlcipher API http://sqlcipher.net/sqlcipher-api/
  3. github上的sqlcipher https://github.com/sqlcipher/
  4. sqlcipher使用 http://jordy.easymorse.com/?p=970
  5. github上的sqlcipher测试 https://github.com/sqlcipher/SQLCipherSpeed
  6. 代替OpenSSL的官方代替库 Security.framework

  感谢之后,再上一些实际的代码,以检验这个流程是否正常。

加密数据库几种方式

1.shell方式加密一个sqlite

sqlcipher test.db
> PRAGMA key='test'; //必须在打开数据库第一步来执行

2.Object-c代码实现对一个非加密库导入到加密库的方法(已经验证)(Xcode)

NSString *databasePath = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0]
                              stringByAppendingPathComponent: @"sqlcipher.db"];
    NSLog(@"databasePath: %@",databasePath);
    
    sqlite3 *db;
    if (sqlite3_open([databasePath UTF8String], &db) == SQLITE_OK) {
        const char* key = [@"BIGSecret" UTF8String];
        sqlite3_key(db, key, strlen(key));
        if (sqlite3_exec(db, (const char*) "SELECT count(*) FROM sqlite_master;", NULL, NULL, NULL) == SQLITE_OK) {
            // password is correct, or, database has been initialized
            NSLog(@"打开数据库成功");
            char *errorMsg;
            const char *createSql="create table if not exists persons (id integer primary key autoincrement,name text)";
            
            if (sqlite3_exec(db, createSql, NULL, NULL, &errorMsg)==SQLITE_OK) {
                NSLog(@"create ok.");
            }
            
            const char *insertSql="insert into persons (name) values('张三')";
            if (sqlite3_exec(db, insertSql, NULL, NULL, &errorMsg)==SQLITE_OK) {
                NSLog(@"insert ok.");
            }
            
            const char *selectSql="select id,name from persons";
            sqlite3_stmt *statement;
            if (sqlite3_prepare_v2(db, selectSql, -1, &statement, nil)==SQLITE_OK) {
                NSLog(@"select ok.");
            }
            
            while (sqlite3_step(statement)==SQLITE_ROW) {
                int _id=sqlite3_column_int(statement, 0);
                NSString *name=[[NSString alloc] initWithCString:(char *)sqlite3_column_text(statement, 1) encoding:NSUTF8StringEncoding];
                NSLog(@"row>>id %i, name %@",_id,name);
            }
            
        } else {
            // incorrect password!
        }
        
        sqlite3_close(db);
    }

为加密数据库解密

1.先导出现有库的数据(In shell)

sqlcipher plaintext.db
.output dsa.sql
.dump

将新的数据库导出,并加密,之后导入非加密的库里面的数据

sqlcipher another.db
PRAGMA key='aaa';
.read dsa.sql

2. 为加密后的sqlite执行解密(其实步骤与加密一样,只要把key设置为空就实现了不加密)

ATTACH DATABASE 'encrypted.db' as encrypted KEY ''; //encrypted.db是要导出的新的数据库
SELECT sqlcipher_export('encrypted');
DETACH DATABASE encrypted;

3.(In shell)

sqlciper test.db
PRAGMA KEY='helloworld';#第一步必须执行
ATTACH DATABASE 'encrypted.db' as encrypted KEY '';
SELECT sqlcipher_export('encrypted');
DETACH DATABASE encrypted;

void Md5( NSString * string){
    // 输入参数 1 :要生成 md5 值的字符串, NSString-->uchar*
    unsigned char *inStrg = ( unsigned char *)[[string dataUsingEncoding : NSASCIIStringEncoding ] bytes];
    // 输入参数 2 :字符串长度
    unsigned long lngth = [string length ];
    // 输出参数 3 :要返回的 md5 值, MD5_DIGEST_LENGTH 为 16bytes , 128 bits
    unsigned char result[ MD5_DIGEST_LENGTH ];
    // 临时 NSString 变量,用于把 uchar* 组装成可以显示的字符串: 2 个字符一 byte 的 16 进制数
    NSMutableString *outStrg = [ NSMutableString string ];
    // 调用 OpenSSL 函数
    MD5 (inStrg, lngth, result);
    unsigned int i;
    for (i = 0 ; i < MD5_DIGEST_LENGTH ; i++)
    {
        [outStrg appendFormat : @"%02x" , result[i]];
    }
    NSLog ( @"input string:%@" ,string);
    NSLog ( @"md5:%@" ,outStrg);
}
- (void)viewDidLoad
{
    ...
    Md5(@"asd");
    ...
}

运行完之后,在上述打印的databasePath路径下,如果通过Navitcat直接链接数据会提示该文件已加密说明我们制作的framework已经成功了。
但是细心的朋友会发现在代码:
sqlite3_key(db, key, strlen(key));
这一行中有一个警告,提示内容是:Implicit declaration of function ‘sqlite3_key’ is invalid in C99
或者是说这个sqlite3_key方法是无效的。
经过google后,可以在UseSwlcipherDemo工程的BuildSettings选项卡,搜索C Language Dialect并
将设置属性为:
图片
选择蓝色的这个。再次编译则不会再显示警告。

开源的Demo请飞跃至github:
https://github.com/sunchaofan/Sqlcipher-OpenSSL

  1. 还没有评论
评论提交中, 请稍候...

留言


可以使用的标签: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>
Trackbacks & Pingbacks ( 0 )
  1. 还没有 trackbacks