I am encoding my password using the code below, how can i decode it to the correct one using C#
public static string EncodePassword(string password)
{
var provider = new SHA256CryptoServiceProvider();
var encoding = new UnicodeEncoding();
return Convert.ToBase64String(provider.ComputeHash(encoding.GetBytes(password)));
}
You can't That is the idea behind password hashing.
You can only check if a password is correct by hashing the input and comparing it
with the stored hash. This is to avoid hackers from stealing your password
Related
I need to encrypt a password and add it as a http header to make a rest call from a python client. I am trying to implement the following C# code listed below in Python, but the rest POST request seems to be failing with Python as the encrypted password string generated from python does not seem to be matching the encrypted password from C# . The C# code generates the correct encrypted password
modulus: "w1jcEfmxCTz5aB9wGg1Vl5K45VUm8Aj7+05sBarmrwbvC9BNjAqSySPmC2ajWSQGdmBs4xylKZjHKaXg5rxuNw=="
exponent:
"AQAB"
password to encrypt:'tricky'
encrypted password from C#(keeps changing each time it is generated): '%14%1d%0a%bb%a0X%24H%ad%ce%9aG%f6a%dau%d8%01%ec%d5)+%d3%11%8e%3ew%c8K%dce%ec%84K%e6%1d%ea%81%3e%d14%87%80s%8eo%a6%bc%fd%1b%8f%a1V8%c8%96%b1%ec%1f%d7qd%bbz'
encrypted password from Python:'%21%F6%7E.i%F4%F4%5E%E5%A9v%03E%8C%1C%3E%F1%D7%DBT%A2%03z%BF%E2%E8%8FJh%E3%85%AA%24%25%C2%C9Hg%18z%22a%F8g%0B%81%3C%DC%FEr%F8C%98s%B5%DA1%F6%60%23%BAw%10F'
Here is my python code using Pycrypto which does the encryption:
from base64 import b64decode
from Crypto.PublicKey.RSA import construct
def get_encrypted_password(password, modulus, exponent):
password = password.encode('utf-8')
# decode base64 string to be used as modulus(n) and exponent(e) components for constructing the RSA public key object
modulus = b64decode(modulus)
exponent = b64decode(exponent)
n = int.from_bytes(modulus, byteorder=sys.byteorder)
e = int.from_bytes(exponent, byteorder=sys.byteorder)
pubkey = construct((n,e))
encrypted = pubkey.encrypt(password,None)[0]
#url encode the encrypted password
encrypted = urllib.parse.quote_plus(encrypted)
return encrypted
This is the C# code which does the encryption:
public static string EncryptForTransport(string strToEncrypt, string rsaPublicKey)
{
KeyContainerPermission permission = new KeyContainerPermission(KeyContainerPermissionFlags.AllFlags);
permission.Assert();
if (string.IsNullOrEmpty(strToEncrypt))
{ return strToEncrypt; }
RSACryptoServiceProvider rsaEncryptor = GetRsaEncryptor(rsaPublicKey);
byte[] buffer = rsaEncryptor.Encrypt(Encoding.UTF8.GetBytes(strToEncrypt), false);
try
{
rsaEncryptor.Clear();
}
catch (CryptographicException)
{
//errors may occur ignore them.
}
string encryptedStr = HttpUtility.UrlEncode(buffer);// byteConverterGetString;
return encryptedStr;
}
private static RSACryptoServiceProvider GetRsaEncryptor(string rsaPublicKey)
{
RSACryptoServiceProvider.UseMachineKeyStore = true;
RSACryptoServiceProvider rsaEncryptor = RSACryptoServiceProvider.Create() as RSACryptoServiceProvider;
if (rsaEncryptor.PersistKeyInCsp)
rsaEncryptor.PersistKeyInCsp = false;
rsaEncryptor.FromXmlString(rsaPublicKey);
return rsaEncryptor;
}
Any ideas on what I might be doing wrong with encrypting the password using RSA in Python?
To match what the C# code is doing you must parse the big-endian modulus and exponent correctly, and use PKCS v1.5 padding. This example below modifies your code slightly to show this.
from base64 import b64decode
from Crypto.PublicKey.RSA import construct
from Crypto.Cipher import PKCS1_v1_5
import urllib.parse
def get_encrypted_password(password, modulus, exponent):
password = password.encode('utf-8')
# decode base64 string to be used as modulus(n) and exponent(e) components for
# constructing the RSA public key object
modulus = b64decode(modulus)
exponent = b64decode(exponent)
n = int.from_bytes(modulus, byteorder='big')
e = int.from_bytes(exponent, byteorder='big')
pubkey = construct((n, e))
pubkey = PKCS1_v1_5.new(pubkey)
encrypted = pubkey.encrypt(password)
# url encode the encrypted password
encrypted = urllib.parse.quote_plus(encrypted)
return encrypted
I want to create random password and salt.
Now I have a function based who Encrypt password like:
public string EncryptPassword(string password, string salt)
{
using (var sha256 = SHA256.Create())
{
var saltedPassword = string.Format("{0}{1}", salt, password);
byte[] saltedPasswordAsBytes = Encoding.UTF8.GetBytes(saltedPassword);
return Convert.ToBase64String(sha256.ComputeHash(saltedPasswordAsBytes));
}
}
So I want to do same encode password and salt but with random values, and before encode it I want to know what password is. How can I do it?
I have something like this:
public string EncryptPasswordRandom()
{
var password = // some random password, how can I generate it?
var salt = // how can I generate it?
using (var sha256 = SHA256.Create())
{
var saltedPassword = string.Format("{0}{1}", salt, password);
byte[] saltedPasswordAsBytes = Encoding.UTF8.GetBytes(saltedPassword);
return Convert.ToBase64String(sha256.ComputeHash(saltedPasswordAsBytes));
}
}
Help is very appreciated. Regards
Note: I have a web application who works well, I can register user and
login, this random password is for recovery password and made one
random
System.Web.Membership has a GeneratePassword method that will do the job.
As for randomly generating the salt Guid.New() should work.
This answer addresses generating the salt in a high entropy fashion.
It might help if you explain what you are attempting to accomplish as well. At face value it looks like an odd requirement unless this is in a test of some sort.
I've been reading this article from MSDN on Rfc2898DeriveBytes. Here is the sample encryption code they provide.
string pwd1 = passwordargs[0];
// Create a byte array to hold the random value.
byte[] salt1 = new byte[8];
using (RNGCryptoServiceProvider rngCsp = ne RNGCryptoServiceProvider())
{
// Fill the array with a random value.
rngCsp.GetBytes(salt1);
}
//data1 can be a string or contents of a file.
string data1 = "Some test data";
//The default iteration count is 1000 so the two methods use the same iteration count.
int myIterations = 1000;
try
{
Rfc2898DeriveBytes k1 = new Rfc2898DeriveBytes(pwd1,salt1,myIterations);
Rfc2898DeriveBytes k2 = new Rfc2898DeriveBytes(pwd1, salt1);
// Encrypt the data.
TripleDES encAlg = TripleDES.Create();
encAlg.Key = k1.GetBytes(16);
MemoryStream encryptionStream = new MemoryStream();
CryptoStream encrypt = newCryptoStream(encryptionStream, encAlg.CreateEncryptor(), CryptoStreamMode.Write);
byte[] utfD1 = new System.Text.UTF8Encoding(false).GetBytes(data1);
encrypt.Write(utfD1, 0, utfD1.Length);
encrypt.FlushFinalBlock();
encrypt.Close();
byte[] edata1 = encryptionStream.ToArray();
k1.Reset();
My question is, how would I properly Read/Write the hashed data to/from a text file?
My main goal is to do what this developer is doing. I need to store a password locally. When my application prompts the user for the password, the user will enter the password, then my application will read from the text file and verify if the password that the user entered is indeed correct. How would I go about doing it?
You typically store the hash of the password, then when user enters password, you compute hash over the entered password and compare it with the hash which was stored - that said, just hashing is usually not enough (from security point of view) and you should use a function such as PKBDF2 (Password-Based Key Derivation Function 2) instead. Here is article covering all that information in more elaborate way as well as sample code (bottom of the page): http://www.codeproject.com/Articles/704865/Salted-Password-Hashing-Doing-it-Right
Here is a link to codereview, which I guess refers to the same implementation as above article.
How to properly store password locally
Just don't do it. No really don't do it.
...But if you really really have to, never just implement it yourself. I would recommend reviewing how ASP.NET Identity hashes passwords. Version 3 is pretty rock solid at the moment:
note that the following is taken from github.com and may be changed at any time. For the latest, please refer to the previous link.
private static byte[] HashPasswordV3(string password, RandomNumberGenerator rng, KeyDerivationPrf prf, int iterCount, int saltSize, int numBytesRequested)
{
// Produce a version 3 (see comment above) text hash.
byte[] salt = new byte[saltSize];
rng.GetBytes(salt);
byte[] subkey = KeyDerivation.Pbkdf2(password, salt, prf, iterCount, numBytesRequested);
var outputBytes = new byte[13 + salt.Length + subkey.Length];
outputBytes[0] = 0x01; // format marker
WriteNetworkByteOrder(outputBytes, 1, (uint)prf);
WriteNetworkByteOrder(outputBytes, 5, (uint)iterCount);
WriteNetworkByteOrder(outputBytes, 9, (uint)saltSize);
Buffer.BlockCopy(salt, 0, outputBytes, 13, salt.Length);
Buffer.BlockCopy(subkey, 0, outputBytes, 13 + saltSize, subkey.Length);
return outputBytes;
}
You should store the password as a one-way hash and the salt used to create that password. This way you are absolutely sure that the password for the user can never be DECRYPTED. Never use any two-way encryption for this particular task, as you risk exposing user information to would-be attackers.
void Main()
{
string phrase, salt, result;
phrase = "test";
result = Sha256Hash(phrase, out salt);
Sha256Compare(phrase, result, salt);
}
public string Sha256Hash(string phrase, out string salt)
{
salt = Create256BitSalt();
string saltAndPwd = String.Concat(phrase, salt);
Encoding encoder = Encoding.Default;
SHA256Managed sha256hasher = new SHA256Managed();
byte[] hashedDataBytes = sha256hasher.ComputeHash(encoder.GetBytes(saltAndPwd));
string hashedPwd = Encoding.Default.GetString(hashedDataBytes);
return hashedPwd;
}
public bool Sha256Compare(string phrase, string hash, string salt)
{
string saltAndPwd = String.Concat(phrase, salt);
Encoding encoder = Encoding.Default;
SHA256Managed sha256hasher = new SHA256Managed();
byte[] hashedDataBytes = sha256hasher.ComputeHash(encoder.GetBytes(saltAndPwd));
string hashedPwd = Encoding.Default.GetString(hashedDataBytes);
return string.Compare(hash, hashedPwd, false) == 0;
}
public string Create256BitSalt()
{
int _saltSize = 32;
byte[] ba = new byte[_saltSize];
RNGCryptoServiceProvider.Create().GetBytes(ba);
return Encoding.Default.GetString(ba);
}
You could also figure out another method for obtaining the salt, but I have made mine to that it computes 2048 bits worth of random data. You could just use a random long you generate but that would be a lot less secure. You won't be able to use SecureString because SecureString isn't Serializable. Which the whole point of DPAPI. There are ways to get the data out but you end up having to jump a few hurdles to do it.
FWIW, PBKDF2 (Password-Based Key Derivation Function 2) is basically the same thing as SHA256 except slower (a good thing). On its own both are very secure. If you combined PBKDF2 with an SHA256 as your salt then you'd have a very secure system.
I am using Hashing and Salt to decrypt the password. that is the methods I am using:
public string CreateSalt(int size)
{
var rng = new RNGCryptoServiceProvider();
var buff = new byte[size];
rng.GetBytes(buff);
return Convert.ToBase64String(buff);
}
public string GenerateHash(string input, string salt)
{
byte[] bytes = Encoding.UTF8.GetBytes(input + salt);
SHA512Managed sha256 = new SHA512Managed();
byte[] hash= sha256.ComputeHash(bytes);
return ByteArrayToHexString(hash);
}
After I hashed the password and save it to database, how I can rehash it? Or even if I need rehashing at all?
Users are going to create their password to login to the website. I haven't decide how forgot password is going to work, so maybe it is going to reset the password and send to them. Any thought, Idea around hashing?
You have to store both the hashed password and password salt in the database. When the users log in, you get the input password, hashed it with the stored salt in database, then compare the result with the stored hashed password.
You're right about the forgot password. Just create a random password and send it to the users.
I have a table with usenames, hashed password and their salts, now in my application I want to verif the plain password with hashed one below is what I tried but does not generate the same hash, please suggest how can I solve this problem.
byte[] bIn = Encoding.Unicode.GetBytes(Password);
byte[] bSalt = Convert.FromBase64String(SaltValue);
byte[] bAll = new byte[bSalt.Length + bIn.Length];
Buffer.BlockCopy(bSalt, 0, bAll, 0, bSalt.Length);
Buffer.BlockCopy(bIn, 0, bAll, bSalt.Length, bIn.Length);
HMACSHA256 s = new HMACSHA256();
return Convert.ToBase64String(s.ComputeHash(bAll));
You should create one method to hash a password with a salt. Then use this method to encrypt the initial password. If you reuse this method verifying the password afterwards it will always match.
Make sure you retrieved the correct salt from your database for the account.