Flutter Realm DB with encryption - flutter

We are exploring the use of Realm DB in Flutter.
We tried to initialize an existing encrypted realm file via the configuration details provided at https://pub.dev/packages/realm
var config = Configuration.local([Car.schema], disableFormatUpgrade: true,
path: 'assets/myfile.realm');
return Realm(config);
However, we could not find an option to specify the encryption key while opening the file.
Can anyone please help?
Thank you.

At this time, there is limited support for Realm in Flutter - although the beta package exists, it's a work in progress. You can still call native Realm functions from Flutter and get back access codes. See Flutter: Write platform specific code
Generally speaking, to encrypt a Realm, generate a random encryption key and pass it to the Realm configuration object. Keeping in mind that to unencrypt it, you need to use the same key so it will need to be stored.
Here's a quick Swift example how how to generate a key but the technique applies across the board to all platforms
var key = Data(count: 64)
_ = key.withUnsafeMutableBytes { (pointer: UnsafeMutableRawBufferPointer) in
SecRandomCopyBytes(kSecRandomDefault, 64, pointer.baseAddress!) }
Then to initially create that encrypted Realm, pass the key in the encryptionKey parameter in the Configuration object:
var config = Realm.Configuration(encryptionKey: key)
let realm = try Realm(configuration: config)
//write some data to Realm etc
Then later, get the key from wherever it was stored, typically in a keychain on macOS/iOS - or whatever secure way you choose to store it:
var key = //get the key
var config = Realm.Configuration(encryptionKey: key)
let realm = try Realm(configuration: config)
//read, write data from the encrypted Realm

Related

Encrypt [String:Any] with curve25519

i want to encrypt the Data I upload to Firebase with curve25519.
Atm i convert my custom model to [String: Any] and upload this to firebase firestore.
Now I want to encrypt the Data. I thought that I understand how the public/privat key stuff works, but when I search for guides, they always (if I understand it right) use the privat key to encrypt (signature) the Data and the public key to decrypt (isValidSignature) the data.
I don't understand this. I thought that u need the public key to encrypt the data, so the receiver have to use the privat key to decrypt the data and read it.
The Code that others used to encrypt my Dic I found so far looks like this:
let jsonData = try? JSONSerialization.data(withJSONObject: Dic)
let digest512 = SHA512.hash(data: jsonData!)
let signatureForDigest = try! PrivateKey.signature(for: Data(digest512))
But I don't understand where the public key comes into the code. How I use the public key so the receiver can decrypt it with his privat key?
Hope someone can help me. Im really stuck and cant find anything that helps me. I only get more confused.
Greets

Update URLSession after new data is created inside database

I am using the following:
Apollo iOS
Neo4j Database (with the GraphQL plugin)
GraphQL
Singleton Class for Connection
My code below is to connect to the GraphQL endpoint which happens to be my Neo4j Database.
class Network {
static let shared = Network()
private(set) lazy var apollo: ApolloClient = {
let url = URL(string: "http://localhost:7474/graphql/")!
let keychain = KeychainSwift()
let configuration = URLSessionConfiguration.ephemeral
configuration.httpAdditionalHeaders = ["Authorization": "\(String(describing: keychain.get("neo.auth")))"]
return ApolloClient(
networkTransport: HTTPNetworkTransport(url: url, session: URLSession(configuration: configuration))
)
}()
}
When I create data inside my database via my app this works great however if I then query to the database to return all the data, the newly created data is not found. The data is in the database because I can see it in the browser and also if I restart my app and then run the exact same code to return all the data; it returns it.
The other thing I have tried to do is run two instances of my app side by side in the simulator. Both apps have the same features and can import/export data. When I create new data via one instance the data is created in the database successfully however upon importing the data in the other instance of the app - it returns nothing (Both apps being ran at the same time).
My Import Code
func importData(){
let apollo = Network.shared.apollo
//Import all data from the graph database
apollo.fetch(query: GetAllQuery()) { result in
guard let data = try? result.get().data else { return }
print(data.jsonObject.values)
}
}
The only thing I can think of is that the session is not updating when new data is created in the database. The reason I feel this is because if I relaunch the app and run my import function it actually returns all the new data. I need the connection to update when new data is created, is there a way I can refresh the connection upon data creation?
I found a fix that is working so far for me:
apollo.clearCache()
I am using this before I run a query to the database and so far it has pulled down all the correct data. My issue was that when I exported data to the database and then tried importing it (or reading it) directly after it never returned anything or returned data that already existed in the system.

Swift 3 Mac OSX - can't cast SecCertificate object in my Keychain to SecKeychainItem?

I am trying to delete an identity from my Keychain in Swift 3.0. My code is currently:
var idCert: SecCertificate? = nil
var idKey: SecKey? = nil
SecIdentityCopyCertificate(id, &idCert)
SecIdentityCopyPrivateKey(id, &idKey)
SecKeychainItemDelete(idCert as! SecKeychainItem)
SecKeychainItemDelete(idKey as! SecKeychainItem)
"id" is a SecIdentity object that I got by using SecItemCopyMatching to get all of my identities, and then used that list to find the identity associated with a specific email address.
My code fails when I try to cast idCert to SecKeychainItem. Apple's Documentation says:
A SecCertificate object for a certificate that is stored in a keychain
can be safely cast to a SecKeychainItem for manipulation as a keychain
item. On the other hand, if the SecCertificate is not stored in a
keychain, casting the object to a SecKeychainItem and passing it to
Keychain Services functions returns errors.
but upon checking Keychain Access I can plainly see that the certificate is in the Keychain. What is going on? Is it possible for a certificate to appear to be in my Keychain but actually isn't or can't be found for some reason? Is there a way for me to programmatically check if the SecCertificate object is in my Keychain?

client-server approach using realm with swift xcode

I'm new to xcode, swift, and realm. And i have to build an IOS application for my graduation project. I have a problem on how to handle multiple clients request. my application is suppose to get requests from multiple users and i have to handle these requests in a server (start counters, a timer, or add, delete, update, etc), and my server is using the realm database. my question is how to communicate between a client and a server locally ? and can i implement the server with swift not javascript ?
If you're using the Realm Mobile Platform for your client to server interactions, you should be able to use the event handling features of the Realm Object Server to detect and respond to requests triggered by users. You can download a trial of the Professional Edition (Which should be enough for your needs as a private project.)
The code for registering an event handler looks like this (Taken from the Realm docs page)
var Realm = require('realm');
// Insert the Realm admin token here
// Linux: cat /etc/realm/admin_token.base64
// macOS: cat realm-object-server/admin_token.base64
var ADMIN_TOKEN = 'ADMIN_TOKEN';
// the URL to the Realm Object Server
var SERVER_URL = 'realm://127.0.0.1:9080';
// The regular expression you provide restricts the observed Realm files to only the subset you
// are actually interested in. This is done in a separate step to avoid the cost
// of computing the fine-grained change set if it's not necessary.
var NOTIFIER_PATH = '/^\/([0-9a-f]+)\/private$/';
// The handleChange callback is called for every observed Realm file whenever it
// has changes. It is called with a change event which contains the path, the Realm,
// a version of the Realm from before the change, and indexes indication all objects
// which were added, deleted, or modified in this change
function handleChange(changeEvent) {
// Extract the user ID from the virtual path, assuming that we're using
// a filter which only subscribes us to updates of user-scoped Realms.
var matches = changeEvent.path.match(/^\/([0-9a-f]+)\/private$/);
var userId = matches[1];
var realm = changeEvent.realm;
var coupons = realm.objects('Coupon');
var couponIndexes = changeEvent.changes.Coupon.insertions;
for (var couponIndex in couponIndexes) {
var coupon = coupons[couponIndex];
if (coupon.isValid !== undefined) {
var isValid = verifyCouponForUser(coupon, userId);
// Attention: Writes here will trigger a subsequent notification.
// Take care that this doesn't cause infinite changes!
realm.write(function() {
coupon.isValid = isValid;
});
}
}
}
// create the admin user
var adminUser = Realm.Sync.User.adminUser(adminToken);
// register the event handler callback
Realm.Sync.addListener(SERVER_URL, adminUser, NOTIFIER_PATH, 'change', handleChange);
console.log('Listening for Realm changes');
Unfortunately, there's no support for Realm and Swift on the server at this point (Unless it's a Mac server) since Realm Swift needs the Objective-C runtime to work, and this isn't available on non-Mac platforms. Node.js is the way to go. :)

Where do I store my Azure role settings that are not to be stored as plain text?

Looks like the standard way of storing settings of Azure roles is under <ConfigurationSettings> tag in the .cscfg file. Looks convenient, but the file is not encrypted in any way - it is an XML that is uploaded to the Azure portal as plain text and is stored as plain text and can be edited at any time.
In my application I'll need settings that should not be stored as plain text - like for example a password to my SQL Azure database. I'd rather not have a plaintext XML file with that password. How do I store such role settings?
The typical way to do this on-premises is to use DPAPI on a single machine. Of course, this has problems on a web farm. To work around this, you can share a single key on each machine and encrypt. The easiest way to do this is to use certificate based encryption.
Nothing against the SQL Azure posts referenced by Michael, but that had to be the longest series ever to tell you to use the PKCS12 configuration provider. The only reason to use that provider is that it works in conjuction with the built-in tooling from ASP.NET that can read from appSettings automatically. It doesn't help with ServiceConfiguration that needs to change.
If all you want to do is securely protect a setting (typically in ServiceConfig) and you don't mind writing a utility class to do it, then you can use these two functions with any certificate (with private key) uploaded to Windows Azure. This is exactly how the password for remote access is encrypted in the Service Configuration.
Encrypt:
var passwordBytes = UTF8Encoding.UTF8.GetBytes("p#ssw0rd");
var contentInfo = new ContentInfo(passwordBytes);
var thumb = "F49E41878B6D63A8DD6B3650030C1A06DEBB5E77";
var env = new EnvelopedCms(contentInfo);
X509Store store = null;
try
{
store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
store.Open(OpenFlags.ReadOnly);
var cert = store.Certificates.Cast<X509Certificate2>().Where (xc => xc.Thumbprint == thumb).Single();
env.Encrypt(new CmsRecipient(cert));
Convert.ToBase64String(env.Encode()).Dump();
}
finally
{
if (store != null)
store.Close();
}
Decrypt:
var thumb = "F49E41878B6D63A8DD6B3650030C1A06DEBB5E77";
var cipherText = "MIIBrwYJKoZIhvcNAQcDoIIBoDCCAZwCAQAxggFgMIIBXAIBADBEMDAxLjAsBgNVBAMTJWR1bm5yeTd0YWIucmVkbW9uZC5jb3JwLm1pY3Jvc29mdC5jb20CECNRAOTmySOQTA2HuEpAcD4wDQYJKoZIhvcNAQEBBQAEggEAkIxJNnCb1nkZe3Gk2zQO8JQn2hOYM9+O9yx1eprTn7dCwjIlYulUMIYwFCMDI7TiYCXG7cET2IP/ooNBPYwxzAvEL5dUVIMK9EDE0jyRP3sGPGiSvG0MW8+xZuQx4wMGNSwm2lVW1ReVRGEpTeTcUFSBCPvXsULpbqCqXtSTgjsHngxgOKjmrWBIdrxCDxtfzvNPgSQ2AVqLTRKgFTN9RHUwJJ2zhGW+F+dBfxai3nlr7HN7JKiIdlNA0UjCd/kSIZqNfPlvd2V58RBMpkW+PEp3vpBa/8D/fhU3Qg/XBNXhroES7aVDB5E16QYO6KgPdXMCpLcQ4e9t1UhokEwUizAzBgkqhkiG9w0BBwEwFAYIKoZIhvcNAwcECEImLeoQJeVkgBCQ94ZxmHnVkBWrID+S4PEd";
X509Store store = null;
try
{
store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
store.Open(OpenFlags.ReadOnly);
var cert = store.Certificates.Cast<X509Certificate2>().Where (xc => xc.Thumbprint == thumb).Single();
var bytes = Convert.FromBase64String(cipherText);
var env = new EnvelopedCms();
env.Decode(bytes);
env.Decrypt();
Encoding.UTF8.GetString(env.ContentInfo.Content).Dump();
}
finally
{
if (store != null)
store.Close();
}
Check the SQL Azure blog, they blogged exactly about this!
Securing Your Connection String in Windows Azure: Part 1 (original)
Securing Your Connection String in Windows Azure: Part 2 (original)
Securing Your Connection String in Windows Azure: Part 3 (original)
also, previous posts at
http://blogs.msdn.com/b/sqlazure/archive/tags/security/