在实现SQLCipher

时间:2017-08-25 08:15:34

标签: c# sqlite xamarin sqlcipher couchbase-lite

所以,

我想要的是什么:

能够告诉Couchbase Lite(CB Lite)存储数据的位置并在其上实现SQLCipher加密。

我的问题是什么:

即使我对默认目录进行了加密,但只要我告诉Manager使用自定义目录,它就会在尝试创建数据库时抛出异常: 消息:

  

"错误8,1032(尝试编写只读数据库)执行sql' CREATE INDEX docs_docid ON docs(docid)'"

来源:

  

" Couchbase.Lite.Storage.SQLCipher"

堆栈跟踪:

  

"在/ Users / jenkins / jenkins / workspace /中的Couchbase.Lite.Storage.SQLCipher.SqlitePCLRawStorageEngine.ExecSQL(System.String sql,SQLitePCL.sqlite3 db,System.Object [] paramArgs)[0x00079] couchbase-lite-net-build@2/1.4/Android/couchbase-lite-net/src/StorageEngines/SQLiteCommon/storage.sqlite.common/src/DatabaseUpgraderFactory_Upgraders.cs:249 \ n在Couchbase.Lite.Storage.SQLCipher。 SqlitePCLRawStorageEngine.ExecSQL(System.String sql,System.Object [] paramArgs)< 0xd70821f8 + 0x0005f> in< 223c4357c0d44faaaa01c387793a30cc>:0 \ n在Couchbase.Lite.Storage.SQLCipher.SqlitePCLRawStorageEngine.Open(System.String path,System.Boolean readOnly,System.String schema,Couchbase.Lite.Store.SymmetricKey encryptionKey)[0x00065] in /Users/jenkins/jenkins/workspace/couchbase-lite-net-build@2/1.4/Android/couchbase-lite-net/src/StorageEngines/SQLiteCommon/storage.sqlite.common/src/DatabaseUpgraderFactory.cs:87&# 34;

现在,奇怪的是,在模拟器上运行我的代码时,它不会抛出任何异常。只有在真实设备(Lenovo TAB 2A Series,Android 5.0.1)上运行我的代码时才会出现此问题。

注意:即使抛出了异常,也会创建自定义文件夹,也会创建couchbase lite文件夹,但在其中只能找到名为db.sqlite3的文件。通常会创建三个文件和一个文件夹: enter image description here

注2:我已将 WRITE_EXTERNAL_STORAGE 权限添加到Android Manifest。

运行的代码没有问题:

public async Task<Database> OpenDatabaseOnEncryptedWayAsync(string encryptionPassword)
    {
        Database encryptedDatabase = null;

        try
        {
            SymmetricKey Key;
            DatabaseOptions options = new DatabaseOptions();
            await Task.Run(() =>
            {
                Key = new SymmetricKey(encryptionPassword);
                options.EncryptionKey = Key;
                options.Create = true;
                options.StorageType = StorageEngineTypes.SQLite;
            });

            // Database stored in default directory
            encryptedDatabase = Manager.SharedInstance.OpenDatabase(database, options);
        }
        catch (CouchbaseLiteException e)
        {
            LogWriterMethod.TryWriteLog(String.Format("Error while creating encrypted database: {0}", e)); 
            Console.WriteLine("Encryption Message: {0}", e);
        }
        catch (Exception e)
        {
            LogWriterMethod.TryWriteLog(String.Format("Unhandled Exception on OpenDatabaseOnEncryptedWayAsync method: {0}", e));
            Console.WriteLine("Unhandled Exception Message: {0}", e);
        }

        App.SettingsViewModel.isDatabaseOpen = encryptedDatabase != null;

        return encryptedDatabase;
    }

抛出(CouchbaseLite)异常的代码:

    public async Task<Database> OpenDatabaseOnEncryptedWayAsync(string encryptionPassword)
    {            
        Database encryptedDatabase = null;

        try
        {
            SymmetricKey Key;
            DatabaseOptions options = new DatabaseOptions();
            await Task.Run(() =>
            {
                Key = new SymmetricKey(encryptionPassword);
                options.EncryptionKey = Key;
                options.Create = true;
                options.StorageType = StorageEngineTypes.SQLite;
            });

            // Custom directory
            var path = Android.OS.Environment.GetExternalStoragePublicDirectory(Android.OS.Environment.DirectoryDownloads).Path;
            var dir = Directory.CreateDirectory(path);
            Manager manager = new Manager(dir, Manager.DefaultOptions);
            encryptedDatabase = manager.GetDatabase(database);
        }
        catch (CouchbaseLiteException e)
        {
            LogWriterMethod.TryWriteLog(String.Format("Error while creating encrypted database: {0}", e)); 
            Console.WriteLine("Encryption Message: {0}", e);
        }
        catch (Exception e)
        {
            LogWriterMethod.TryWriteLog(String.Format("Unhandled Exception on OpenDatabaseOnEncryptedWayAsync method: {0}", e));
            Console.WriteLine("Unhandled Exception Message: {0}", e);
        }

        App.SettingsViewModel.isDatabaseOpen = encryptedDatabase != null;

        return encryptedDatabase;
    }

那么,那里有人知道如何处理这个问题吗?在此先感谢:)

1 个答案:

答案 0 :(得分:0)

回到主题,我发现抛出(CouchbaseLite)异常的代码中有一个非常简单的错误。我分享它,以防任何人阅读这个错误:

我正在创建目录,然后使用新路径创建管理器,但我从未将DatabaseOptions分配给新创建的Manager

SymmetricKey Key;
DatabaseOptions options = new DatabaseOptions();
await Task.Run(() =>
{
    Key = new SymmetricKey(encryptionPassword);
    options.EncryptionKey = Key;
    options.Create = true;
    options.StorageType = StorageEngineTypes.SQLite;
});
var path = Android.OS.Environment.GetExternalStoragePublicDirectory(Android.OS.Environment.DirectoryDownloads).Path;
var dir = Directory.CreateDirectory(path);
Manager manager = new Manager(dir, Manager.DefaultOptions);
encryptedDatabase = manager.GetDatabase(database);

因此,我们所要做的就是将代码更改为

encryptedDatabase = manager.OpenDatabase(database, options);

就是这样!