Best practice for saving sensitive data in Windows 8 - c#

What's the best way of saving sensitive data to a local file in Windows 8? I'm developing a C# application that needs to store oAuth tokens/passwords. I've heard it was common in .NET to encrypt/decrypt data, but I don't have any experience with those mechanics. Is encryption still recommended/neccesary given that Windows 8 apps have their own personal/protected storage area similar to Windows Phone?
Also, doesn't encrypting/decrypting each time when you request the data causes a performance issue? (would it be better to write a custom/lite algorithm?)

UPDATE: Please be aware that while modern/metro apps are restricted from poking at each other's stuff, desktop applications will have unrestricted access to all data stored through these APIs. See http://www.hanselman.com/blog/SavingAndRetrievingBrowserAndOtherPasswords.aspx which includes code demonstrating this.
Win8 has a new API called PasswordVault that's designed for taking care of all these hard problems for you. Really easy to use, secure, and can be configured by users to roam between their machines so they only have to enter credentials once. I've successfully used this for OAuth tokens
Retrieving credentials (note the stupid exception that WinRT raises... they really should just return null):
const string VAULT_RESOURCE = "[My App] Credentials";
string UserName { get; set; };
string Password { get; set; };
var vault = new PasswordVault();
try
{
var creds = vault.FindAllByResource(VAULT_RESOURCE).FirstOrDefault();
if (creds != null)
{
UserName = creds.UserName;
Password = vault.Retrieve(VAULT_RESOURCE, UserName).Password;
}
}
catch(COMException)
{
// this exception likely means that no credentials have been stored
}
Storing credentials:
vault.Add(new PasswordCredential(VAULT_RESOURCE, UserName, Password));
Removing credentials (when the user clicks the logout button in your app):
vault.Remove(_vault.Retrieve(VAULT_RESOURCE, UserName));

It depends on what you need, if you realy need to store the passwords you should use a 2-way encryption algorithm like 3DES/RC2/Rijndael etc.
However, if all you need to be able to do is verify if a password is correct it is recommended to use a oneway function to store a hash.
When dealing with sensitive data I realy recommend the encrypt/hash it, even if you use windows 8. Encryption does mean extra overhead but in most cases you will not notice the speed difference.
Would it be better to write your own custom/lite algorithm? As a security guy I advise against it. People spend years testing, improving and trying to find holes in existing algoritms. The ones that survived are therefore quite good.

you could encrypt like this:
public static string EncodePassword(string password)
{
byte[] bytes = Encoding.Unicode.GetBytes(password);
byte[] inArray = HashAlgorithm.Create("SHA1").ComputeHash(bytes);
return Convert.ToBase64String(inArray);
}
And when checking the user input, you also trow it into this method and check for it to match.
In case of data that you put in an xml (for example) that you want to encrypt/decrypt you can use RijndaelManaged.
-Edit1-
An example:
if you have a small login screen that pops up (ShowDialog) you can is it like this snip-it:
private void settings_Click(object sender, RoutedEventArgs e)
{
Login log = new Login(); //login window
log.ShowDialog(); //show the login window
string un = log.userName.Text; //the user input from the username field
string pw = log.passWord.Password; //the userinput from the password input
if (EncodePassword(un) == Properties.Settings.Default.adminUsername && EncodePassword(pw) == Properties.Settings.Default.adminPassword) //in my case, i stored it in the app settings, but this could also be somewhere else.
{
//login was correct
//do something
}
else
{
//login was not correct
}
}

Related

Is there a way to authenticate UWP app with razor-pages created accounts?

First, I am pretty new to C# and sorry for the bad writing, I have a razor page web app with individual accounts authentication type. Now I am working on a UWP app in which users can log in to the UWP app with the username and password provided in the razor app. Users have the same username and password for both applications.
Is there any possible way to log in user to the UWP app and also limit users to access different parts of the app just like razor pages(Role manager)?
Please note that the razor app is on a local server (on-premise), not a cloud, also the UWP app is on the same network so it can access the database.
What is expected to happen is that users must provide a username and password in the UWP app, they have limited access based on their roles, user names and passwords are fetched from the razor page application Db, UWP app doesn't need the ability to create or edit user accounts(it's all managed by razor app)
Update
Please be more specific about your question next time.
if you want to hash the password in UWP apps, you could use HashAlgorithmProvider Class to hash the text. The HashAlgorithmProvider class support MD5,SHA1,SHA256,SHA384,SHA512. You could choose the same way as you choosed in your razor app.
The sample code looks like this:
public string SampleHashMsg()
{
string strAlgName = HashAlgorithmNames.Md5;
string strMsg = "thisistest";
// Convert the message string to binary data.
IBuffer buffUtf8Msg = CryptographicBuffer.ConvertStringToBinary(strMsg, BinaryStringEncoding.Utf8);
// Create a HashAlgorithmProvider object.
HashAlgorithmProvider objAlgProv = HashAlgorithmProvider.OpenAlgorithm(strAlgName);
// Demonstrate how to retrieve the name of the hashing algorithm.
string strAlgNameUsed = objAlgProv.AlgorithmName;
// Hash the message.
IBuffer buffHash = objAlgProv.HashData(buffUtf8Msg);
// Verify that the hash length equals the length specified for the algorithm.
if (buffHash.Length != objAlgProv.HashLength)
{
throw new Exception("There was an error creating the hash");
}
// Convert the hash to a string (for display).
string strHashBase64 = CryptographicBuffer.EncodeToHexString(buffHash);
// Return the encoded string
return strHashBase64;
}
Old
Your post contains many questions. Please focus on question in one post next time.
First, you need to check the document: Use a SQL Server database in a UWP app. This tutorial shows the steps about how to connect to a sql server in UWP apps. Then you will have to write your own logic for checking the input for username and password and verify it with the data in the database.
After that, you might need to create a userinfo class which contains a flag that could indicate the role or the user after you verified the user. Before navigation, you could check the flag do decide if the user could access the page. If not, then cancel the navigation.

Implement a secure login mechansim in Windows presentation foundation (WPF) application

I created a small WPF application that does some operations. I would like to distribute this application to some people, but I want it to be accessible only by the authorized people. I don't really need a registering mechanism.
Because the application is quite small and will be delivered as an EXE file, I don't think that having a database would be an efficient idea.
I was thinking of having a file within the application that contain the credentials of the authorized people, but as far as I know, WPF applications can be easily reversed engineered. I turned my thinking into having the application contact a server to authorize the person or something, but wasn't sure whether it is a good choice or not.
Can you please suggest or throw at me some readings or best practices to study, because whenever I search about this topic I get an example of implementing the UI (which is something i know how to do) and not the login mechanism.
Design Guidelines for Rich Client Applications by MSDN
https://msdn.microsoft.com/en-in/library/ee658087.aspx
Read Security Considerations, Data Handling Considerations and Data
Access
It is very easy to reverse any .Net app , So the point of having an authentication system is for dealing with Noobs and people who do not know about reverse programming , you can use authentication system using Cpu Id for example witch i use , but any way like i said any .Net is reversible .
I will shier my authentication logic with you:
public static string GetId( )
{
string cpuInfo = string.Empty;
ManagementClass mc = new ManagementClass("win32_processor");
ManagementObjectCollection moc = mc.GetInstances( );
foreach (ManagementObject mo in moc)
{
if (cpuInfo == "")
{
//Get only the first CPU's ID
cpuInfo = mo.Properties["processorID"].Value.ToString( );
break;
}
}
return cpuInfo;
}
After you have cpu id do some encryption
Public static string Encrypt(string CpuId)
{ // do some encryption
retuen encryptionCpuId;
}
after that in your UI create a dialog window show the user his cpuID and he will send it to you, after that you will encrypt user's cpuID and give him his activation Key , to do that you must create an other project for generate encryption , And in your App (That you want to publish) check :
if(Key== Encrypt(GetId()) {// Welcome }
else {Environment.Exit(0); }
So every user have his own Key.
After all this you must know that any one can reflect your code and crack this mechanism.

How to store information like passwords encrypted but not in hash

I need to store "password like information" in a database field. I would like it to be encrypted but I need to decrypt it before using it. So I can not use a Hash/Salt solution.
Granted if an attacker made it that far into the database it may be too far gone but I figure this would at least stop the mistaken dump of the data.
How to encrypt a value store it into the database and decrypt the same value for use later?
Hashing is not an option (I use it on other parts actually).
Where to store the private key? Users would not supply anything.
This a C# solution so .NET specific stuff would be great. My question is very similar but I am looking for a .net based solution: Two-way encryption: I need to store passwords that can be retrieved
EDIT:
Hogan pretty much answered my question. I found examples out there and they ranged from very complicated to rather simple. It looks like AES is still good so I will be using that method. thank you for all your help.
One solution that does not involve private keys is using DPAPI.
You can use it from .NET via the ProtectedData class.
Here is an example:
public void Test()
{
var password = "somepassword";
var encrypted_password = EncryptPassword(password);
var decrypted_password = DecryptPassword(encrypted_password);
}
public string EncryptPassword(string password)
{
var data = Encoding.UTF8.GetBytes(password);
var encrypted_data = ProtectedData.Protect(data, null, DataProtectionScope.CurrentUser);
return Convert.ToBase64String(encrypted_data);
}
public string DecryptPassword(string encrypted_password)
{
var encrypted_data = Convert.FromBase64String(encrypted_password);
var data = ProtectedData.Unprotect(encrypted_data, null, DataProtectionScope.CurrentUser);
return Encoding.UTF8.GetString(data);
}
Please note that DPAPI in this case depends on the current logged in user account. If you encrypt the password when your application is running as User1, then you can only decrypt the password running under the same user account. Please note that if you change the windows password for User1 in an incorrect way, then you will lose the ability to decrypt the password. See this question for details.
If you don't want use DPAPI, and prefer to have a private key. Then the best place to store such private key is in the user's key store. However, in order to store a private key in the local user store, you need to have a certificate for it. You can create a self signed certificate and store it with its corresponding private key into the local user certificate store.
You can access the user store in code using the X509Store class. You can use it to find the certificate (which is in C# a X509Certificate2 class) that you want to use and then use it to do encryption/decryption.
See this and this for more details.

How to store and retrieve credentials on Windows using C#

I build a C# program, to be run on Windows 10. I want to send emails from this program (calculation results) by just pressing a button. I put the from: e-mail address and the subject:, etc. in C# properties, but I do not want to put a clear text password anywhere in the program, AND I don't want the user to have to type in the password for the server each time a mail is sent.
Can that be done?
If so, how (generally)?
I was thinking of putting all that e-mail information, including an encrypted password for the server in a data file to be read during startup of the program.
Or maybe Windows 10 has a facility for that...
You can use the Windows Credential Management API. This way you will ask the user for the password only once and then store the password in Windows Credentials Manager.
Next time your application starts and it needs to use the password it will read it from Windows Credentials Manager. One can use the Windows Credential Management API directly using P/Invoke (credwrite, CredRead, example here) or via a C# wrapper CredentialManagement.
Sample usage using the NuGet CredentialManagement package:
public class PasswordRepository
{
private const string PasswordName = "ServerPassword";
public void SavePassword(string password)
{
using (var cred = new Credential())
{
cred.Password = password;
cred.Target = PasswordName;
cred.Type = CredentialType.Generic;
cred.PersistanceType = PersistanceType.LocalComputer;
cred.Save();
}
}
public string GetPassword()
{
using (var cred = new Credential())
{
cred.Target = PasswordName;
cred.Load();
return cred.Password;
}
}
}
I don't recommend storing passwords in files on client machines. Even if you encrypt the password, you will probably embed the decryption key in the application code which is not a good idea.

Recognize user already logged in C# WPF

I have created the registration and login form. Both work perfectly. But how do i recognize the user logged in as the PHP does by using SESSIONS and COOKIES. I can use static class to get data between different pages, but how can i retrieve the logged user data if he closes the application.
Is there any way for achieving this?
Thanks!
I'm assuming that you want something like instant messenger applications like Skype, or cloud storage applications like DropBox, OneDrive or Mega do. They ask you to enter user name and password once, and then start automatically without asking for user's credentials again.
They achieve this by storing user name and password in encrypted format in the file they normally keep in application folder under specific user account. See the following link for details: How can I get the current user directory?
This is standard practice, as another user will not be automatically logged into your app, if they not entered their own credentials.
Make sure you encrypt the user name and password or the whole file before saving it to disk, otherwise it may become an easy target for password stealing malware.
You should use user settings to do this, as this mechanism hides all the necessary work for creating files in the right locations, etc. from the developer. It works fine and it is made for stuff like this.
You design them in Visual Studio in the project properties on the "Settings" tab. Make sure to select the settings type correctly, as application settings are read-only.
Assume you have to settings UserName and UserPassword. Then, in your code, you could do this:
if (String.IsNullOrWhitespace(Properties.Settings.Default.UserName))
{
// USER NEEDS TO LOG IN
string userName;
string password;
if (Login(out userName, out password))
{
try
{
Properties.Settings.Default.UserName = Encrypt(userName);
Properties.Settings.Default.Password = Encrypt(password);
Properties.Settings.Default.Save();
}
catch (Exception exp)
{
...
}
}
}
else
{
// USER IS ALREADY LOGGED IN
}
private bool Login(out string userName, out string password) would be a method that shows a login user interface and returns true on success or false on failure.
private string Encrypt(string input) would be a method to encrypt a string.

Categories

Resources