So,
Что я хочу:
Чтобы иметь возможность указать Couchbase Lite (CB Lite), где хранить данные и внедрить на них шифрование SQLCipher.
В чем моя проблема:
Несмотря на то, что шифрование работает в каталоге по умолчанию, как только я говорю менеджеру использовать пользовательский каталог, он выдает исключение при попытке создать базу данных: Сообщение:
«Ошибка 8, 1032 (попытка записи базы данных только для чтения) при выполнении sql «CREATE INDEX docs_docid ON docs (docid)»»
Источник:
"Couchbase.Lite.Storage.SQLCipher"
Трассировки стека:
«в Couchbase.Lite.Storage.SQLCipher.SqlitePCLRawStorageEngine.ExecSQL (System.String sql, SQLitePCL.sqlite3 db, System.Object [] paramArgs) [0x00079] в /Users/jenkins/jenkins/workspace/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 at Couchbase.Lite.Storage.SQLCipher.SqlitePCLRawStorageEngine.Open (путь System.String, схема System.String только для чтения, System.String , Couchbase.Lite.Store.SymmetricKey EncryptionKey) [0x00065] в /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 "
Теперь странно то, что при запуске моего кода на эмуляторе он не выдает никаких исключений. Проблема возникает только при запуске моего кода на реальном устройстве (Lenovo TAB 2A Series, Android 5.0.1).
Примечание. Несмотря на то, что создается исключение, пользовательская папка создается, а также папка для дивана lite, но внутри нее находится только файл с именем db.sqlite3. Обычно создаются три файла и папка:
Примечание 2. я добавил разрешение WRITE_EXTERNAL_STORAGE в манифест Android.
Код, который работает без проблем:
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;
}
Итак, кто-нибудь знает, как справиться с этой проблемой? Заранее спасибо :)