Titanium JIRA Archive
Appcelerator Community (AC)

[AC-6231] Encrypted Database Module - Unable to use encrypted database after ATTACH Database operation

GitHub Issuen/a
TypeBug
Priorityn/a
StatusResolved
ResolutionDone
Resolution Date2019-05-06T23:26:06.000+0000
Affected Version/sn/a
Fix Version/sn/a
ComponentsAppcelerator Modules
Labelsdatabase, encrypted_database
ReporterMark Henderson
AssigneeShak Hossain
Created2019-04-28T12:52:16.000+0000
Updated2019-05-06T23:26:06.000+0000

Description

I am transitioning my app to use SQLCipher through the 'appcelerator.encrypteddatabase' module. Existing devices will have an unencrypted SQLite database which the app will need to do a sqlcipher_export() on. See documentation here [https://www.zetetic.net/sqlcipher/sqlcipher-api/#sqlcipher_export](https://www.zetetic.net/sqlcipher/sqlcipher-api/#sqlcipher_export) I am now able to get the ATTACH command to work. But I cannot use the database for anything afterwards. It is as though the encrypteddatabase module is holding on to a reference to the DB. See my attached app.js example. 1.You can click the first button as many times as you like to create and add data to an unencrypted DB. 2. This will create an encrypted DB, attach it, export it. 3. This will now cause an exception 4. Restart the app 5. Button 3 now works perfectly. I have tried everything I can think of to get around this, and there's nothing in the SQLCipher documentation that I appear to be doing wrong. Thanks for your help!. [^app.js]

Attachments

FileDateSize
app.js2019-04-29T09:31:11.000+00004148
Screen Shot 2019-04-29 at 4.37.51 PM.png2019-04-29T10:39:32.000+000035899

Comments

  1. Rakhi Mitro 2019-04-29

    Hello [~mark.henderson@snagr.co.uk], Thanks for reporting this . Are you using 7.5.2SDK for build? Can you please test on 8.0.0.GA? And also share the console logs here.
  2. Mark Henderson 2019-04-29

    Technically I'm using 7.5.2GA for production. But for this test I've also tried with 8.0.0GA. I'm pretty sure this is a bug with EncryptedDatabase module, as I've re-written this code 5 different ways today and tried almost everything. Whatever is locking it is removed when you re-launch the app. But after the attach / export / detach the database is completely locked. I also tried the second method of exporting a plaintext database into a new encrypted database. But this module gives an error message 'incorrect number of arguments'. I can also see that this module is using SQLCipher v3 not v4, as I need to set DB Browser for SQLite to this mode in order to decrypt and view the database. So I think it should be updated internally if there is a bug. Here are the console logs:
       [ERROR] :  file is not a database
       [ERROR] :  A SQLite database error occurred on database '/Users/mark/Library/Developer/CoreSimulator/Devices/1D771BB8-BA4E-4C52-ADBA-E08AEC0E4B91/data/Containers/Data/Application/C04413E4-9003-40E9-90F3-0F14D343D473/Library/Private Documents/encryptedDB.db.sql': Error Domain=com.plausiblelabs.EncPLDatabase Code=4 "Cipher migrate: failed to attach new database." UserInfo={com.plausiblelabs.EncPLDatabase.error.vendor.string=file is not a database, NSLocalizedDescription=Cipher migrate: failed to attach new database., com.plausiblelabs.EncPLDatabase.error.vendor.code=26} (SQLite #26: file is not a database) (query: '<none>')
       [ERROR] :  Script Error {
       [ERROR] :      column = 42;
       [ERROR] :      line = 97;
       [ERROR] :      message = "Couldn't open database and migrate";
       [ERROR] :      nativeLocation = "";
       [ERROR] :      nativeReason = "encryptedDB.db";
       [ERROR] :      nativeStack = "3   testAttach 0x000000010793f7fd -[AppceleratorEncrypteddatabaseDBProxy open:] + 560\n4   testAttach 0x000000010793b519 -[AppceleratorEncrypteddatabaseModule open:] + 373\n5   CoreFoundation  0x000000010def94cc __invoking___ + 140\n6   CoreFoundation  0x000000010def6a45 -[NSInvocation invoke] + 325\n7   TitaniumKit0x000000010cc02c89 -[KrollMethod call:] + 1385\n8   TitaniumKit0x000000010cc01dcb __KrollCallAsFunction_block_invoke + 30\n9   TitaniumKit0x000000010cc01bdc KrollCallAsFunction + 496\n10  JavaScriptCore  0x0000000107ecc8d3 _ZN3JSC16JSCallbackObjectINS_20JSDestructibleObjectEE4callEPNS_9ExecStateE + 515\n11  JavaScriptCore  0x00000001083724fc _ZN3JSC5LLInt9setUpCallEPNS_9ExecStateENS_22CodeSpecializationKindENS_7JSValueEPNS_17LLIntCallLinkInfoE + 380\n12  JavaScriptCore  0x0000000107e97b63 llint_entry + 61648\n13  JavaScriptCore  0x0000000107e888d9 vmEntryToJavaScript + 200\n14  JavaScriptCore  0x000000010826e730 _ZN3JSC11Interpreter11executeCallEPNS_9ExecStateEPNS_8JSObjectENS_8CallTypeERKNS_8CallDataENS_7JSValueERKNS_7ArgListE + 464\n15  JavaScriptCore  0x00000001084b3634 _ZN3JSC12profiledCallEPNS_9ExecStateENS_15ProfilingReasonENS_7JSValueENS_8CallTypeERKNS_8CallDataES3_RKNS_7ArgListE + 196\n16  JavaScriptCore  0x0000000107ed36fe JSObjectCallAsFunction + 478\n17  TitaniumKit0x000000010cbde3e2 __TiBindingEventProcess_block_invoke + 53\n18  TitaniumKit0x000000010cbde30a TiBindingEventProcess + 723\n19  TitaniumKit0x000000010cbffdf5 -[KrollContext invoke:] + 109";
       [ERROR] :      sourceURL = "file:///Users/mark/Library/Developer/CoreSimulator/Devices/1D771BB8-BA4E-4C52-ADBA-E08AEC0E4B91/data/Containers/Bundle/Application/FE136192-6854-4DB9-893B-120FD5A806EE/testAttach.app/app.js";
       [ERROR] :      stack = "    at [native code]\n    at testExisting(/app.js:97:42)";
       [ERROR] :      toJSON = "<KrollCallback: 0x600000dec680>";
       [ERROR] :  }
       
    Thanks!
  3. Mark Henderson 2019-05-03

    Hi Shak, do let me know if there's any other information you require. I'm happy to help with any testing etc.. Unfortunately as the module is closed source I can't do too much.
  4. Mark Henderson 2019-05-04

    I seem to have got this working finally.. It seems for iOS by checking the cipher upgrade and also making sure that after initialising appcelerator.encrypteddatabase I only use that to open database connections, not Ti.Database anymore. Here's the change to the code in case it helps anyone else in the future:
       function createEncryptedDBAttachAndExport() {
          		 		
       		//set password in case we are creating a new encrypted DB not opening
       		EncryptedDatabase.password = 'testkey';
       		
       		var newDB = EncryptedDatabase.open(newDBName);
       		if (Ti.Platform.osname !== 'android') {
       			Ti.API.info('UpgradeRequired? ' + newDB.isCipherUpgradeRequired(newDBName));
       		}
       		var encDBFilePath = newDB.file.nativePath;
       		newDB.close();
       		newDB = null;
       		
       		/*var origDB = Ti.Database.open(databaseName);
       		var origDBFilePath = origDB.file.nativePath;
       		origDB.close();
       		origDB = null;*/
       	
       	
       		//set password back to plaintest database so we can export
       		EncryptedDatabase.password = '';
       		
          		var unEncryptedDB = EncryptedDatabase.open(databaseName);
          		unEncryptedDB.execute("ATTACH DATABASE '" + encDBFilePath + "' AS encrypted KEY 'testkey'");
       		unEncryptedDB.execute("SELECT sqlcipher_export('encrypted')");
          		unEncryptedDB.execute("DETACH DATABASE encrypted");  		
          		unEncryptedDB.close();
          		unEncryptedDB = null;
          		
       		//reset key back again
       		EncryptedDatabase.password = 'testkey';
       		
       		// wrong number of arguments exception if we try to go this way (must be old SQLCipher version I think)
       		/*var unEncryptedDB = EncryptedDatabase.open(newDBName);
       		unEncryptedDB.execute("PRAGMA key = 'testkey';");
          		unEncryptedDB.execute("ATTACH DATABASE '" + origDBFilePath + "' AS plain KEY ''");
       		unEncryptedDB.execute("SELECT sqlcipher_export('main', 'plain')");
          		unEncryptedDB.execute("DETACH DATABASE plain");  		
          		unEncryptedDB.close();
          		unEncryptedDB = null;*/
       		
       		
       		
          	}
       

JSON Source