I want to authenticate user form asp.net web application. data base used for application is MySQL and password stored in db is in encrypted format which is generated from word press application. i need to encrypted password so that i can compare encrypted password with db password.
my password : Push#123
Encrypted password : $P$BGW0cKLlkN6VlZ7OqRUvIY1Uvo/Bh9/
How to generate this Encrypted password in c#
It took me a while, but here you have working almost 1:1 conversion from php to C#:
using System;
using System.Text;
using System.Security.Cryptography;
using System.Linq;
namespace WordpressHash {
public class Program {
private static string itoa64 = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
public static void Main(string[]args) {
string StrPassword = "Push#123";
string expected = "$P$BGW0cKLlkN6VlZ7OqRUvIY1Uvo/Bh9/";
string computed = MD5Encode(StrPassword, expected);
Console.WriteLine(StrPassword);
Console.WriteLine(computed);
Console.WriteLine("Are equal? " + expected.Equals(computed));
}
static string MD5Encode(string password, string hash) {
string output = "*0";
if (hash == null) {
return output;
}
if (hash.StartsWith(output))
output = "*1";
string id = hash.Substring(0, 3);
// We use "$P$", phpBB3 uses "$H$" for the same thing
if (id != "$P$" && id != "$H$")
return output;
// get who many times will generate the hash
int count_log2 = itoa64.IndexOf(hash[3]);
if (count_log2 < 7 || count_log2 > 30)
return output;
int count = 1 << count_log2;
string salt = hash.Substring(4, 8);
if (salt.Length != 8)
return output;
byte[]hashBytes = {};
using(MD5 md5Hash = MD5.Create()) {
hashBytes = md5Hash.ComputeHash(Encoding.ASCII.GetBytes(salt + password));
byte[]passBytes = Encoding.ASCII.GetBytes(password);
do {
hashBytes = md5Hash.ComputeHash(hashBytes.Concat(passBytes).ToArray());
} while (--count > 0);
}
output = hash.Substring(0, 12);
string newHash = Encode64(hashBytes, 16);
return output + newHash;
}
static string Encode64(byte[]input, int count) {
StringBuilder sb = new StringBuilder();
int i = 0;
do {
int value = (int)input[i++];
sb.Append(itoa64[value & 0x3f]); // to uppercase
if (i < count)
value = value | ((int)input[i] << 8);
sb.Append(itoa64[(value >> 6) & 0x3f]);
if (i++ >= count)
break;
if (i < count)
value = value | ((int)input[i] << 16);
sb.Append(itoa64[(value >> 12) & 0x3f]);
if (i++ >= count)
break;
sb.Append(itoa64[(value >> 18) & 0x3f]);
} while (i < count);
return sb.ToString();
}
}
}
Every hash in the database is encoded using salt and n iterations of md5. Brief explanation can be found here: https://codex.wordpress.org/Function_Reference/wp_hash_password
Intentionally I have ommited salt generation. But if you will need it in the future, it should start with $P$ and be at least 12 characters long. Whit this extra method you will be able also to hash new passwords, not only check if hash is correct.
Probably this might do the trick for you
using System.Security.Cryptography;
class Program
{
static void Main(string[] args)
{
string StrPassword = "Push#123";
using (MD5 md5Hash = MD5.Create())
{
string hashPassword = GetMd5Hash(md5Hash, StrPassword);
Console.WriteLine(hashPassword);
}
}
static string GetMd5Hash(MD5 md5Hash, string input)
{
byte[] data = md5Hash.ComputeHash(Encoding.UTF8.GetBytes(input));
StringBuilder sBuilder = new StringBuilder();
for (int i = 0; i < data.Length; i++)
{
sBuilder.Append(data[i].ToString("x2"));
}
return sBuilder.ToString();
}
}
Hash functions map binary strings of an arbitrary length to small binary strings of a fixed length. A cryptographic hash function has the property that it is computationally infeasible to find two distinct inputs that hash to the same value; that is, hashes of two sets of data should match if the corresponding data also matches. Small changes to the data result in large, unpredictable changes in the hash.
The hash size for the MD5 algorithm is 128 bits.
The ComputeHash methods of the MD5 class return the hash as an array of 16 bytes. Note that some MD5 implementations produce a 32-character, hexadecimal-formatted hash. To interoperate with such implementations, format the return value of the ComputeHash methods as a hexadecimal value.
Source MSDN: MD5 Class
I've rewritten crypt_private php method from class-phpass.php (see /wp-includes/class-phpass.php of your wordpress installation) to use it in c#.
Password is user entered string, setting is user_pass value in wp database of wp_users row.
crypt_private return hash of password. So, if crypt_private returned value equals setting value, password is correct.
This works if you're using php5 and newer on server with wordpress.
private const string itoa64 = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
public bool SignIn(string password)
{
string foundUserHash = "hash from database (saved password of a user)";
string hash = Crypt(password, foundUserHash);
return foundUserHash == hash;
}
private string Crypt(string password, string setting)
{
string output = "*0";
if (setting.Substring(0, 2) == output)
output = "*1";
string id = setting.Substring(0, 3);
if (id != "$P$" && id != "$H$")
return output;
int count_log2 = itoa64.IndexOf(setting[3]);
if (count_log2 < 7 || count_log2 > 30)
return output;
var count = 1 << count_log2;
string salt = setting.Substring(4, 8);
if (salt.Length != 8)
return output;
var hash = GetHash(
GetByteArraysAppended(
Encoding.UTF7.GetBytes(salt),
Encoding.UTF7.GetBytes(password)
));
do
{
hash = GetHash(
GetByteArraysAppended(
hash,
Encoding.UTF7.GetBytes(password)
));
}
while (--count!=0);
output = setting.Substring(0, 12);
output += encode64(hash, 16);
return output;
}
private string encode64(byte [] input, int count)
{
string output = "";
int i = 0;
do
{
Int32 value = input[i++];
output += itoa64[value & 0x3f];
if (i < count)
value |= input[i] << 8;
output += itoa64[(value >> 6) & 0x3f];
if (i++ >= count)
break;
if (i < count)
value |= input[i] << 16;
output += itoa64[(value >> 12) & 0x3f];
if (i++ >= count)
break;
output += itoa64[(value >> 18) & 0x3f];
} while (i < count);
return output;
}
private byte[] GetByteArraysAppended(byte[] partOne, byte[] partTwo)
{
var parts = partOne.ToList();
parts.AddRange(partTwo);
var result = parts.ToArray();
return result;
}
private byte[] GetHash(byte [] bytesToHash)
{
MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider();
var hash = md5.ComputeHash(bytesToHash);
return hash;
}
I'm a PHP developer and a little out of my element in C#. In PHP, there's a crc32() function which returns a signed integer for any string that you pass in.
So this is what I'm used to:
<?php
echo crc32("test");
// displays -662733300
I would like to do the same thing in C#. I came across this C# class library but understand little about it. According to his instructions, I'm supposed to do this:
// first convert string to byte-array
String input = "test";
byte[] bytes = new byte[input.length * sizeof(char)];
System.Buffer.BlockCopy(input.ToCharArray(), 0, bytes, 0, bytes.Length);
// then calculate the value
Crc32 crc32 = new Crc32();
String output = "";
foreach (byte b in crc32.ComputeHash(bytes))
{
output += b.ToString("x2").ToLower();
}
That gives me an output string of 27d86d6a. What do I need to do instead to return a signed integer? (Which in this example should equal -662733300)
Try use BitConverter.ToInt32 method:
var crcVal = BitConverter.ToInt32(crc32.ComputeHash(bytes), 0);
EDIT
It's seems you use different Crc32 algorithm implementation, try the following one:
using System;
using System.Collections.Generic;
using System.Security.Cryptography;
public class Program
{
public void Main()
{
// first convert string to byte-array
String input = "test";
byte[] bytes = new byte[input.Length * sizeof(char)];
System.Buffer.BlockCopy(input.ToCharArray(), 0, bytes, 0, bytes.Length);
// then calculate the value
var crcVal = crc32(input);
Console.WriteLine((int)crcVal);
}
public uint crc32(string input) {
var table = new uint[]{
0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F,
0xE963A535, 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988,
0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2,
0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9,
0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172,
0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C,
0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423,
0xCFBA9599, 0xB8BDA50F, 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924,
0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, 0x76DC4190, 0x01DB7106,
0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D,
0x91646C97, 0xE6635C01, 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,
0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950,
0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7,
0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0,
0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C, 0x270241AA,
0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81,
0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A,
0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, 0xE3630B12, 0x94643B84,
0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB,
0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC,
0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8, 0xA1D1937E,
0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55,
0x316E8EEF, 0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236,
0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 0xC5BA3BBE, 0xB2BD0B28,
0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F,
0x72076785, 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38,
0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242,
0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69,
0x616BFFD3, 0x166CCF45, 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2,
0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC,
0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693,
0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
};
unchecked
{
uint crc = (uint)(((uint)0) ^ (-1));
var len = input.Length;
for (var i=0; i < len; i++) {
crc = (crc >> 8) ^ table[
(crc ^ (byte)input[i]) & 0xFF
];
}
crc = (uint)(crc ^ (-1));
if (crc < 0) {
crc += (uint)4294967296;
}
return crc;
}
}
}
Demo
this is my code in C# :
public static String MD5Encrypt(String str, Boolean raw_output=false)
{
// Use input string to calculate MD5 hash
String output;
MD5 md5 = System.Security.Cryptography.MD5.Create();
byte[] inputBytes = System.Text.Encoding.ASCII.GetBytes(str);
byte[] hashBytes = md5.ComputeHash(inputBytes);
// Convert the byte array to hexadecimal string
StringBuilder sb = new StringBuilder();
for (int i = 0; i < hashBytes.Length; i++)
{
sb.Append(hashBytes[i].ToString("x2"));
}
output = sb.ToString();
if (raw_output)
{
output = pack(output);
}
return output;
}
public static String pack(String S)
{
string MultiByte = "";
for (int i = 0; i <= S.Length - 1; i += 2)
{
MultiByte += Convert.ToChar(HexToDec(S.Substring(i, 2)));
}
return MultiByte;
}
private static int HexToDec(String hex)
{
//Int32.Parse(hexString, System.Globalization.NumberStyles.HexNumber);
return Convert.ToInt32(hex, 16);
}
To reproduce what is done in php by this way :
md5($str, true);
OR
pack('H*', md5( $str ));
I tried many things but can't get the same on the two sides in some cases of word.
For example, Trying this test on the string "8tv7er5j"
PHP Side :
9c36ad446f83ca38619e12d9e1b3c39e <= md5("8tv7er5j");
œ6DoƒÊ8ažÙá³Ãž <= md5("8tv7er5j", true) or pack("H*", md5("8tv7er5j"))
C# Side :
9c36ad446f83ca38619e12d9e1b3c39e <= MD5Encrypt("8tv7er5j")
6DoÊ8aÙá³Ã <= MD5Encrypt("8tv7er5j", true) or pack( MD5Encrypt("8tv7er5j") )
Why ? Encoding problem ?
EDIT 1 :
I have the good result, but bad encoded with this this function for pack() :
if ((hex.Length % 2) == 1) hex += '0';
byte[] bytes = new byte[hex.Length / 2];
for (int i = 0; i < hex.Length; i += 2)
{
bytes[i / 2] = Convert.ToByte(hex.Substring(i, 2), 16);
}
return bytes;
So, System.Text.Encoding.UTF8.GetString(bytes) give me :
�6�Do��8a���Þ
And System.Text.Encoding.ASCII.GetString(bytes)
?6?Do??8a??????
...
I encountered same scenario where I am in need of php's pack-unpack-md5 functions in C#. Most important was that I need to match out of all these 3 functions with php.
I created my own functions and then validated(verified) my output with functions at onlinephpfunctions.com. The output was same when I parsed with DefaultEncoding. FYI, I checked my application's encoding(Encoding.Default.ToString()) and it was System.Text.SBCSCodePageEncoding
Pack
private static string pack(string input)
{
//only for H32 & H*
return Encoding.Default.GetString(FromHex(input));
}
public static byte[] FromHex(string hex)
{
hex = hex.Replace("-", "");
byte[] raw = new byte[hex.Length / 2];
for (int i = 0; i < raw.Length; i++)
{
raw[i] = Convert.ToByte(hex.Substring(i * 2, 2), 16);
}
return raw;
}
MD5
private static string md5(string input)
{
byte[] asciiBytes = Encoding.Default.GetBytes(input);
byte[] hashedBytes = MD5CryptoServiceProvider.Create().ComputeHash(asciiBytes);
string hashedString = BitConverter.ToString(hashedBytes).Replace("-", "").ToLower();
return hashedString;
}
Unpack
private static string unpack(string p1, string input)
{
StringBuilder output = new StringBuilder();
for (int i = 0; i < input.Length; i++)
{
string a = Convert.ToInt32(input[i]).ToString("X");
output.Append(a);
}
return output.ToString();
}
PS: User can enhance these functions with other formats
I guess that PHP defaults to Latin1 so the code should look like :
public static String PhpMd5Raw(string str)
{
var md5 = System.Security.Cryptography.MD5.Create();
var inputBytes = System.Text.Encoding.ASCII.GetBytes(str);
var hashBytes = md5.ComputeHash(inputBytes);
var latin1Encoding = System.Text.Encoding.GetEncoding("ISO-8859-1");
return latin1Encoding.GetString(hashBytes);
}
If you are going to feed the result as a key for HMAC-SHA1 hashing keep it as bytes[] and initialize the HMACSHA1 with the return value of this function: DO NOT convert it to a string and back to bytes, I have spent hours because of this mistake.
public static byte[] PackH(string hex)
{
if ((hex.Length % 2) == 1) hex += '0';
byte[] bytes = new byte[hex.Length / 2];
for (int i = 0; i < hex.Length; i += 2)
{
bytes[i / 2] = Convert.ToByte(hex.Substring(i, 2), 16);
}
return bytes;
}
I know this is an old question. I am posting my answer for anyone who might reach this page searching for it.
The following code is the full conversion of the pearl function pack("H*") to c#.
public static String Pack(String input)
{
input = input.Replace("-", " ");
byte[] hashBytes = new byte[input.Length / 2];
for (int i = 0; i < hashBytes.Length; i++)
{
hashBytes[i] = Convert.ToByte(input.Substring(i * 2, 2), 16);
}
return Encoding.UTF7.GetString(hashBytes); // for perl/php
}
I'm sorry. I didn't go with the questions completely. But if php code is as below,
$testpack = pack("H*" , "you value");
and if can't read the $testpack values(due to some non support format), then first do base64_encode as below and echo it.
echo base64_encode($testpack);
Then use Risky Pathak answer. For complete this answer I'll post his answer with some small modification like base 64 encoding etc.
var hex = "you value";
hex = hex.Replace("-", "");
byte[] raw = new byte[hex.Length / 2];
for (int i = 0; i < raw.Length; i++)
{
raw[i] = Convert.ToByte(hex.Substring(i * 2, 2), 16);
}
var res = Convert.ToBase64String(raw);
Console.WriteLine(res);
Now if you compare both of values, those should be similar.
And all credit should go to the Risky Pathak answer.
The same in c# can be reached with Hex.Decode() method.
And bin2hex() in php is Hex.Encode().