5

I have some secrets that need to be transferred from my .NET application to another. I am using the CNG DPAPI to encrypt these secrets, and I wish to find the most suitable place to store them (in this encrypted format) on my machine (from which I can collect them and send them to the other application when needed).

The options include: 1) An SQL database; 2) The Windows registry; 3) A file; 4) Some Windows-specific secret vault I haven't been able to Google as of yet...

I realize that options 1-3 have access control mechanisms, but I cannot really determine the pros and cons of one approach over the other. Considering these, what would be the best option?

NLuburić
  • 294
  • 2
  • 9
  • 1
    As long as they are encrypted and the key is in a secure location, it doesn't really matter. –  Aug 21 '19 at 14:46
  • @MechMK1 How would you store the key in a secure location, if the application needs access to it? It's like a never ending loop if you try to approach security from this side. You have a secret, you encrypt it, you need to store the key where the application can read it from. Than you need to secure the key, you encrypt it.... Overall encrypting secrets if they are not in transit is just security by obscurity. – Raimonds Liepiņš Aug 21 '19 at 15:43
  • @RaimondsLiepiņš Use a key derivation function to derive a key for AES, and as input use a passphrase from the user. –  Aug 21 '19 at 16:10
  • @MechMK1 Everytime you restart an application you are not going to ask for input from a user for everyone to start working with it. That would be very secure, but would simply be horrible management wise. – Raimonds Liepiņš Aug 21 '19 at 18:43
  • @RaimondsLiepiņš Then your question isn't about where to store the encrypted files, but rather about proper key management. And asking the user for credentials on login isn't something uncommon. –  Aug 21 '19 at 20:57
  • @MechMK1 for key management, I'm relying on Windows to do the heavy lifting. The DPAPI manages the keys and ties them to the SID of the account under which my app runs. – NLuburić Aug 22 '19 at 04:59
  • @RaimondsLiepiņš The reason I don't want to rely on this alone is if there is a vulnerability in the key management scheme, I would like additional protective controls (standard access control for one) for a defense-in-depth. – NLuburić Aug 22 '19 at 05:00

1 Answers1

8

The Windows-built-in secret store (analogous to Apple's Keyring) is called Credential Manager. See https://stackoverflow.com/questions/9221245/how-do-i-store-and-retrieve-credentials-from-the-windows-vault-credential-manage for (slightly dated but still usable) instructions on accessing it programmatically.

With that said, all that the Credential Manager does is encrypt your secrets with DPAPI and store them in a structured data store (I'm pretty sure it's in the registry). Since you're encrypting with DPAPI yourself, the Credential Manager buys you very little except possibly a bit of convenience (though DPAPI is very convenient, and so are most storage APIs).

Personally, I recommend encrypting with DPAPI and then storing the secrets in the user's Local AppData folder, in a subdirectory with your program's name (if the secret is machine-wide rather than per-user, you can use the ProgramData directory instead of AppData\Local, but of course this will make it world-readable). It's as secure as any other location reliably available in Windows, easy to delete when uninstalling the program, and easy to access. Using the current user's registry hive under Programs\ProgName is also an option, though. A database is pretty pointless unless your secrets are some kind of interrelated structured data, or you anticipate having a very large number of them. I wouldn't bother with Credential Manager unless the secrets you're storing are actually credentials and/or it's acceptable/important that your users be able to view them using the Credential Manager GUI.


With all that said, a few words of warning:

  1. DPAPI uses a per-user encryption key that is different on every machine. If you copy DPAPI-encrypted data from one machine to another, you won't be able to decrypt it on the second machine.
  2. DPAPI's encryption key is itself encrypted using a key derived from the user's password (among other things). If the user changes their password through the standard process (where the old password is provided), this is fine; the DPAPI key is decrypted and re-encrypted with the new password's derived key. If the password is reset (by an Administrator or via offline modification of the SAM data), the DPAPI key is lost forever. This is probably fine for your use case but is something you should know.
  3. A lot of the stuff mentioned in this answer is Windows-specific, but .NET itself is cross-platform. If you want to be allow Mac, Linux, and other platforms to run your code too, take care to avoid Windows-specific features and functions.
CBHacking
  • 40,303
  • 3
  • 74
  • 98
  • 1
    Thanks for the answer. I am using the CNG DPAPI that lets me use the SID of a user group, so that I can use it on multiple machines. As for being Windows specific, my system relies on Windows and its AD so yeah, I won't be able to port it to other OS easily. – NLuburić Aug 23 '19 at 10:46
  • Ah, if you're using DPAPI-NG and Active Directory, then yes, you can encrypt to AD users or groups and it will work for other machines in the same forest. DPAPI-NG is less convenient that legacy DPAPI but still probably the easiest option for you. – CBHacking Aug 23 '19 at 17:29