Encrypted SQLite database cannot be attached: "Unable to open the database file" - apache-flex

The database can be open()ed using the same encryption key and it works fine. Tried with multiple encrypted databases - all can be opened, but not attached.
This works when encrypted and when not encrypted (bytearray is null):
connection.open(file, "create", false, 1024, bytearray);
This only works when not encrypted:
connection.attach("db" + newnum.toString(), file, new Responder(attachEncryptedSuccess, openEncryptedError), bytearray);
Any help is appreciated.
UPDATE:
Just found a strange pattern here:
It seems that if I create an encrypted database, and then create new databases and attach them, everything works fine.
The created files, after unloading, will only be properly opened using the command that they were initially created with. Therefore, the encrypted database that I created before using open() will only open with open() method. All the encrypted databases that were initially created using attach() will only be able to be opened using attach(). It also doesn't matter which database was open()ed first, aka which one is the main database. It can even be not encrypted.
This is something very strange. Is this a bug? Or am I doing something wrong here?

One gotcha that I ran into awhile ago, and it sounds like it might be impacting you. If you are creating both db's from AIR then this should work fine, however if you have created one with any external tool - generally most tools will default the PRAGMA ENCODING = UTF8. AIR, being Adobe, does things a little different than just straight up telling you that they create theirs UTF16-LE.
According to sqlite rules, differing encoding types cannot be attached one way or the other. One way to verify is to use sqliteman or some other sqlite editor to verify the pragma settings.
For me, I ended up having to start from a seeded db (empty databases -just the header- were over written by AIR) that was to be initialized from a template database. If I allowed AIR to create my starting db, it was set to UTF16 to which I could not attach a UTF8 template.

Related

SQLite-PCL : Accessing my own created table?

I'm referring to SQLite-PCL tutorial here: https://code.tutsplus.com/tutorials/an-introduction-to-xamarinforms-and-sqlite--cms-23020
I'm very new to SQLite, so I'm lacking in knowledge in lots of basic things - I have tried Googling, can't understand most of it.
Is the call to new SQLiteConnection actually opens up the database or just saying that "the road to the database has been established, whether you access it or not is up to you"?
How do I check if there's already existing database in the devices? And if there is, how do I access it? I have Googled this, but it all seems to be a bit extreme - can't I just call simple OPEN the database?
Is it okay to have multiple SQLiteConnection instances to the same database, if I can be sure that I'm not going to do multiple transaction at the same time?
After I have INSERT into the database, close the app, open up the app back - how do I make sure that there is database created in previous session? Any way to debug this? Because I have no idea if the database is there or not, and I don't know how to access it either..
SQLiteConnection returns a connection object that is used to make subsequent queries
use File.Exists to see if the db file is already present
Yes
Again, use File exists to see if the db file is physically present
Xamarin's ToDo sample provides a good overview of using SQLite with Forms.

Where to Get Encryption Key for Realm App in Swift

I have a Swift app that uses the Realm Object Server running remotely on a Linux server. Everything is working, including real-time sync.
Occasionally I want to inspect the contents of a local Realm file used by the iOS Simulator so I can do some debugging. When I browse here:
~/.../CoreSimulator/.../Documents/realm-object-server/<unique id>/
...and I try to open this file: realm%3A%2F%2F104%2E236%2E129%2E235%3A9080%2F%7E%2Fmyapp.realm
I get prompted with: Please enter a valid encryption key for this Realm file.
Where do I get this encryption key? I tried using the admin token from the server, but that doesn't appear to be working.
Also, can I turn off encryption everywhere? Or is it mandatory for any app using the Realm Object Server?
It is not possible to open the local version of a synced Realm file using the Browser (or anything else, for that matter). This is due to differing history types internally (but I won't go into that now). In order to inspect the contents of the Realm file, you have to open it using the previously defined syncURL. The browser will then download the file and show you the contents.
A few links on this topic:
https://github.com/realm/RealmTasks/issues/327
https://github.com/realm/realm-core/issues/2276
You may use old version of Realm Browser, please update it and check the result again.
Use Realm Studio instead which worked for me.
Here can download the file
byte[] key = new byte[64];
new SecureRandom().nextBytes(key);
String encryptionKey = byteArrayToHexString(key);
//encryptionKey is what you want byteArrayToHexString see
Log.d("test", "encryptionKey:"+encryptionKey);
byteArrayToHexString() method you can see:How to convert a byte array to a hex string in Java?

'file is encrypted or is not a database' error while opening the sqlite db

I have a sqlite database in my UWP app. On the very first launch of my app, I create the database and set it up with all the tables and stuff. I play around with the app and generate some data just fine. But when I close and relaunch the app, it starts giving me 'file is encrypted or is not a database' error while trying to execute any query.
I am using sqlite3.dll v3.12.0 and here is my pragma key statement (with an example encryption key):
"PRAGMA key='aes256:66zk4rsKBIfSJ4vhF1XkzFxzrznOhjjnotuHRdKADIg='"
I verified, on second launch, the encryption key is being used to run the pragma key statement.
Edit: It looks like the encryption went just fine. Because, when I use a tool like SQLite Manager and provide the same key, it opens the db just fine.
I think what might be happening to you Is that you use to have a previous library of SQLite working with encryption working properly like I did.
<SDKReference Include="SQLite.UAP.2015, Version=3.10.2">
<Name>SQLite for Universal App Platform</Name>
</SDKReference>
And since you updated the library to v3.12.0 the PRAGMA key in this version did not work hence not being able to enter to the previous encrypted DB.
I'm trying to rebuild the link to that version but is hard: "SQLite.UAP.2015, Version=3.10.2"

Replacing SQLite database while accessing it

I am completely new to SQLite and I intend to use it in a M2M / client-server environment where a database is generated on the server, sent to the client as a file and used on the client for data lookup.
The question is: can I replace the whole database file while the client is using it at the same time?
The question may sound silly but the client is a Linux thin client and to replace the database file a temporary file would be renamed to the final file name. In Linux, a program which has still open the older version of the file will still access the older data since the old file is preserved by the OS until all file handles have been closed. Only new open()s will access the new version of the file.
So, in short:
client randomly accesses the SQLite database
a new version of the database is received from the server and written to a temporary file
the temporary file is renamed to the SQLite database file
I know it is a very specific question, but maybe someone can tell me if this would be a problem for SQLite or if there are similar methods to replace a database while the client is running. I do not want to send a bunch of SQL statements from the server to the client to update the database.
No, you cannot just replace an open SQLite3 DB file. SQLite will keep using the same file descriptor (or handle in Windows-speak), unless you close and re-open your database. More specifically:
Deleting and replacing an open file is either useless (Linux) or impossible (Windows). SQLite will never get to see the contents of the new file at all.
Overwriting an SQLite3 DB file is a recipe for data corruption. From the SQLite3 documentation:
Likewise, if a rogue process opens a
database file or journal and writes
malformed data into the middle of it,
then the database will become corrupt.
Arbitrarily overwriting the contents of the DB file can cause a whole pile of issues:
If you are very lucky it will just cause DB errors, forcing you to reopen the database anyway.
Depending on how you use the data, your application might just crash and burn.
Your application may try to apply an existing journal on the new file. Sounds painful? It is!
If you are really unlucky, the user will just get back invalid results from any queries.
The best way to deal with this would be a proper client-server implementation where the client DB file is updated from data coming from the server. In the long run that would allow for far more flexibility, while also reducing the bandwidth requirements by sending updates, rather than the whole file.
If that is not possible, you should update the client DB file in three discrete steps:
Send a message to the client application to close the DB. This allows the application to commit any changes, remove any journal files and clean-up its internal state.
Replace/Overwrite the file.
Send a message to the client application to re-open the DB. You would have to setup all prepared statements again, though.
If you do not want to close the DB file for some reason, then you should have your application - or even a separate process - update the original DB file using the new file as input. The SQLite3 backup API might be of interest to you in that case.

Using an encrypted file securely

I'm writing an application with a dBASE database file in Borland Delphi 7.
Note: I think this question is file-security related and you can forget the dBASE thing (consider it as a TXT file) in this question.
The database must be accessed just by the application. Then it must be encrypted. Unfortunately dBASE doesn't support any password mechanism and i had to encrypt the file by myself (and i also HAVE to use dBASE)
What approach do you suggest to secure the database file?
The simple one is:
Encrypting the database file and placing it near beside the application EXE file.
When the application runs, it should decrypt the file (with a hard-coded password) and copy the result to a temporary file that has DeleteOnClose and NoSharingPermission flags.
When Closing, application should encrypt the temp dBASE file and replaces the old encrypted file with the new one.
I think this is a fair secure approach. But it have two big problems:
With an undelete tool the user can restore and access to the deleted temp file.
Worse: When application is running, if the system rebooted suddenly the DeleteOnClose flag fails and the temp file remains on hard disk and user can access it.
Is there any solution for, at least, the second part?
Is there any other solution?
You could also try to create a TrueCrypt file-based containter, mount it, and then put the dBase file inside the mounted encrypted volume. TrueCrypt is free (in both senses) and it's accessible via command line parameters from your application (mount before start, unmount before quit).
Depending on what you're doing with the database, you may be able to get away with just decrypting the records you actually need. For example, you could build indexes based on hash codes (rather than real data); this would reduce seeks into the database to a smaller set of data. Each record in the subset would have to be decrypted, but this could be a lot better than decrypting the entire database.

Resources