Hashing password algorith issue - c#

I am new in C# wpf programming but I am trying to connect to MySQL database and to hash my password. Unfortunately while I was implementing the algorith I get error in this code:
byte[] plainTextWithSaltBytes = new byte[plainTextBytes.Length + saltBytes.Length];
salt.CopyTo(plainTextWithSaltBytes, 0);
plainText.CopyTo(plainTextWithSaltBytes, salt.Length);
The error is:
Error: no overload for method 'Copy To' takes 2 arguments Exceptions: System.ArgumentNullException System.ArgumentOutOfRangeException
enter code here
By any chance do you know what is causing this errors and how to fix it?

You need to copy plainTextBytes, not plainText:
byte[] plainTextWithSaltBytes = new byte[plainTextBytes.Length + saltBytes.Length];
salt.CopyTo(plainTextWithSaltBytes, 0);
plainTextBytes.CopyTo(plainTextWithSaltBytes, salt.Length);

If you need to do simple hash, this bit of code may encrypt your password:
String GetEncryptedPassword (String prmUser, String prmPassword)
{
// Concatenating the password and user name.
String encryptedPassword = prmUserName + prmPassword;
// Converting into the stream of bytes.
Byte[] passInBytes = Encoding.UTF8.GetBytes(encryptedPassword);
// Encrypting using SHA1 encryption algorithm.
passInBytes = SHA1.Create().ComputeHash(passInBytes);
// Formatting every byte into %03d to make a fixed length 60 string.
return passInBytes.Aggregate(String.Empty, (pass, iter) => pass += String.Format("{0:000}", iter));
}
This code will give you a nice encrypted hash of 60 characters. But remember that you can't regenerate your original username and password from the hash, because this is a one way algorithm. There are few more encryption algorithms in System.Security.Cryptography that you can use.

Related

Trouble matching SHA512 hash from PHP with C# counterpart formula

This should be so simple but I've spent 4 hours fiddling with this code and I just can't seem to get it to work.
The PHP code works as follows (I didn't write it and I can't change it, so I'm stuck with it):
$password = hash('sha512', "HelloWorld1");
$salt = hash('sha512', uniqid(mt_rand(1, mt_getrandmax()), true);
$hashed = hash('sha512', $password.$salt);
$hashed and $salt are stored in the DB as is. That means $salt is already hashed for later on.
I have no idea why they decided to hash everything but what's done is done.
In this case, the result is
Pswd: ab3e648d69a71b33d0420fc3bfc9e2e8e3ef2a300385ea26bc22057a84cd9a5c359bd15c4a0a552122309e58938ce310839cd9d2ecad5f294266015d823331dd
Salt: fb5a0f741db0be2439dc14662aae3fc68eb5e16b446385d3ddd319b862d5e2d4f50488a39487b27fdd8ff7b7b76420fc3ebef2bce9e082ac15c9f2d6fe7d87fc
Now the login code on the C# side just needs to match a plain text hashed password along with the already hashed salt.
string password = "HelloWorld1";
string storedSalt = "fb5a0f741db0be2439dc14662aae3fc68eb5e16b446385d3ddd319b862d5e2d4f50488a39487b27fdd8ff7b7b76420fc3ebef2bce9e082ac15c9f2d6fe7d87fc";
using(SHA512 shaManaged = new SHA512Managed())
{
byte[] hashPassword = shaManaged.ComputeHash(Encoding.UTF8.GetBytes(password));
string hashPasswordString = BitConverter.ToString(hashPassword).Replace("-", "");
byte[] finalHash = shaManaged.ComputeHash(Encoding.UTF8.GetBytes(hashPasswordString + storedSalt));
Debug.WriteLine("Calculated Hash Password: " + BitConverter.ToString(finalHash).Replace("-", ""));
}
Essentially the idea is to
Hash the plain text password first (same as with the PHP code).
Convert the byte array to a string that matches the PHP format of hashing.
Then hash the hashed password and previously hashed salt together.
The result is as follows:
Stored Hash Password: AB3E648D69A71B33D0420FC3BFC9E2E8E3EF2A300385EA26BC22057A84CD9A5C359BD15C4A0A552122309E58938CE310839CD9D2ECAD5F294266015D823331DD
Calculated Hash Password: 189ABBA71AAEDDE5C8154558B68D59500A72E64D5F3F3C07EFA94F0126571FBB68C6ADD105E0C029BABF30CADD8A6A6B6E4749075854461A88EE1CE545E84507
Hopefully someone can spot where I'm going wrong :)
You have to tweak your code a little bit. Note the ToLowerInvariant(). C# returns upper case letters as string. As you see in your original code $salt and $password are returned with lower case letters, so your self calculated password hash hashPasswordString must also be lower case before concatenating with your storedSalt to gain the correct finalHash. Your shown expected result again uses upper case letters (maybe before stored it was converted in PHP?) so you don't need ToLowerCaseInvariant() on your final hash string.
Here is the code:
string password = "HelloWorld1";
string storedSalt = "fb5a0f741db0be2439dc14662aae3fc68eb5e16b446385d3ddd319b862d5e2d4f50488a39487b27fdd8ff7b7b76420fc3ebef2bce9e082ac15c9f2d6fe7d87fc";
using (SHA512 shaManaged = new SHA512Managed())
{
byte[] hashPassword = shaManaged.ComputeHash(Encoding.UTF8.GetBytes(password));
string hashPasswordString = BitConverter.ToString(hashPassword).Replace("-", "").ToLowerInvariant(); // Note the ToLowerInvariant();
byte[] finalHash = shaManaged.ComputeHash(Encoding.UTF8.GetBytes(hashPasswordString + storedSalt));
return BitConverter.ToString(finalHash).Replace("-", "");
}

Blowfish ECB encryption in C# implementation

I have a client who needs us to use Blowfish ECB encryption with cipherMode 0, output 1. I have tried to solve for this, but I'm getting stuck. How do I fix my code?
Here are the full client instructions:
Algorithm: Blowfish
・ Mode: ECB
・ Padding: PKCS5Padding
*Initial vector is unnecessary because we use ECB mode.
Example
・Encrypt Key: 2fs5uhnjcnpxcpg9
 → Plain Text : 3280:99:20120201123050
 → Cipher Text : daa745f1901364c0bd42b9658db3db96336758cd34b2a576
* Please keep Cipher Text with 16 hexadecimal characters .
* Please generate Cipher Text without “salt”.
I need to write this in C#. Here's what I did, but it doesn't seem to be working:
string member_id = "3280";
string panelType = "99";
string RandomString = "20120201123050";
string encryptionKey = "2fs5uhnjcnpxcpg9";
string cryptstr = member_id + ":" + panelType + ":" + RandomString;
string plainText = cryptstr;
BlowFish b = new BlowFish(encryptionKey);
string cipherText = b.Encrypt_ECB("3280:99:20120201123050");
The result is not daa745f1901364c0bd42b9658db3db96336758cd34b2a576. Where did I go wrong?
Encrypt_ECB() so I assume its Schneier's class.
The ctor expects a hexadecimal string if one is passed, you need the overload for a byte array:
BlowFish b = new BlowFish(Encoding.UTF8.GetBytes(encryptionKey));
The output is still not correct, lets see what it really should be by decrypting their example:
string clear = b.Decrypt_ECB("daa745f1901364c0bd42b9658db3db96336758cd34b2a576");
gives us:
"3280:99:20120201123050\u0002\u0002"
Which is good but there are 2 0x2 bytes on the end, the N x 0xN is due to the PKCS padding. To get the match you need to pad the input:
// input to bytes
List<byte> clearBytes = new List<byte>(Encoding.UTF8.GetBytes("3280:99:20120201123050"));
// how many padding bytes?
int needPaddingBytes = 8 - (clearBytes.Count % 8);
// add them
clearBytes.AddRange(Enumerable.Repeat((byte)needPaddingBytes, needPaddingBytes));
// encrypt
byte[] cipherText = b.Encrypt_ECB(clearBytes.ToArray());
// to hex
string cipherTextHex = BitConverter.ToString(cipherText).Replace("-", "").ToLowerInvariant();

HMAC SHA256 decrypt string in C#

How can I decrypt HMAC SHA256 encrypted string?
private string CreateToken(string message, string secret)
{
secret = secret ?? "";
var encoding = new System.Text.ASCIIEncoding();
byte[] keyByte = encoding.GetBytes(secret);
byte[] messageBytes = encoding.GetBytes(message);
using (var hmacsha256 = new HMACSHA256(keyByte))
{
byte[] hashmessage = hmacsha256.ComputeHash(messageBytes);
return Convert.ToBase64String(hashmessage);
}
}
How can I do reverse engineering if I have resultant string?
Thanks in advance.
A hash is a one-way function, by definition it is not reversible. What is it that you are trying to achieve?
If it's for something like password comparison then just hash the password you have and then compare the resulting hashes. Without any further context it's hard what to suggest.
HMACSHA256: It is a hash based Message authentication code.It is used to verify the message integrity on the insecure channel.It is a forward only hash algorithm, it can not be decrypted. It hashes the message based on the shared secret key which is known by both parties(sender and receiver).Sender uses the shared secret and compute the hash value from original data and send both the original data and hash value and then receiver re-computes the hash value from the original data. If both hash value matches it means no tempered in original data, if not matched it means tempered in original data for this scenario validation is failed.

Decrypting AES in SQL Anywhere 16 encrypted in C# and vise versa

I have this peace of code that encrypts stuff using AES, to be more precise Rijndael algorithm to mimic (http://dcx.sybase.com/index.html#sa160/en/dbreference/encrypt-function.html) the behaviour of SQL Anywhere 16, for sake of examples simplicity keys are fake:
var Key = Encoding.ASCII.GetBytes("1234567812345678");
var IV = Encoding.ASCII.GetBytes("1234567812345678");
var text = "stuff";
string encrypted;
var aes = new RijndaelManaged { Mode = CipherMode.CBC, Padding = PaddingMode.PKCS7, BlockSize = 128, KeySize = 128, Key = Key, IV = IV };
using (var encryptor = aes.CreateEncryptor())
{
var tmp = Encoding.ASCII.GetBytes(text);
encrypted = Convert.ToBase64String(encryptor.TransformFinalBlock(tmp, 0, tmp.Length));
}
Console.WriteLine("Encrypted text: " + encrypted);
And the result I get: do3BgGEeCWS5+mruUU1Czg== nXnrIX9m4zCxupbPsw3zsg==
Decrypting it in SQL Anywhere 16:
select cast(decrypt(base64_decode('do3BgGEeCWS5+mruUU1Czg=='), '1234567812345678', 'AES(format=RAW;padding=PKCS5)', '1234567812345678') as varchar)
I get this result: s t u f f stuff
So it almost works, comparing in hex it is 0x73007400750066006600 instead of 0x7374756666. Furthermore, if I decrypt same text in C# (decryptor source can be found bellow), I also get same spaces, what am I doing wrong?
Also I tried it other way around, encrypted in SQL Anywhere:
select base64_encode(encrypt('stuff', '1234567812345678', 'AES(format=RAW;padding=PKCS5)', '1234567812345678'))
Got this line: nXnrIX9m4zCxupbPsw3zsg==
Trying to decrypt in C# using same procedure:
string decrypted;
using (var decryptor = aes.CreateDecryptor())
{
var tmp = System.Convert.FromBase64String(encrypted);
decrypted = Encoding.ASCII.GetString(decryptor.TransformFinalBlock(tmp, 0, tmp.Length));
};
Console.WriteLine("Decrypted text: " + decrypted);
I get the correct result: stuff with no unnecessary spaces in it.
So it works with a mirror drawback, any ideas where from are those the extra spaces?
Update: Error was in var tmp = Encoding.Unicode.GetBytes(text); line, changed Unicode to ASCII.
If you are using SQL Anywhere version 16.0 or later, you can do this using the 'format=raw' option of the decrypt function. If you are using a version earlier than that, the decrypt function will not be able to decrypt data encrypted outside the database server.
Update: Since you updated your question, I'll address that too. I ran through the decryption in the SQL Anywhere server, and the data that comes out has the embedded NULLs in it, which means that the data that's encrypted already contains the embedded NULLs. I'm not a C# guy so I can't tell you for sure, but I suspect that var text = "stuff"; stores the data in UTF-16.
Full disclosure: I work for SAP in SQL Anywhere engineering.

UTF8 encoded password Byte[] with SHA512 encryption to string conversion

I have created a web form in c# that accepts username and password and stores password in MSSQL 2005 db in 'image' format. The password is merged with salt, encoded in UTF8 and lastly it is applied with a SHA512 encryption. I want to be able to see the passwords in string format when I pull them up back from the database. How should my decrypt function be, if the following is how I encrypted the password? Is that possible? :
string loginID = "";//This will be stored in varchar format in MSSQL..(Unrelated to the question)
string password =""; //This is where I store password inputted by user.
Random r = new Random();
int salt = r.Next((int)Math.Pow(2, 16));
int verifyCode = r.Next((int)Math.Pow(2, 16));
string tmpPwd = password.ToLower() + salt.ToString();
UTF8Encoding textConverter = new UTF8Encoding();
byte[] passBytes = textConverter.GetBytes(tmpPwd);
byte[] hashedPWD = new SHA512Managed().ComputeHash(passBytes);
The value in hashedPWD is stored in MSSQL as image datatype and salt is stored as int.
You can't - that's what a hash function is, by definition - a one-way function. Up until the last line, you can get the password back, but after the hash function, all you can do is generate a second hash and compare the two to see if they've produced the same result, in which case you can presume that the source strings were the same.

Categories

Resources