We have a Ruby on Rails app that uses the Devise gem for user handling, including creating and authenticating user passwords. The passwords are encrypted in the MySQL database obviously. We are using Devise defaults for how it encrypts the password. Now we have another small same-LAN side app that (a C# ASP.NET app) needs to authenticate with a user/password directly with the database to do some read-only operations.
How can we best mimic what Devise does for user/password authentication in the C# ASP.NET app against the very same data in the MySQL database?
Essentially, I need to figure out how to recreate Devise's valid_password? method in C# .NET
http://www.rubydoc.info/github/plataformatec/devise/Devise/Models/DatabaseAuthenticatable#valid_password%3F-instance_method
# File 'lib/devise/models/database_authenticatable.rb', line 46
def valid_password?(password)
return false if encrypted_password.blank?
bcrypt = ::BCrypt::Password.new(encrypted_password)
password = ::BCrypt::Engine.hash_secret("#{password}#{self.class.pepper}", bcrypt.salt)
Devise.secure_compare(password, encrypted_password)
end
I think I understand the question correctly. What you want to do is authenticate a user on you .NET application using the credentials on your rails application. If so, I would suggest implementing an oauth server on the ruby side and a client in you .NET code. As for the server you have several gems that provide this functionality including
oauth-ruby
doorkeeper
oauth2-provider
Devise uses BCrypt for password storage, and so thankfully the verification process is fairly simple. Install the BCrypt.Net NuGet package (or any other BCrypt implementation), and then do this:
public static bool ValidPassword(string userSuppliedPassword, string hashedAndSaltedPassFromDatabase)
{
return BCrypt.Net.BCrypt.Verify(userSuppliedPassword, hashedAndSaltedPassFromDatabase);
}
I was having a similar requirement of verifying already existing users from the C# application.
I used package bcrypt.net - next for BCrypt.
Here is the code snippet which I used
static void Main(string[] args)
{
const string DEVISE_PEPPER = "Here comes the devise pepper value";
// One pass
string pass = "reE8TuLcZ44XwRz";
const string passHash = "$2a$10$1Rm.BC0hnF1laC7MFJ/B0eFu2rtG1Asy6fRqJVdqcfBO6LASn4Nqa";
// Second pass
const string secondPass = "FpRfaaqzNNRAum9";
const string secondPassHash = "$2a$10$/Ex4x9LkvxIncaXhByqVP.YRdwRlZFJ7p4H96BfqHk1oGmw3YwLMC";
// How Ruby BCyrpt verify? Ref - https://www.freecodecamp.org/news/how-does-devise-keep-your-passwords-safe-d367f6e816eb/
// 1. Fetch the input password
// 2. Fetch the salt of the stored password
// 3. Generate the hash from the password and salt using the same bcrypt version and cost factor
// 4. Check if the stored hash is the same one as the computed on step 3
// Ref - https://github.com/heartcombo/devise/blob/5d5636f03ac19e8188d99c044d4b5e90124313af/lib/devise/encryptor.rb#L14
var finalPass = $"{secondPass}{DEVISE_PEPPER}";
var verified = BCrypt.Net.BCrypt.Verify(finalPass, secondPassHash);
var verifiedTxt = verified ? "verified!" : "didn't verified.";
Console.WriteLine($"Password and hash {verifiedTxt}");
Console.ReadKey();
}
I was successfully able to verify the password.
Related
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.
I'm attempting to create a password expiration function in my application. Passwords are already set up as well as authentication and changing passwords. Now I want to prompt the user to change their password after x amount of time.
When the user goes to change their password and my Angular frontend makes that request I want my C# Service Stack API to compare the given new password with the current password and the password before that to check for duplication.
I'm not worried about slight variations. If the user submits the same password but with one extra character for example, that's fine. I want to be an simple as possible to start.
The passwords are stored in a MS SQL Server in two columns Salt varchar(8000) and PasswordHash varchar(8000). I've got everything set up I'm just very confused on how to compare the hashed password with the string provided by the User. Then save the old password in a new hashed column. I've been searching the web and SOF for three days now and I haven't found anything. Any guidance would be greatly appreciated.
Following on #Fildor comment, you'll need to create an audit history of password changes containing the hashes of existing passwords. From ServiceStack v5+ ServiceStack switched to use the same PBKDF2 password hashing algorithm ASP.NET Identity v3 uses which stores the password hash + salt + iterations + algorithm version in a single PasswordHash field on UserAuth table, so your password audit history table only needs a single column to store the existing password hash.
The password hashing algorithm is available from the IPasswordHasher dependency, which you can use in your Service implementation like:
public IPasswordHasher PasswordHasher { get; set; }
public object Any(AllowPassword request)
{
var passwordHashes = MyRepo.GetExistingUserPasswords(GetSession().UserAuthId);
foreach (var passwordHash in passwordHashes)
{
if (PasswordHasher.VerifyPassword(passwordHash, request.Password, out var neeedsRehash)
throw new ArgumentException("Can't use existing password", nameof(request.Password));
}
return new AllowPasswordResponse();
}
I have a database of logins and passwords. I wouldn't like that anyone who has access to the database can see everybody's password. How can I encrypt the passwords in the database?
In other words, I want the fields pwd (password) to be encrypted in the database but it is automatically decrypted when I enter it in the LoginForm.
I have found a method that encrypt the strings input but it doesn't solve my issue.
static string Encrypt(string value)
{
using (MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider())
{
UTF8Encoding utf8 = new UTF8Encoding();
byte[] data = md5.ComputeHash(utf8.GetBytes(value));
return Convert.ToBase64String(data);
}
}
private void BtnEncrypt_Click(object sender, EventArgs e)
{
if (string.IsNullOrEmpty(txtPass.text))
{
MessageBox.Show("Please enter your password !");
}
texResult.Text=Encrypt(txtPass.Text);
}
Please, can somebody help me.
Thanks in advance.
You can Encrypt your password using your Encrypt function and store the Encrypted password in your database.
But Decrypting the password, is not a good option. Password Encryption should be one way.
To check whether the password is available in your database, you can Encrypt the password entered by user by using the same Encrypt function, then match that Encrypted password to encrypted password you have in your database.
Thanks
It is easy to muddle encryption with hashing. What you are asking about is encryption - encryption lets you turn your password into an apparently random sequence of characters which can then be decrypted to get the original password back. What you should be using (and some have suggested) is hashing.
There are lots of examples of how to do encryption/decryption on the net, just search. This is the first one that came up for me: http://www.codeproject.com/Articles/14150/Encrypt-and-Decrypt-Data-with-C Tempting as it is to copy and paste the code from there, I won't because this isn't what you should be doing. For storing user passwords in a database it is much better to use password hashing (with salt) than to store encrypted passwords. Why? because then if your system is hacked it is impossible for an attacker to recover people's passwords - all your accounts might still be compromised but given that people often use the same password for more than one system you won't be compromising your users.
A hash is a one way function, so you can't get the original password back. When someone wants to login you simply generate a hash and then compare it with the one you have stored in the database. If you want to read more about this and why you should be using it then this is a good start: https://crackstation.net/hashing-security.htm If you would like to jump in and get some working code then have a look at Hash and salt passwords in C#.
You can use any complex cryptography technique to encrypt a password and send the password key to be saved in database for corresponding user.
Now when the client tries to login and enters password, sends it to server.
From the server you can again convert the login details and compute the hash and finally send to a stored procedure to compare. If the two strings match, you return true else false as for authentication.
using System.Security.Cryptography;
...
...
...
private const string _alg = "HmacSHA256";
private const string _salt = "rz8LuOtFBXphj9WQfvFh"; // Generated at https://www.random.org/strings
public static string GenerateToken(string username, string password)
{
string hash = string.Join(":", new string[] { username, password });
using (HMAC hmac = HMACSHA256.Create(_alg))
{
hmac.Key = Encoding.UTF8.GetBytes(GetHashedPassword(password));
hmac.ComputeHash(Encoding.UTF8.GetBytes(hash));
hash = Convert.ToBase64String(hmac.Hash);
}
return Convert.ToBase64String(Encoding.UTF8.GetBytes(hash));
}
public static string GetHashedPassword(string password)
{
string key = string.Join(":", new string[] { password, _salt });
using (HMAC hmac = HMACSHA256.Create(_alg))
{
// Hash the key.
hmac.Key = Encoding.UTF8.GetBytes(_salt);
hmac.ComputeHash(Encoding.UTF8.GetBytes(key));
return Convert.ToBase64String(hmac.Hash);
}
}
MD5 is not secure anymore.
When a user register to use your application, hash the password with SHA512 bit with salt. You can find like PWDTK nuget package which we can easily use. Password is what we don't need to know what it means but just plays a secure role. Like some person commented above, when the user try to log-in after user registration, just encrypt the user's input(password) and compare it with that registered in SQL database. Password must be one-way.
After the login result comes up success or fail, the role of password is finished.
As of Winform cases, you need to deeply consider to secure the connectionstring to connect to SQL database. One possible option might be WCF middleware between Winform application and SQL database.
And for last but very importantly, you must use SSL for secure communication.
It seems you might consider these at later stages.
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.
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
}
}