isar / hive

Lightweight and blazing fast key-value database written in pure Dart.
Apache License 2.0
4.1k stars 407 forks source link

encryption - where is the best place to store encryption keys? #1070

Open FetFrumos opened 2 years ago

FetFrumos commented 2 years ago

I used hive in my flutter app. I store very important data in the local database(hive). I used encryptedBox for my data, but I want to securely protect my data. so I have a few questions:

  1. I am concerned that it is relatively easy to access the box file. how reliable is the encryption method(AES-256)?

2.if the encryption is reliable(and I read that yes), then it is important to store the key securely. where is the best place to store keys? I have two options: 2.1 secureStorage(like as example).

  const secureStorage = FlutterSecureStorage();

  final encryptionKey = await secureStorage.read(key: 'key');

  if (encryptionKey == null) {

   final key = Hive.generateSecureKey();

   await secureStorage.write(    key: 'key',      value: base64UrlEncode(key),);

  }

 final key = await secureStorage.read(key: 'key');

 final encryptionKey = base64Url.decode(key!);

  final encryptedBox= await Hive.openBox('vaultBox', encryptionCipher: HiveAesCipher(encryptionKey));`

also in the documentation it says:

Only values are encrypted while keys are stored in plaintext.

I think it is not very reliable - to store the key in the program code.

2.2 store them(value and key) on the server - receive them when starting the application.

your opinion? I will be grateful for any advice.

Grrravity commented 1 year ago

Hi there !

I don't know much for the first topic, sorry :(

Regarding the second question I may have the answer

1) Storing in secure storage is OK as it's done on first run of the app, not at build times. Meaning that the actual key value is not written in the code itself and may not be read with reverse engineering. That said, you should add the proper configuration for iOS keychain to restrict the key to be backed up when user migrate to another device. Check iOS options of SecureStorage(), there's 5 of them and 2 or 3 provide the anti-migration thing. If you don't, the user may already have the key in its keychain when you try to regenerate a new random for the fresh-new installation.

2) However as the key name itself is written in codebase it may be retrieved. Meaning if the user can access the keychain it can retrieve the value of the key by searching keystore for the key name and do whatever he should not on your data.

3) Leaving the backend to handle the process would be nice if you are absolutely sure the communication with the app is secured (i.e : no-one can watch for the key during the exchange...). Usually api are not secured enougth so I would not recommend it.

4) The best solution would be to leave the key value generation as provided in the example but to tweek the key name management so that its name isn't known at build time nor written in plain text in code base.

One would generate a random on first run and use it as the key name then put the key name - key value in secure storage. This last point is easier said than done so I leave you the actual implementation :)