Encrypting password for C# configuration file - c#

I'm trying to figure out the best way to encrypt a password that is in a configuration file. We are not allowed to hard code the passwords.
This a requirement that I have to meet.
I'm using DOTNET core and this needs to work on windows 10, windows server and OSX.
Does anyone have any good ways of meeting this requirement?
Thank you

First, read up on RSA Key Containers. You are going to have your operations group create one for each of your environments. They will export them and keep track of the exports for you. They'll also ACL them so that devs have access to them in lower environments, but only ops folks have access in higher environments. They also need to add an ACL so that the process identities on your servers have access.
Those Key Containers will be imported on to the servers, and on any client machines that will be doing any encryption work.
Then create a C# class that has the secret name, perhaps an encryption timestamp, and two strings, one for the clear text secret, and one for the encrypted version. Make everything JSON serializable. Mark the clear text member so that it doesn't serialize.
Create a small client app (say, with WinForms) that can read in a collection of secrets objects, decrypting any encrypted text using a key in the Key Container. The app will allow users to paste in a secret (perhaps one copied from KeePass). When the file is saved, the clear text/pasted in secret is encrypted and serialized out. The clear text version is thrown away.
At that point, you have a JSON text file that contains one or more encrypted secrets, but those secrets can only be decrypted by processes running with a token that has access to the RSA Key Container. So, you can put the file in source control and rely on your build/deploy to push the file(s) out to your servers.
Sorry for the lack of code, but I really can't copy/paste code I wrote for my employer. There should be enough here to get you started.

Related

Store secret key securely in .NET Standard cross-platform app

I'm working on a C# PowerShell module, which is going to be a simple wrapper around some service REST API. I'd like to target PowerShell Standard / .NET Standard and make module available across all supported platforms.
For this app authentication requires API token, issued on a service website by the user. Entering key every time you open a session would be extremely inconvenient and therefore I need some way to securely store the API key in a user profile.
The problem is - I cannot find an easy way to encrypt data that has transparent cross-platform support. Initially, I wanted to use SecureString, but it is (a) deprecated and (b) doesn't seem to have good support on Linux. In a perfect world I'd like to have some mechanism similar to Windows encryption - user certificate encrypts API key and I put result in a text file in a user folder.
This is not a financial or mission-critical application, top-notch security is not required, but still keening plain text secrets in my home folder makes me nervous. Yes, I'm talking to you, AWS SDK authors :)
My first thought was: "just save secret key to ENV variables..."
But if I understood OP's question correctly, it is required to restrict unauthorized reading of this secret even on OP's machine.
One option I could see is just create a folder (or maybe file) and give it the access permissions only for one particular user. Ultimately one can create new user account which will be used to run the code in powershell and give this new user exclusive permissions to read secret file. This will prevent some 3rd party programs running from OP's account to read secret file.

Obtaining sensitive data from the user and storing it without hashing so that it can be restored

I'd like to ask for some advice on the app security when it comes to getting the password from the user and storing it.
I'm developing a tool using .NET Core (console project) and Selenium WebDriver to automate a process on a website, which requires authentication, and my concerns are following:
1. Getting the password from the user (using console) and securely handle it
2. Storing the password in a secure manner
Regarding the first point:
I've found an answer on
SO pointing out that
using
SecureString
doesn't fully prevent sensitive data to be read as at some point it
has to be converted to/from normal string. I have come across the
solution
for getting user input from console using SecureStrings, but
according to what's written
here
SecureStringToBSTR has to be used to handle the sensitive data in a
secure way. However, SecureStringToBSTR is not included in .NET
Core, because it's
available only for Windows thus I'm stuck.
As for the second point:
I cannot hash the password as it has to be restored. At first I
wanted to use platform specific solutions and check the current
platform in the app, but after a research I found out that there's API only for DPAPI for Windows, there's no API for KeyChain in MacOS (there's some workaround) and Linux doesn't have a unified way of storing sensitive data at all. The only solution I can think of is to force the user to generate public/private keys (using for example RSA which is available on all platforms, encrypt the password using public key and require private key to retrieve the password. Then I would store the encrypted password either in appsettings.json or as an Environmental variable as desribed here. Unfortunately Azure Key Vault is not free
I am aware that there are many questions similar to this, but:
I couldn't find any regarding storing passwords, most sources focus on hashing them, however, it doesn't apply to described use case
Virtually all are focused on ASP.NET Core MVC
Thanks in advance for the hints.

How can a user encrypt a configuration file to be used by a service application?

Ok, I'm asking a rather generic question to a specific problem. I have searched this in more ways than I can count, and nothing seems to work. Let me explain my need and then I'll mention a few of the best solutions I've found and why they don't work in my case.
I have an application that a user launches and uses to set up various configuration values that are saved into an app.config file. This is a WPF application. Specifically, some of this data are HIGHLY sensitive.
This data needs to encrypted and subsequently decrypted by a Windows Service that will be launched by the application once the configuration step is finished. The general solution given for this scenario is to use DPAPI, which has two modes for encryption: User and Local Machine.
If you use User-level encryption, your application will encrypt and decrypt data as much as it desires, as long as the current user that initially encrypts the data is doing the decryption. My problem is that when the service is started, it also restarts on reboots and will specifically be running under a different user account.
The next approach, using DPAPI, is to encrypt the data as the Local Machine. This means that when ANYONE logs into the machine can decrypt the sensitive data. This is a BIG no-no!
What I need is to have a way for a user to specify the data he wants to encrypt and then specify an account (in this case, what will be the service account) and use it for data encryption.
I can't find how to do this. This MSDN article alludes that can be done. (See section 'Web Farm Scenarios'.) The TL;DR on that article is that for ASP.Net applications, you can use the RsaProtectedConfigurationProvider to encrypt your data, and export the keys to be used with a specific web account. This is close to what I want, but in my case I need to create the data in a WPF application and store it to be used in a Windows Server Service.
How can this be done?
You can accomplish something similar to this using something as mundane as EFS, but unlike raw DPAPI, a recovery key might bypass the protection. In either case, a local admin could replace your program with his own and it would have full access to the decrypted data.
As for setting this up, the easiest way to do that would be to interactively log on with the service account and either create the protected data using System.Security.Cryptography.ProtectedData or create a file in a directory marked with the "encrypt" attribute.
Use the account name as the salt for your encryption, decyption should use the logged in account name as the salt to decrypt.
i have a suggestion , you can create User group add required users into that group. And encrypt and decrypt data only if user is part of that group using second method.

Store key file as embedded resource (how unsafe is it?)

If I have a stored key file used to decrypt the encrypted input coming into my application, and I store that key file as an embedded resource so that it is embedded in the assembly when deploying, how difficult would it be for someone to reverse engineer the application and retrieve the key file?
Also, the application is deployed through ClickOnce "Online only" mode which I imagine would also make it more difficult to reverse engineer? (I'm not exactly sure of the workings of ClickOnce but I wasn't able to find the dll's/assemblies on my local machine after running the application in online only mode...).
Update:
As Ralf essentially answered the main question below in his comment (answer: it's not really safe at all), here's some more information so that you knowledgeable people can possibly suggest a better security model.
The encryption will be used to encrypt the login password for my application, to be used in a SSO setup (the user will first sign on to a different system and then by clicking a link will be able to directly open my application without having to enter in their login details).
The encrypted data will be sent as a base-64 string URL parameter in the link that will launch the my click-once application.
I will also be developing the application that will create the encrypted data for the URL parameter (clarification: not the first application the user will sign in to for the SSO, I will only be creating a small tool to convert the plain text password into an encrypted base64 string).
It's only an internal application so bullet proof security isn't essential and ease of deployment is more important, but it'd be nice to know what the best practices and different options that are available.
Whether in clear text or encrypted, you don't want to store the password. When you get a password, all you should do is pass it to your server app where you compare it against the salted hash of the password you have in the DB. Even if you don't think security is that important, you need to take care with the password because people frequently reuse passwords across different systems. I know they shouldn't but they do.
If you want to implement a single sign on (SSO), create a sign on token on the server side and pass it back to the client, either encrypted or signed (HMAC is a good choice for signing). This is an unforgeable token because you need to know the encryption key or shared secret for the HMAC and that data is only known on your servers. So you have your SSO and all data involving the SSO is managed on servers so there's no data leakage or chance of spoofing.
As long as the aplication can be launched, the files have to be somewhere on the computer. You just have to know where to look. The reverse-engineering may be ugly but it is always possible. The computer has to be able to understand what he is supposed to do so you only have to extraxt the information one is looking for. Therefore the security of your application should never depend on the difficulty of reverse-engineering! I believe that a secure application should be open-source anyways.
You propably need a diffent security model. The important thing here is that you know against what you want to protect the data. If you simply want that you know the data is sent by the server and not somebody else (man in the middle attack) you could use digital signatures instead.
If you do not want anybody to read any data sent between server and client you should use some sort of ssl implementation to create an encrypted channel. Then you only need to watch out that the public key of the server is not altered on the client. This may be done by an certificate of an official CA but unfortunately those are usualy not for free.

When should I encrypt my config file?

I have a C# application that comes with an app.config file. The application is built on a build server and deployed to multiple users.
I'd like to encrypt the app.config, but I'm not sure about when to do so: If I do it straight after the build, won't the encryption depend on the build server credentials? How can the application decrypt on other machines? If I do the encryption on the users machine, won't this leave time when the app.config is unprotected?
Thanks
Edit:
I was considering using DPAPI. It uses the user's credentials to encrypt and decrypt. This is why I think I might have a problem delivering an encrypted file to the users.
I just read the addition to your post, and I don't think you actually need encryption at all...
You say that you intended to use a system that would encrypt/decrypt based on the user's credentials. That means two things:
You don't encrypt during build; you can't use this sort of system during build, for the reasons yoy noted.
You seem to be OK with the users having access to the data. In that case, you should not be using configuration at all, but you should be prompting them for login info (perhaps saving it securely afterward to reuse) or just using their Windows/domain logins.
Either way, you don't need to encrypt the file to protect it... you simply need to store the login info, or other config info, as user settings, rather than configuration, which is readable to all users.

Categories