Match C# MD5 hashing algorithm with node.js - c#

I am having trouble matching a C# hashing algorithm with node, the problem seems to be the Unicode encoding. Is there a way to convert a string to Unicode then hash it and output it as hexadecimal? Unfortunately I cannot change the c# code, it is out of my control.
node algorithm
function createMd5(message) {
var crypto = require("crypto");
var md5 = crypto.createHash("md5");
return md5.update(message).digest('hex');
}
c# hashing algorithm
private static string GetMD5(string text)
{
UnicodeEncoding UE = new UnicodeEncoding();
byte[] hashValue;
byte[] message = UE.GetBytes(text);
using (MD5 hasher = new MD5CryptoServiceProvider())
{
string hex = "";
hashValue = hasher.ComputeHash(message);
foreach (byte x in hashValue)
{
hex += String.Format("{0:x2}", x);
}
return hex.ToLower();
}
}

Your suspicion of this being an encoding problem is correct. You can fix your node code with the following alteration, which will convert your message string into utf-16 (which is what .NET's default encoding is):
function createMd5(message) {
var crypto = require("crypto");
var md5 = crypto.createHash("md5");
return md5.update(new Buffer(message, 'ucs-2')).digest('hex');
}

Related

C# - Convert String with Public Key (mod) and Exponent RSA PKCS#1.5

I have a publickey that is:
a383a2916281721498ff28226f851613bab6f89eb0536e9f237e158596d3b012e5707eba9f2a2963faca63fcb10f5de79caf246c1f587ee6e8f895fd848f2da5aba9d71af4dd8d06e99ff3729631626ed3f3202e56962957c0110a99d2b3893feb148291e09b54fe7df121751fb8bb589576542321b4f548be06b9845ebc6bbef1427741c00b632c05854146b597fdef5a89ace1556a769c5eaff8fc0589e7ad4adb2e2a929969c77f395b2f5a276a9389d1f43c061c9459a65b77bcd581c107aa8424223a0b44ee52582362cc96b90eea071a0dda5e9cb8fd5c9fd4ac86e177c07d79071788cb08231240dc1c9169af2629ecec31751069f0c7ccc1c1752303
(Not Base64)
and an exponent thats:
010001
(Again not base64)
and I need to convert this along with a small string to RSA PKCS#1.5
But im a bit confused, it keeps giving me errors when trying to do it
apparently the exponent is formatted wrong and the public key isnt base64?
Heres my code
string publicKey = "a383a2916281721498ff28226f851613bab6f89eb0536e9f237e158596d3b012e5707eba9f2a2963faca63fcb10f5de79caf246c1f587ee6e8f895fd848f2da5aba9d71af4dd8d06e99ff3729631626ed3f3202e56962957c0110a99d2b3893feb148291e09b54fe7df121751fb8bb589576542321b4f548be06b9845ebc6bbef1427741c00b632c05854146b597fdef5a89ace1556a769c5eaff8fc0589e7ad4adb2e2a929969c77f395b2f5a276a9389d1f43c061c9459a65b77bcd581c107aa8424223a0b44ee52582362cc96b90eea071a0dda5e9cb8fd5c9fd4ac86e177c07d79071788cb08231240dc1c9169af2629ecec31751069f0c7ccc1c1752303";
string exponant = "010001";
string toEncrypt = "Test123";
using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider())
{
RSAParameters rsap = new RSAParameters {
Modulus = Encoding.UTF8.GetBytes(Convert.ToBase64String(Encoding.UTF8.GetBytes(publicKey))),
Exponent = Encoding.UTF8.GetBytes(Convert.ToBase64String(Encoding.UTF8.GetBytes(exponant)))
};
//Tried with and without the whole base64 thing
rsa.ImportParameters(rsap);
byte[] encryptedData = rsa.Encrypt(Encoding.UTF8.GetBytes(toEncrypt), false);
string base64Encrypted = Convert.ToBase64String(encryptedData);
x = x.Replace(match, text.Contains("(URLENCODE)") ? WebUtility.UrlEncode(base64Encrypted) : base64Encrypted);
}
CryptographicException: Bad Data.
Occuring On: rsa.ImportParameters(rsap);
I do have the finished result:
PV7v6F8AOJvIJA6yYJReUf3jRD8HL5LzNIIqs4ehKlwxt00xyvnCCy/MiSX/4ZP6+IZfXPGAs57kM2/KsUau+fgU4p0rxJM569MLZ+RFjBnI/ATE1Ru5v8D2ZcJ89Y0Z3xowVnNMaytwacRf/LZqxIAFpBr/E5G6KSHkSg+3zQIu6RrxbHPrWeiYYUWB5XfYDKlPcezW3QYi9lktGCp2Eqsg+ULX1GD6qIlHySslYlT3kqVZbQb1B5ak416Rq1RMLhUgpsBazuB50jr5I1zfrFdi4UeNlkBWxFcJaGOY8HScCKwvlGU7TqGbjucB1rA3mQhGvSTUmfDeGBnGrLwCdA==
(Got this from using the same data in a non c# non open-source application).
The public key string you have looks like the hexadecimal representation of a byte array to me. Therefore, I tested to convert it to a byte[] using the following conversion:
public static byte[] HexStringToByteArray(string hexString)
{
MemoryStream stream = new MemoryStream(hexString.Length / 2);
for (int i = 0; i < hexString.Length; i += 2)
{
stream.WriteByte(byte.Parse(hexString.Substring(i, 2), System.Globalization.NumberStyles.AllowHexSpecifier));
}
return stream.ToArray();
}
Also, the exponent probably has the same format (3 bytes, 0x01 0x00 0x01), therefore I am using the same approach to convert it to a byte[]
At the end, the code looks like:
string publicKey = "a383a2916281721498ff28226f851613bab6f89eb0536e9f237e158596d3b012e5707eba9f2a2963faca63fcb10f5de79caf246c1f587ee6e8f895fd848f2da5aba9d71af4dd8d06e99ff3729631626ed3f3202e56962957c0110a99d2b3893feb148291e09b54fe7df121751fb8bb589576542321b4f548be06b9845ebc6bbef1427741c00b632c05854146b597fdef5a89ace1556a769c5eaff8fc0589e7ad4adb2e2a929969c77f395b2f5a276a9389d1f43c061c9459a65b77bcd581c107aa8424223a0b44ee52582362cc96b90eea071a0dda5e9cb8fd5c9fd4ac86e177c07d79071788cb08231240dc1c9169af2629ecec31751069f0c7ccc1c1752303";
string exponant = "010001";
string toEncrypt = "Test123";
using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider())
{
RSAParameters rsap = new RSAParameters
{
Modulus = HexStringToByteArray(publicKey),
Exponent = HexStringToByteArray(exponant)
};
//Tried with and without the whole base64 thing
rsa.ImportParameters(rsap);
byte[] encryptedData = rsa.Encrypt(Encoding.UTF8.GetBytes(toEncrypt), false);
string base64Encrypted = Convert.ToBase64String(encryptedData);
The import of the RSA parameters is successful, and the encryption too.
The output looks like the following. It does not have to be the same as yours (which you produced by using a non C#, non open source application, by the way with which I sensed some kind of reproach) because there are other factors like padding which affects the result, but the encryption is successful.
VXg8wRZz7SDnhg3T1GPs8CztjPsGwES+ngJAaBBVMSNkBiBOU+ju70pI5sAjvFS34+ztY8VLUZZ4vzf9
NkBNCgEn7Q2NezOwgP029yHY169Jc7Kqkwy0UbJLAwCwmqR+/G6B/S2hL2ADV+5EeaEn4ZmmKl/WRp+P
ruwWKDQx46/ih0itvh7uF5/OfKCqeIrcsqpZgQ4pByNQNOTs1sFlKB+/8TZ6Ey00lYU8c3bRLOef0Nh+
uivY0LI2ryOYI//EtmoZqfkeJH2ZqOQPy/I4R/OXHs1RcEZpnam8/OF1c/DlGVp3//RO8owmStxSj/eF
TD5arc3a1kiNma+/DDQYuQ==

hashing "SHA256" with two parameters

I must convert a JAVA function that Hashing a string.
this is a function:
private static String hmacSha256(String value, String key) throws NoSuchAlgorithmException, InvalidKeyException {
byte[] keyBytes = key.getBytes();
SecretKeySpec signingKey = new SecretKeySpec(keyBytes, "HmacSHA256");
Mac mac = Mac.getInstance("HmacSHA256");
mac.init(signingKey);
byte[] rawHmac = mac.doFinal(value.getBytes());
return String.format("%0" + (rawHmac.length << 1) + "x", new BigInteger(1, rawHmac));
}
My doubt is: this function take 2 parameters:
String value: It is the string to crypt
String Key: It is another key
I already used the Sha256, but I always use it with only one parameter (one string to encrypt)
please, how can I wrote this function in c# or is there anyone who can explain to me the logical?
thank you
You can use HMACSHA256 class to make it work:
private static string ComputeHash(string key, string value)
{
var byteKey = Encoding.UTF8.GetBytes(key);
string hashString;
using (var hmac = new HMACSHA256(byteKey))
{
var hash = hmac.ComputeHash(Encoding.UTF8.GetBytes(value));
hashString = Convert.ToBase64String(hash);
}
return hashString;
}
This is not plain SHA256, this is HMACSHA256 and there is allready a class in .Net.
HMACSHA256

How can I SHA512 a string in C#?

I am trying to write a function to take a string and sha512 it like so?
public string SHA512(string input)
{
string hash;
~magic~
return hash;
}
What should the magic be?
Your code is correct, but you should dispose of the SHA512Managed instance:
using (SHA512 shaM = new SHA512Managed())
{
hash = shaM.ComputeHash(data);
}
512 bits are 64 bytes.
To convert a string to a byte array, you need to specify an encoding. UTF8 is okay if you want to create a hash code:
var data = Encoding.UTF8.GetBytes("text");
using (...
This is from one of my projects:
public static string SHA512(string input)
{
var bytes = System.Text.Encoding.UTF8.GetBytes(input);
using (var hash = System.Security.Cryptography.SHA512.Create())
{
var hashedInputBytes = hash.ComputeHash(bytes);
// Convert to text
// StringBuilder Capacity is 128, because 512 bits / 8 bits in byte * 2 symbols for byte
var hashedInputStringBuilder = new System.Text.StringBuilder(128);
foreach (var b in hashedInputBytes)
hashedInputStringBuilder.Append(b.ToString("X2"));
return hashedInputStringBuilder.ToString();
}
}
Please, note:
SHA512 object is disposed ('using' section), so we do not have any resource leaks.
StringBuilder is used for efficient hex string building.
512/8 = 64, so 64 is indeed the correct size. Perhaps you want to convert it to hexadecimal after the SHA512 algorithm.
See also: How do you convert Byte Array to Hexadecimal String, and vice versa?
You might try these lines:
public static string GenSHA512(string s, bool l = false)
{
string r = "";
try
{
byte[] d = Encoding.UTF8.GetBytes(s);
using (SHA512 a = new SHA512Managed())
{
byte[] h = a.ComputeHash(d);
r = BitConverter.ToString(h).Replace("-", "");
}
r = (l ? r.ToLowerInvariant() : r);
}
catch
{
}
return r;
}
It is disposed at the end
It's safe
Supports lower case
Instead of WinCrypt-API using System.Security.Cryptography, you can also use BouncyCastle:
public static byte[] SHA512(string text)
{
byte[] bytes = System.Text.Encoding.UTF8.GetBytes(text);
Org.BouncyCastle.Crypto.Digests.Sha512Digest digester = new Org.BouncyCastle.Crypto.Digests.Sha512Digest();
byte[] retValue = new byte[digester.GetDigestSize()];
digester.BlockUpdate(bytes, 0, bytes.Length);
digester.DoFinal(retValue, 0);
return retValue;
}
If you need the HMAC-version (to add authentication to the hash)
public static byte[] HmacSha512(string text, string key)
{
byte[] bytes = Encoding.UTF8.GetBytes(text);
var hmac = new Org.BouncyCastle.Crypto.Macs.HMac(new Org.BouncyCastle.Crypto.Digests.Sha512Digest());
hmac.Init(new Org.BouncyCastle.Crypto.Parameters.KeyParameter(System.Text.Encoding.UTF8.GetBytes(key)));
byte[] result = new byte[hmac.GetMacSize()];
hmac.BlockUpdate(bytes, 0, bytes.Length);
hmac.DoFinal(result, 0);
return result;
}
Keeping it simple:
using (SHA512 sha512 = new SHA512Managed())
{
password = Encoding.UTF8.GetString(sha512.ComputeHash(Encoding.UTF8.GetBytes(password)));
}
I'm not sure why you are expecting 128.
8 bits in a byte. 64 bytes. 8 * 64 = 512 bit hash.
From the MSDN Documentation:
The hash size for the SHA512Managed algorithm is 512 bits.
You could use the System.Security.Cryptography.SHA512 class
MSDN on SHA512
Here is an example, straigt from the MSDN
byte[] data = new byte[DATA_SIZE];
byte[] result;
SHA512 shaM = new SHA512Managed();
result = shaM.ComputeHash(data);
UnicodeEncoding UE = new UnicodeEncoding();
byte[] message = UE.GetBytes(password);
SHA512Managed hashString = new SHA512Managed();
string hexNumber = "";
byte[] hashValue = hashString.ComputeHash(message);
foreach (byte x in hashValue)
{
hexNumber += String.Format("{0:x2}", x);
}
string hashData = hexNumber;
I used the following
public static string ToSha512(this string inputString)
{
if (string.IsNullOrWhiteSpace(inputString)) return string.Empty;
using (SHA512 shaM = new SHA512Managed())
{
return Convert.ToBase64String(shaM.ComputeHash(Encoding.UTF8.GetBytes(inputString)));
}
}
Made it into an extension method in my ExtensionUtility.cs class
public static string SHA512(this string plainText)
{
using (SHA512 shaM = new SHA512Managed())
{
var buffer = Encoding.UTF8.GetBytes(plainText);
var hashedInputBytes = shaM.ComputeHash(buffer);
return BitConverter.ToString(hashedInputBytes).Replace("-", "");
}
}

md5 hash confusion

My company uses the following algorithm to hash passwords before store it in the database:
public static string Hash(string value)
{
byte[] valueBytes = new byte[value.Length * 2];
Encoder encoder = Encoding.Unicode.GetEncoder();
encoder.GetBytes(value.ToCharArray(), 0, value.Length, valueBytes, 0, true);
MD5 md5 = new MD5CryptoServiceProvider();
byte[] hashBytes = md5.ComputeHash(valueBytes);
StringBuilder stringBuilder = new StringBuilder();
for (int i = 0; i < hashBytes.Length; i++)
{
stringBuilder.Append(hashBytes[i].ToString("x2"));
}
return stringBuilder.ToString();
}
To me it sounds like a trivial md5 hash, but when I tried to match a password (123456) the algorithm gives me ce0bfd15059b68d67688884d7a3d3e8c, and when I use a standard md5 hash it gives me e10adc3949ba59abbe56e057f20f883e.
A iOS version of the site is being build, and the users needs to login, the password will be hashed before sent. I told the iOS team to use a standard md5 hash, but of course it don't worked out.
I can't unhash the password and hash it again using the standard md5 (of course), and I don't know what exactly tell to the iOS team, in order to get the same hash.
Any help?
You need to use the same encoding on both ends (probably UTF8).
If you replace your code with
byte[] hashBytes = md5.ComputeHash(Encoding.UTF8.GetBytes("123456"));
, you'll get e10adc3949ba59abbe56e057f20f883e.
You need to use UTF8 instead of Unicode. The following code works exactly like the PHP md5() function:
public static string md5(string value)
{
byte[] encoded = ASCIIEncoding.UTF8.GetBytes(value);
MD5CryptoServiceProvider md5Provider = new MD5CryptoServiceProvider();
byte[] hashCode = md5Provider.ComputeHash(encoded);
string ret = "";
foreach (byte a in hashCode)
ret += String.Format("{0:x2}", a);
return ret;
}

.NET Equivalent of MD5.hex() in Javascript

I'm trying to connect to a website I made with auth that uses MD5.hex(password) to encrypt the password before sending it to the PHP. How could I achieve the same encryption in C#?
EDIT1:
Javascript (YUI Library):
pw = MD5.hex(pw);
this.chap.value = MD5.hex(pw + this.token.value);
C#.NET
string pw = getMD5(getHex(getMD5(getHex(my_password)) + my_token));
Utility:
public string getMD5(string input)
{
// Create a new instance of the MD5CryptoServiceProvider object.
MD5 md5Hasher = MD5.Create();
// Convert the input string to a byte array and compute the hash.
byte[] data = md5Hasher.ComputeHash(Encoding.Default.GetBytes(input));
// Create a new Stringbuilder to collect the bytes
// and create a string.
StringBuilder sBuilder = new StringBuilder();
// Loop through each byte of the hashed data
// and format each one as a hexadecimal string.
for (int i = 0; i < data.Length; i++)
{
sBuilder.Append(data[i].ToString("x2"));
}
// Return the hexadecimal string.
return sBuilder.ToString();
}
public string getHex(string asciiString)
{
string hex = "";
foreach (char c in asciiString)
{
int tmp = c;
hex += String.Format("{0:x2}", (uint)System.Convert.ToUInt32(tmp.ToString()));
}
return hex;
}
Using .NET's MD5 Class in the System.Security.Cryptography namespace.
The link above contains a short code example; you might also want to check out Jeff Attwood's CodeProject article .NET Encryption Simplified.

Categories

Resources