Import MD5 Passwords from a PHP app to ASP.NET - c#

So I'm in the process of writing an ASP.NET application that requires to import users from a PHP application. The passwords were hashed using MD5 into the database, so the user table records looks more or less like this:
user Password
user1 827ccb0eea8a706c4c34a16891f84e7b
user2 e10adc3949ba59abbe56e057f20f883e
And so on. I have access to the PHP source code and I can see that there is no salt or anything else, it is juts a straight MD5 application. Now, Back on my ASP.NET, I tried to use MD5 using the following logic:
public static string HashPassword(string Password)
{
//Declarations
Byte[] originalBytes;
Byte[] encodedBytes;
MD5 md5;
originalBytes = ASCIIEncoding.Default.GetBytes(Password);
md5 = new MD5CryptoServiceProvider();
encodedBytes = md5.ComputeHash(originalBytes);
return BitConverter.ToString(encodedBytes);
}
Problem is, that is returning strings like 50-F8-4D-AF-3A-6D-FD-6A-9F-20-C9-F8-EF-42-89-42, which of course is not going to match with the information in the database. What should I do so I don't have to reset 500+ user passwords?

Return this instead:
return Encoding.UTF8.GetString(encodedBytes).ToLowerInvariant();
BitConverter explicitly inserts dashes in the string value.
Or of course you could keep using BitConverter and just do .Replace("-","").ToLower()

Related

c# encoding to PHP encoding

I have an ASP project in which some encoding algorithm is used to save the password. I have to convert c# code to PHP code to compare the password with my table value in SQL database.
Code used in c# for encoding is
MD5CryptoServiceProvider md5Hasher = new MD5CryptoServiceProvider();
Byte[] hashedDataBytes;
UTF8Encoding encoder = new UTF8Encoding();
hashedDataBytes = md5Hasher.ComputeHash(encoder.GetBytes(password));
Now while registration, I entered the password '123456', and when I checked table Customers , password saved is 0xE10ADC3949BA59ABBE56E057F20F883E00000000000000000000000000000000000000000000000000000000000000000000
and column structure in the table is Password (binary(50),null).
Can any one please tell me what code should I use in PHP to compare '123456' with
0xE10ADC3949BA59ABBE56E057F20F883E00000000000000000000000000000000000000000000000000000000000000000000
You have to check the method ComputeHash in the class MD5CryptoServiceProvider
and write a similiar class/method in PHP
With that bit of code, nobody can help you!

Convert ASP.NET membership passwords from clear text to hashed

We were hashing our passwords, although somewhere along the way one of our developers changed it to clear text so that we could email a user their password if they forgot it.
Anyhow, I'm changing it so that we store passwords 'hashed' now. There is a group of passwords which we need to hash. The salt is already there in the database, I just need to loop through where "passwordformat" = 0 and hash accordingly. How do I do this?
edit: I had a go at a suggestion from another SO post, using "SHA-1" as the hashing algorithm to calculate the digest. It was not the result I expected.
I know the original clear password, the salt, but the result is not what I expected. The answer in the above suggests using SHA-1 as the hashing algo.
If it's any help this is from our web.config of the web server.
<add name="AspNetSqlMembershipProvider"
type="System.Web.Security.SqlMembershipProvider, System.Web, Version=2.0.0.0,
EDIT: I'm getting somewhere. I created another test user, and this time got the same digest value as that generated by the web application. Only difference was the one salt contained '/' symbol, and the other did not. I was not aware that '/' would cause an issue, as I didn't think it's an escape character.
EDIT: here is my code. It works only if the salt does not contain '/'
public static string EncodePassword3(string pass, string saltBase64)
{
byte[] bytes = Encoding.Unicode.GetBytes(pass);
byte[] src = Convert.FromBase64String(saltBase64);
byte[] dst = new byte[src.Length + bytes.Length];
byte[] inArray = null;
Buffer.BlockCopy(src, 0, dst, 0, src.Length);
Buffer.BlockCopy(bytes, 0, dst, src.Length, bytes.Length);
HashAlgorithm algorithm = HashAlgorithm.Create("SHA1");
inArray = algorithm.ComputeHash(dst);
return Convert.ToBase64String(inArray);
}
I can supply the clear text password and salt (only testing at mo) to see if you can get the correct result....

pbkdf2 computation not consistent between C# and JavaScript

Hi my question is I've Encrypted a password with crypto.pbkdf2 on windows azure server side Javascript I'm pretty sure that there is a public library which you can look up. The problem is I'm trying to encrypt the same password in C# on my system because I want the credentials to be universal but despite using Rfc2898DeriveBytes and the salt generated the first time I'm not able to get back to the same hashed password.
Thank you for your help :)
function hash(text, salt, callback) {
crypto.pbkdf2(text, salt, iterations, bytes, function(err, derivedKey){
if (err) { callback(err); }
else {
var h = new Buffer(derivedKey).toString('base64');
callback(null, h);
}
});
}
And the C# code:
byte[] salt = Convert.FromBase64String(user.salt);
using (var deriveBytes = new System.Security.Cryptography.Rfc2898DeriveBytes(password, salt, 1000))
{
byte[] newKey = deriveBytes.GetBytes(32);
// user is the user object drawn from the database in existence
if (Convert.ToBase64String(newKey).Equals(user.password))
{
FormsAuthentication.RedirectFromLoginPage(Request.Form["username"], false);
}
}
hex generated by C# = 3lRSQF5ImYlQg20CGFy2iGUpWfdP5TD0eq2cTHhLono=
hex generated by JS = w4PDh8K6YMKGwr3DgcObRsOsFFUgDMOJw5PCnkdAwrTCgcOOV8OCKMKFdcKRwrLCqMK2VA==
Salt generated by JS and used at both = /Ij0hgDsvAC1DevM7xkdGUVlozdCxXVd0lgfK2xEh2A=
All the above info is in base64 format
Another thing that might be useful
item.salt = new Buffer(crypto.randomBytes(bytes)).toString('base64'); crypto.pbkdf2(text, salt, iterations, bytes, function(err, derivedKey){
which means the JS function accepts a string
I want the credentials to be universal but despite using Rfc2898DeriveBytes and the salt generated the first time I'm not able to get back to the same hashed password.
The obvious stuff is hash algorithm, salt, and iteration count. Can you confirm (for both languages):
the hash algorithm
the salt
the iteration count
The non-obvious is the encoding of the password and possibly salt. I included the salt because its often stored as a string.
To keep it portable among languages, you should use UTF-8. That's because you could encounter a default encoding, a UTF16-BE, UTF16-LE or any number of other encoding.
In C#, the setup would be:
byte[] utf8_salt = Encoding.UTF8.GetBytes(salt);
byte[] utf8_pass = Encoding.UTF8.GetBytes(password);
You would then pass utf8_salt and utf8_pass to the PBKDF2 function.
I don't know how to do the same in Javascript.
Alright kids daddy has figured out the answer.. took long enough..
Buffer(encodedPassword, 'binary').toString('base64')
on Javascript side will suffice now the tutorial I looked at was clearly not accurate.. the 'binary' was missing.
Thank you all for the help :)
and happy new year

MD5 or other Encryption in Silverlight C#

I'm looking to encrypt a password field for use in a login system, therefore I would like to match encryption to make sure the user has entered the correct details.
For some reason Security.Cryptography doesn't have the MD5 services in Silverlight so I'm left looking for a different method.
I had used this before:
public string Md5Encrypt(string originalPassword)
{
//Declarations
Byte[] originalBytes;
Byte[] encodedBytes;
MD5 md5;
//Instantiate MD5CryptoServiceProvider, get bytes for original password and compute hash (encoded password)
md5 = new MD5CryptoServiceProvider();
originalBytes = ASCIIEncoding.Default.GetBytes(originalPassword);
encodedBytes = md5.ComputeHash(originalBytes);
//Convert encoded bytes back to a 'readable' string
return BitConverter.ToString(encodedBytes);
}
But doesn't work now.
Can anyone give me a simple example for a working encryption method in Silverlight C#
Thanks
You can simply use Using HashLib in silverlight: http://hashlib.codeplex.com/ (look inside the HashLib.HashFactory.HashCryptoNotBuildIn namespace)
Also BouncyCastle.Crypt 1.7 release has a Silverlight 2.0 and above build where most crypto/hashing functions are available: http://www.bouncycastle.org/csharp/
And finally to your rescue, Mono source code is always here to rescue you: https://github.com/mono/mono/blob/master/mcs/class/corlib/System.Security.Cryptography/SHA512Managed.cs which you can copy any cypto code to your project if it targets .NET 2.0 or above.

Error in C# encrypt code when decrypting!

A bit more background info as suggested:
I'm finsihing of an Intranet CMS web app where I have to use the products API (ASP.NET based). Because of time constraints and issues with Windows authen' I need another way to ensure staff do not need to re login everytime they visit the site to view personalised content. The way it works is that once a user logs in (username/password), a Session ID storing a new different Security context value is generated that is used to display the personalised content. The API login method called uses the username and password as parameters. The only way I can think of automatically logging in the next time the staff visits the site is by storing the password in a enrypted cookie and checking of its existing when the site is visited and then calling the API login method using the username and decrypted password cookie values.
Any other ideas as an alternative welcomed.
Mo
Hi,
I'm using some code found on the web to encrypt and decrypt a password string. It encrypts fine but when it calls the code below to decrypt the string it throws the error "Length of the data to decrypt is invalid" How can I resolve this?
Thanks in advance.
Mo
System.Text.Encoding enc = System.Text.Encoding.ASCII;
byte[] myByteArray = enc.GetBytes(_pword);
SymmetricAlgorithm sa = DES.Create();
MemoryStream msDecrypt = new MemoryStream(myByteArray);
CryptoStream csDecrypt = new CryptoStream(msDecrypt, sa.CreateDecryptor(), CryptoStreamMode.Read);
byte[] decryptedTextBytes = new Byte[myByteArray.Length];
csDecrypt.Read(decryptedTextBytes, 0, myByteArray.Length);
csDecrypt.Close();
msDecrypt.Close();
string decryptedTextString = (new UnicodeEncoding()).GetString(decryptedTextBytes);
A couple of things here...
You shouldn't encrypt passwords usually. You should hash them.
If you decide to continue down the road of encryption..
You are using the DES algorithm. This is considered insecure and flawed. I'd recommend looking at the AES algorithm.
Depending on how much data you are working with, the CryptoStream might be overkill.
Using the ASCII encoding can cause loss of data that isn't ASCII, like Cyrillic letters. The recommended fix is to use something else, like UTF8.
Here is an example:
string text = "Hello";
using (var aes = new AesManaged())
{
var bytes = System.Text.Encoding.UTF8.GetBytes(text);
byte[] encryptedBytes;
using (var encrypt = aes.CreateEncryptor())
{
encryptedBytes = encrypt.TransformFinalBlock(bytes, 0, bytes.Length);
}
byte[] decryptedBytes;
using (var decrypt = aes.CreateDecryptor())
{
decryptedBytes = decrypt.TransformFinalBlock(encryptedBytes, 0, encryptedBytes.Length);
}
var decryptedText = System.Text.Encoding.UTF8.GetString(decryptedBytes);
Console.Out.WriteLine("decryptedText = {0}", decryptedText);
}
This will use a random key every time. It is likely that you will need to encrypt some data, then decrypt it at a later time. When you create the AesManaged object, you can store the Key and IV property. You can re-use the same Key if you'd like, but different data should always be encrypted with a different IV (Initialization Vector). Where you store that key, is up to you. That's why hashing might be a better alternative: there is no key, and no need to worry about storing the key safely.
If you want to go down the hashing route, here is a small example:
var textToHash = "hello";
using (SHA1 sha = new SHA1Managed())
{
var bytesToHash = System.Text.Encoding.UTF8.GetBytes(textToHash);
var hash = sha.ComputeHash(bytesToHash);
string base64hash = Convert.ToBase64String(hash);
}
This uses the SHA1 algorithm, which should work fine for passwords, however you may want to consider SHA256.
The concept is simple: a hash will produce a (mostly) unique output for an input, however the output cannot be converted back to the input - it's destructive. Whenever you want to check if a user should be authenticated, check hash the password they gave you, and check it against the hash of the correct password. That way you aren't storing anything sensitive.
I've actually had this error before and it took me 3 days to figure out the solution. The issue will be the fact that the machine key you need for descryption needs to be registered on your machine itself.
Read fully up on DES encryption, it works by an application key, and a machine-level key. The error you're getting is likely because of the machine key missing.
Compare the bytes used to create the _pword string (in the encryption method) to the bytes retrieved with GetBytes. Probably you will notice a change in the data there.
To store the encrypted bytes, I think you should use Convert.ToBase64String and Convert.FromBase64String turn the encrypted password to/from a string.
I also do not see the code where you set the Key and IV. So I guess you are using a different key to encrypt and decrypt the password.
If the current Key property is null,
the GenerateKey method is called to
create a new random Key. If the
current IV property is null, the
GenerateIV method is called to create
a new random IV.
DES is a block based cipher - only certain lengths of buffers are valid. If I remember correctly, the block size for DES is 64 bits, so you need to ensure that your byte array is a multiple of 8 bytes long.
(That should fix your immediate problem, but I'd reference other peoples advice here - you really ought not to be using DES for any new code, and for passwords it's usually more appropriate to hash than to encrypt).

Categories