Does my iOS app contain encryption if I use realm? - realm

Finally I’m uploading my app to the App Store connect. I’m using the latest version of realmswift and I only created a default realm database and never explicitly tell the realm to use encryption. In this case does my app contain encryption?
Also, sometimes I can see the outputs which looked like realm established an internet connection(I don’t know whether it’s HTTPS or not) and I don’t know why. Maybe to check the realm’s updates?
In this case, does realm really establish a HTTPS connection? What should I choose? Contain or not?

A Realm database is not encrypted unless you tell it to be an encrypted. e.g. you would need to include the following code for the Realm to be encrypted
// Generate a random encryption key
var key = Data(count: 64)
_ = key.withUnsafeMutableBytes { (pointer: UnsafeMutableRawBufferPointer) in
SecRandomCopyBytes(kSecRandomDefault, 64, pointer.baseAddress!) }
var config = Realm.Configuration(encryptionKey: key)
do {
let realm = try Realm(configuration: config)
} catch let error as NSError {
fatalError("Error opening realm: \(error.localizedDescription)")
}
That being said, by default with iOS 8 and above app files are encrypted using NSFileProtection whenever the device is locked.
When it comes to a sync'd Realm, that's a little different as the on-disk files can be encrypted per above, but the sync'd data stored in MongoDB is not encrypted.
A sync'd realm will establish a connection to the sync server (MongoDB) so that will results in internet traffic. Likewise if you're using REST calls to pull data from MongoDB, those will also result in network activity.

Related

Encrypt SQLITE database and use it with FireDac in a windows VCL application

I am writing a Windows VCL desktop using c++ builder. The app uses Firedac and a SQLite database.
I want to protect this SQLite database:
Only my vcl app can connect to it and use it
Other programs and people cannot use the SQLite file
So far I found that the easiest thing that I can do is Encryption, you make it so that anybody without a correct password gets a message like "This file is not a database" if he tries to open it.
Yes we can do this with Embarcadero VCL, doc. using a TFDSQLiteSecurity component and these lines :
FDSQLiteSecurity1->Password = "";/* we are protecting (encrypting) our uncyphered database*/
FDSQLiteSecurity1->ToPassword = 'newpassword';
FDSQLiteSecurity1->ChangePassword();
Unfortunately the VCL Firedac app cannot connect to an encrypted sqlite database so it must decrypt it first.
In order to make things work my program starts and decrypts the database ( removes password) then it connects to the database and use it. When finished I recrypt the database again (when closing app).
THE PROBLEM:
During this time (My program is up and running and the database in uncrypted) can I stop other programs from opening the SQLITE database? Is there a better approach, I am opened for any suggestion
Once it is encrypted by FireDac just set the appropriate properties on the FDConnection. Those would be password to the password and encrypt to the encryption method.
Firedac can open a SQLite database it has encrypted itself so the problem resolves itself by doing that as a better approach. Other programs only see the encrypted version on disk and can't open it without the password.

Guidelines for robust synchronisation of mobile client (iOS, Swift) with Realm Object Server

I have used the techniques in the RealmTask tutorial (https://realm.io/docs/tutorials/realmtasks/ ) to get a demonstration of synchronisation with the Realm Object Server working. However, as mentioned in realm mobile platform, how to connect while offline? , it is difficult to find design guidelines on realising a robust app in the presence of intermittent network connectivity. For example, the network might not be available when the app is first run, and in the tutorial example I think the login attempt would just time out after say 30 seconds.
From various sources, I have tried to outline an implementation approach on the client and have come up with the following:
=============================================================
At start-up of app
Create login credentials with
SyncCredentials.usernamePassword()
Check whether user credentials already exist using
SyncUser.all
If so, get the correct user using the appropriate key (UserId)
If a user is obtained, get the Realm configuration using
realmConfiguration = Realm.Configuration(SyncConfiguration(user, realmURL))
Attempt a log-in with
SyncUser.logIn with SyncCredentials
On completion, put the following on the main DispatchQueue (async)
realmConfiguration = Realm.Configuration(SyncConfiguration(user, realmURL))
if not logged in, repeat login attempts every N minutes until successful? E.g. to handle the situation when the network is unavailable when the app is started, but then becomes available?
Launch the rest of the app, making realmConfiguration available.
However, only access the Realm if realmConfiguration has been set up. Design the app so that it handles the scenario of realmConfiguration not being set up.
=============================================================
Is the above approach sensible, or is there a better solution?
Katsumi from Realm here. Our RealmTasks demo application may help you.
https://github.com/realm-demos/realm-tasks/tree/master/RealmTasks%20Apple
First, check whether the user has logged in or not at launched the app.
if configureDefaultRealm() {
window?.rootViewController = ContainerViewController()
window?.makeKeyAndVisible()
} else {
window?.rootViewController = UIViewController()
window?.makeKeyAndVisible()
logIn(animated: false)
}
https://github.com/realm-demos/realm-tasks/blob/master/RealmTasks%20Apple/RealmTasks%20iOS/AppDelegate.swift#L35
If the user has been logged in before, you can use user object that was cached before. (SyncUser.current or SyncUser.all)
If there is no cached user object (The user is the first time to use the app, or the user re-installs the app), show login view to signing up/in.
The former case (Use the cached user object) doesn't require network access, so you don't need to care about the offline situation.
The latter case (The user should signing up/in) requires network access, in that case, the best practice depends on the specification of the app. It is enough to show a just alert view that indicates requiring network for some apps, or use standalone Realm and then migrate synced realm after the app will be online.

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?

Possibility for only currently connected (not authenticated) and admin user to read and write on certain location

Is there any way to write a security rule or is there any other approach that would make possible only for currently connected (not authenticated) user to write/read certain location - admin should also be able to write/read?
Can a rule be written that disallows users to read of complete list of entries and let them read only entry that matches some identifier that was passed from client?
I'm trying to exchange some data between user and Node.js application through Firebase and that data shouldn't be able to read or write by anyone else other than user and/or admin.
I know that one solution would be that user requests auth token on my server and uses it to authenticate on Firebase and that would make it possible to write rule which prevents reads and writes. However, I'm trying to avoid user connecting to my server so this solution is not first option.
This is in a way session based scenario which is not available in Firebase but I have
some ideas that could solve this kind of problem - if implemented before session management:
maybe letting admin write into /.info/ location which is observed by client for every change and can be read only by active connection - if I understood correctly how .info works
maybe creating .temp location for that purpose
maybe letting admin and connected client could have more access to connection information which would contain some connection unique id, that can be used to create location with that name and use it inside rule to prevent reading and listing to other users
Thanks
This seems like a classic XY problem (i.e. trying to solve the attempted solution instead of the actual problem).
If I understand your constraints correctly, the underlying issue is that you do not wish to have direct connections to your server. This is currently the model we're using with Firebase and I can think of two simple patterns to accomplish this.
1) Store the data in an non-guessable path
Create a UUID or GID or, assuming we're not talking bank level security here, just a plain Firebase ID ( firebaseRef.push().name() ). Then have the server and client communicate via this path.
This avoids the need for security rules since the URLs are unguessable, or close enough to it, in the case of the Firebase ID, for normal uses.
Client example:
var fb = new Firebase(MY_INSTANCE_URL+'/connect');
var uniquePath = fb.push();
var myId = uniquePath.name();
// send a message to the server
uniquePath.push('hello world');
From the server, simply monitor connect, each one that connects is a new client:
var fb = new Firebase(MY_INSTANCE_URL+'/connect');
fb.on('child_added', newClientConnected);
function newClientConnected(snapshot) {
snapshot.ref().on('child_added', function(ss) {
// when the client sends me a message, log it and then return "goodbye"
console.log('new message', ss.val());
ss.ref().set('goodbye');
});
};
In your security rules:
{
"rules": {
// read/write are false by default
"connect": {
// contents cannot be listed, no way to find out ids other than guessing
"$client": {
".read": true,
".write": true
}
}
}
}
2) Use Firebase authentication
Instead of expending so much effort to avoid authentication, just use a third party service, like Firebase's built-in auth, or Singly (which supports Firebase). This is the best of both worlds, and the model I use for most cases.
Your client can authenticate directly with one of these services, never touching your server, and then authenticate to Firebase with the token, allowing security rules to take effect.

How would allow clients to self regiter over HTTP using sometype of public key fingerprint?

I'm working on creating small relay stations out of tiny embedded Linux boxes. They have some sensors connected to them and transport data back to a server via HTTP POST. Right now the server just accepts their message, along with a unique ID (the MAC address of eth0).
I want to expand this to include some type of security. I want to be able to deploy these little devices with minimal configuration. I'd like to copy a base firmware to the device, hook them up in the field, and they self-register. The first time they connect, I'd like the server and device to do some type of negotiation where I can store a fingerprint. Subsequent requests I could then authentication/verify the device using that fingerprint.
That way, once a device registers with its unique ID, I can be assured all data from that ID is from the same device. If a rouge device or set of devices does register, I'll just delete them (I store IPs to so I can delete by unknown ranges and block them).
My question is what's the best way to go about doing this? I think back to the idea of SSH fingerprints, where the first time you connect to a server you get a server fingerprint. If a future request yields a different fingerprint, you get a huge warning and have to manually delete the fingerprint out of your authorized_keys file if the server's keys have actually regenerated (e.g. you did a reinstall without saving your old SSH keys).
Is something like this possibly with HTTP, possibly avoiding having to use preshared keys?
If it matters, the clients are running Python2 and the server they connect to is written mostly in Scala on Tomcat.
Basically, all you need to do is tell the server the public key, and then sign all of your messages with it. If you don't want pre-shared keys, then the server cannot be assured that someone new who is registering is actually one of your devices. You can still validate that the message came from the same device that originally registered with that identifier, however.
The process basically goes like this:
Client generates a new key pair (e.g. an RSA public/private key pair).
Client registers with server, sending its public key. The server stores this public key.
When the client sends a message, it generates a signature of its message, which it attaches to the message. When the server receives the message, it validates the signature to ensure that the message was sent by someone holding the corresponding private key.
The code for this in PyCrypto goes something like this:
Generate key pair
from Crypto.PublicKey import RSA
key = RSA.generate(2048)
private_key = key.exportKey()
public_key = key.publickey().exportKey()
# private_key is a string suitable for storing on disk for retrieval later
# public_key is a string suitable for sending to the server
# The server should store this along with the client ID for verification
Generate signature
from Crypto.PublicKey import RSA
from Crypto.Hash import SHA
key = RSA.importKey(private_key)
# where private_key is read from wherever you stored it previously
digest = SHA.new(message).digest()
signature = key.sign(digest, None)
# attach signature to the message however you wish
The server should load the public key as it has previously stored, and use a "verify" method provided by the Scala/Java crypto API you use, and accept the message only if it succeeds.
It is important to understand the caveats of each approach, as various techniques only protect against certain types of attacks. For instance, the above approach does not protect against a "replay attack", in which an attacker records a message with a certain meaning and then re-transmits it to the server at a later time. One way of protecting against this would be to include a timestamp in the message which is hashed; another would be to use an appropriately encrypted transport (e.g. SSL/TLS).

Resources