Validating HMACSHA256 in C# - c#

I'm pretty new to asp.net/c# and i'm trying to recreate the password validation in C#. I have this hash stored in the database:
U2zdbUmZXCeOLs0OuS9bhg==7hQ60TTq0ZiT/z+eu4bdzpmBcp5uYa70ZDxQPncEG0c=
The password for this hash is 1234567. This works because I can login with this password in the webapplication.
So if I understand correctly. The hash consists of a base64 encoded salt U2zdbUmZXCeOLs0OuS9bhg== and a password hashed with this salt: 7hQ60TTq0ZiT/z+eu4bdzpmBcp5uYa70ZDxQPncEG0c=
But if I use this example I found on the internet. I don't get the same hash result. I already tried playing with the encoding (resulting in different hashes), but no luck. hashAlgorithmType is set to HMACSHA256 in the web.config. What am I doing wrong?
using System;
using System.Security.Cryptography;
using System.Text;
public class Program
{
public static void Main()
{
var base64Salt = "U2zdbUmZXCeOLs0OuS9bhg==";
var base64Hash = "7hQ60TTq0ZiT/z+eu4bdzpmBcp5uYa70ZDxQPncEG0c=";
// Decode the base64 salt to get the salt byte array
var saltBytes = Convert.FromBase64String(base64Salt);
// Provide the user's plain password
var plaintextPassword = "1234567";
// Salt the plaintext password, prepend to user's provided password, and then hash
try
{
var hmac256 = new HMACSHA256(saltBytes);
var hash = Convert.ToBase64String(hmac256.ComputeHash(Encoding.UTF8.GetBytes(plaintextPassword)));
Console.WriteLine(base64Salt+hash);
if (hash == base64Hash)
{
Console.WriteLine("Success! Both hashes match!");
}
else
{
Console.WriteLine("Passwords do not match.");
}
}
catch (Exception e)
{
Console.WriteLine("Error!", e.Message);
}
}
}

You need to know the right key used and how is the password concatenated with the salt.
Normally, the salt bytes are concatenated with the password bytes, like this:
var password = "1234567";
var passwordBytes = Encoding.UTF8.GetBytes(password);
var salt = "U2zdbUmZXCeOLs0OuS9bhg==";
var saltBytes = Convert.FromBase64String(salt);
var passwordBytesAndSaltBytes = new byte[passwordBytes.Length + saltBytes.Length];
for (int i = 0; i < passwordBytes.Length; i++)
{
passwordBytesAndSaltBytes[i] = passwordBytes[i];
}
for (int i = 0; i < saltBytes.Length; i++)
{
passwordBytesAndSaltBytes[passwordBytes.Length + i] = saltBytes[i];
}
but we don't know what were the rules used.
And the secret is well, kept secret, like this:
var secret = "this must be hidden";
var secretBytes = Encoding.UTF8.GetBytes(secret);
var hmac256 = new HMACSHA256(secretBytes);
var hash = Convert.ToBase64String(hmac256.ComputeHash(passwordBytesAndSaltBytes) );
Without seeing the code, unfortunately, I don't think you will be able to replicate it.

Finally got it to work! I found the answer in the source code of Umbraco (I'm using Umbraco as CMS). I thought it was using the default membershipprovider but it wasn't... Also worth mentioning that the salt was to short for the required key-length, so it was extended.
From the source code I made a working example:
using System;
using System.Security.Cryptography;
using System.Text;
public class Program
{
public static void Main()
{
var bytes = Encoding.Unicode.GetBytes("1234567");
var saltBytes = Convert.FromBase64String("U2zdbUmZXCeOLs0OuS9bhg==");
byte[] inArray;
var hashAlgorithm = HashAlgorithm.Create("HMACSHA256");
var algorithm = hashAlgorithm as KeyedHashAlgorithm;
var keyedHashAlgorithm = algorithm;
if (keyedHashAlgorithm.Key.Length == saltBytes.Length)
{
//if the salt bytes is the required key length for the algorithm, use it as-is
keyedHashAlgorithm.Key = saltBytes;
Console.WriteLine("length is ok");
}
else if (keyedHashAlgorithm.Key.Length < saltBytes.Length)
{
//if the salt bytes is too long for the required key length for the algorithm, reduce it
var numArray2 = new byte[keyedHashAlgorithm.Key.Length];
Buffer.BlockCopy(saltBytes, 0, numArray2, 0, numArray2.Length);
keyedHashAlgorithm.Key = numArray2;
Console.WriteLine("salt byte too long");
}
else
{
//if the salt bytes is too short for the required key length for the algorithm, extend it
Console.WriteLine("salt byte to short");
var numArray2 = new byte[keyedHashAlgorithm.Key.Length];
var dstOffset = 0;
while (dstOffset < numArray2.Length)
{
var count = Math.Min(saltBytes.Length, numArray2.Length - dstOffset);
Buffer.BlockCopy(saltBytes, 0, numArray2, dstOffset, count);
dstOffset += count;
}
keyedHashAlgorithm.Key = numArray2;
}
inArray = keyedHashAlgorithm.ComputeHash(bytes);
var hash = Convert.ToBase64String(inArray);
Console.WriteLine(hash);
var base64Hash = "7hQ60TTq0ZiT/z+eu4bdzpmBcp5uYa70ZDxQPncEG0c=";
if (hash == base64Hash)
{
Console.WriteLine("Success! Both hashes match!");
}
else
{
Console.WriteLine("Passwords do not match.");
}
}
}

Related

SHA 512 and or ARGON2ID Hashing + Salt For Dovecot in C#

I have tried to generate a salted hash using ARGON2ID and am running in to the same issues. The dovecot password generation utility generates the correct hash but I still cant seem to get things working using C#.
I am using the Konscious.Security.Cryptography.Argon2 Nuget Package at the moment..
Like I said still doesn't work even after playing with the length of the salt
I setup a new mail-server using postfix and dovecot. The password storage I am using is SSHA512 which means SHA512 with a salt. I need to create an ASP.NET page that allows the user to create and change their e-mail password in the DB. I could use the SQL route but I would like to do this in C# so I can use NHibernate which is my ORM.
I found a post online that creates the hash and salt using SQL.
INSERT INTO virtual_users
(id, domain_id, password , email)
VALUES
(NULL, '1', (SELECT REPLACE(TO_BASE64(CONCAT(UNHEX(SHA2(CONCAT('YourPasswordHere', v.salt), 512)), v.salt)), '\n', '') AS salted FROM (SELECT SHA2(RAND(), 512) AS salt) v), 'user#example.com');
UPDATE virtual_users
SET password = (
SELECT REPLACE(TO_BASE64(CONCAT(UNHEX(SHA2(CONCAT('YourPasswordHere', v.salt), 512)), v.salt)), '\n', '') AS salted
FROM (
SELECT SHA2(RAND(), 512) AS salt
) v
)
WHERE email = 'user#example.com';
Here is an explanation of what is going on. I am trying to do the following in C# and am not having any luck..
Generate a random (rather lengthy) salt
Append the salt to the password
Get the SHA512 Hash of #2
Convert the hash to binary
Append the salt to #4
Convert the whole thing to Base64
7 .Remove unwanted newlines added by MySQL's TO_BASE64() function
The result is a 256 byte long string so you may need to update your password field to VARCHAR(256).
Any instruction would be greatly appreciated.
Here is what I have so far but it doesn't seem to work
SH1512 Code:
//My Random Method
public byte[] GenerateRandomCryptographicBytes(int keyLength)
{
var randomBytes = new byte[keyLength];
var rng = RandomNumberGenerator.Create();
rng.GetBytes(randomBytes);
return randomBytes;
}
//Hashing Method:
public PasswordHashResult HashWithSalt(string password, int saltLength, HashAlgorithm hashAlgo)
{
var rng = new Rng();
var saltBytes = rng.GenerateRandomCryptographicBytes(saltLength);
var passwordAsBytes = Encoding.UTF8.GetBytes(password);
var passwordWithSaltBytes = new List<byte>();
passwordWithSaltBytes.AddRange(passwordAsBytes);
passwordWithSaltBytes.AddRange(saltBytes);
var digestBytes = hashAlgo.ComputeHash(passwordWithSaltBytes.ToArray());
return new PasswordHashResult
{
Salt = Convert.ToBase64String(saltBytes),
PasswordHash = Convert.ToBase64String(digestBytes)
};
}
//Result Class:
public sealed class PasswordHashResult
{
public string PasswordHash { get; set; }
public string Salt { get; set; }
public string HashAndSalt { get; set; }
}
Argon2 Code:
public byte[] CreateHash(byte[] password, byte[] salt)
{
using var argon2 = new Argon2id(password);
argon2.Salt = salt;
argon2.DegreeOfParallelism = 8;
argon2.Iterations = 4;
argon2.MemorySize = 1024 * 128;
return argon2.GetBytes(32);
}
public static byte[] GenerateRandomCryptographicBytes()
{
var randomBytes = new byte[32];
var rng = RandomNumberGenerator.Create();
rng.GetBytes(randomBytes);
return randomBytes;
}
var bytes = Encoding.UTF8.GetBytes(plainTextPassword);
var salt = PasswordService.GenerateRandomCryptographicBytes(); // Salt should be stored alongside hash.
var hash = passwordService.CreateHash(bytes, salt);
Here is what the Argon2id hash looks like.
{ARGON2ID}$argon2id$v=19$m=65536,t=3,p=1$UCLtz5ubAeKTzeIVo0pzPw$jDDq5JmNX9LRzmlzknJWsGYKJ0TLiEHG6MGt5jcp6XQ
Nothing Like What I Get returned from the code above.

Store user credentials in a local file in c#

I am developing an app in C# .NET. The app will not connect to any database and during the installation it will create files and settings for the application and user. I want to store user data in a local file such as text file or flat file or JSON file.
In simple words I want to prevent user opening the file but if somehow user find a way to open it then at least he should not understand what information is stored. Is there any good method to encrypt file and data in it?
Just like how Google chrome stores data:
1 ŒA û œA àû ¯A ü ÂA °ü ÒA ý åA Pý õA À% B & B p& (B °m <B n OB ðn bB Po uB °o ˆB q ›B Àq ®B r ÁB €r ÔB s çB pt úB °u
C #v C  v 3C x FC Àx YC  z lC P| C °| ’C ð} ¥C P~ ¸C 0 ËC ÞC € ñC € D   D ‚ *D °ƒ =D „ ND „
You can try encrypting the file and decrypt it when you need to access it.
Encryption
Decryption
Example of encryption and decryption from MS Docs:
using System.IO;
using System.Security.AccessControl;
namespace FileSystemExample
{
class FileExample
{
public static void Main()
{
try
{
string FileName = "test.xml";
Console.WriteLine("Encrypt " + FileName);
// Encrypt the file.
AddEncryption(FileName);
Console.WriteLine("Decrypt " + FileName);
// Decrypt the file.
RemoveEncryption(FileName);
Console.WriteLine("Done");
}
catch (Exception e)
{
Console.WriteLine(e);
}
Console.ReadLine();
}
// Encrypt a file.
public static void AddEncryption(string FileName)
{
File.Encrypt(FileName);
}
// Decrypt a file.
public static void RemoveEncryption(string FileName)
{
File.Decrypt(FileName);
}
}
}
I wrote a very simple text encryptor that you can use. Simply encrypt the text before storing it and decrypt it as you need it.
This will not stop someone who is willing to spend a little bit of time with a debugger, but just like locking your door it will keep honest people honest.
I also included some unit tests, feel free to remove them.
using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using NUnit.Framework;
namespace Encryption;
public static class SimpleEncryptor
{
public static async Task<string> EncryptAsync(string cleartext, string password)
{
var hasher = SHA256.Create();
var key = hasher.ComputeHash(Encoding.UTF8.GetBytes(password));
using var aes = Aes.Create();
aes.Key = key;
aes.Padding = PaddingMode.PKCS7;
var iv = aes.IV;
var byteStream = new MemoryStream(10000);
byteStream.Write(iv, 0, iv.Length);
using var cryptoStream = new CryptoStream(
byteStream,
aes.CreateEncryptor(),
CryptoStreamMode.Write);
var encryptWriter = new StreamWriter(cryptoStream);
await encryptWriter.WriteAsync(cleartext);
encryptWriter.Close();
var bytes = byteStream.ToArray();
var base64 = Convert.ToBase64String(bytes);
return base64;
}
public static async Task<string> DecryptAsync(string ciphertext, string password)
{
var hasher = SHA256.Create();
var key = hasher.ComputeHash(Encoding.UTF8.GetBytes(password));
var encryptedArray = Convert.FromBase64String(ciphertext);
var byteStream = new MemoryStream(encryptedArray);
using var aes = Aes.Create();
aes.Key = key;
aes.Padding = PaddingMode.PKCS7;
var iv = new byte[aes.IV.Length];
var numBytesToRead = aes.IV.Length;
var numBytesRead = 0;
while (numBytesToRead > 0)
{
var n = byteStream.Read(iv, numBytesRead, numBytesToRead);
if (n == 0) break;
numBytesRead += n;
numBytesToRead -= n;
}
using var cryptoStream = new CryptoStream(
byteStream,
aes.CreateDecryptor(key, iv),
CryptoStreamMode.Read);
var decryptReader = new StreamReader(cryptoStream);
var decryptedMessage = await decryptReader.ReadToEndAsync();
return decryptedMessage;
}
}
public class EncryptorTests
{
[Test]
[TestCase("How do you turn this on?", "Swordfish", "GHzrU6z5hsgb6HSJtMZyirEs11sHY/X4l5zElwxHz9jpIGA+D9TAxv7SEU31/Jgb")]
[TestCase("Orange you glad I didn't say banana?", "hunter12", "qqNFxhwKYkkYzsN0vDzWhQguZ7f9xc+60duZXQATAzQslRhJsn6lc691+yVR0SWJYDJUD9ZbezpW/v4vYi6qeA==")]
[TestCase("Orange you glad I didn't say banana?", "hunter12", "TsjCbMOT4UKVi6L43Kkc0rMsl6IyeEfLBR3ruAsG+APUjb1zesVLGA/B0yF4FkFV/j1Rc5B55ClZYHV2zoubBA==")]
[TestCase("Your mother is rather fat.", "12345", "WD8e5E+PtQ5kMqkPSIZa18pDutbqn8OroSU5utHFTuikbgIWLA4IRAHihrfiXrV6")]
[TestCase("Yer' a wizard harry!", "Swordfish", "Z6tF/3iDTu72qTeVnKa8DZOsL5NFD9XfqJTWebANVrjQysm+8ps3Z9RuoJyenk30")]
public async Task TestDecryption(string text, string password, string ciphertext)
{
var decoded = await SimpleEncryptor.DecryptAsync(ciphertext, password);
Assert.AreEqual(text, decoded);
}
[Test]
[TestCase("How do you turn this on?", "Swordfish")]
[TestCase("Orange you glad I didn't say banana?", "hunter12")]
[TestCase("Your mother is rather fat.", "12345")]
[TestCase("Yer' a wizard harry!", "Swordfish")]
public async Task TestEncryptAndDecrypt(string text, string password)
{
var ciphertext = await SimpleEncryptor.EncryptAsync(text, password);
var decodedtext = await SimpleEncryptor.DecryptAsync(ciphertext, password);
Assert.AreEqual(text, decodedtext);
}
}

Generating Hashed Passwords in C#

I don't know if this is the correct place to ask, but I am having an issue hashing passwords for MySql Backend. I am running mosquitto 1.4.3 broker and I have the mosquitto-auth-plugin working on the same server. But I want to move the auth-plugin to a new server. So I created a admin program in C# to add users and access controls however I cant seem to the get the correct hash code for the password.
Has anyone implemented this or is there some resoucres available to create the correct hash?
I have tried this Hash It Right
private const int SaltByteLength = 12;
private const int DerivedKeyLength = 24;
public string CreatePasswordHash(string password)
{
var salt = GenerateRandomSalt();
var iterationCount = GetIterationCount();
var hashValue = GenerateHashValue(password, salt, iterationCount);
var iterationCountBtyeArr = BitConverter.GetBytes(iterationCount);
var valueToSave = new byte[SaltByteLength + DerivedKeyLength + iterationCountBtyeArr.Length];
Buffer.BlockCopy(salt, 0, valueToSave, 0, SaltByteLength);
Buffer.BlockCopy(hashValue, 0, valueToSave, SaltByteLength, DerivedKeyLength);
Buffer.BlockCopy(iterationCountBtyeArr, 0, valueToSave, salt.Length + hashValue.Length, iterationCountBtyeArr.Length);
return Convert.ToBase64String(valueToSave);
}
private int GetIterationCount()
{
return 901;
}
private static byte[] GenerateRandomSalt()
{
var csprng = new RNGCryptoServiceProvider();
var salt = new byte[SaltByteLength];
csprng.GetBytes(salt);
return salt;
}
private static byte[] GenerateHashValue(string password, byte[] salt, int iterationCount)
{
byte[] hashValue;
var valueToHash = string.IsNullOrEmpty(password) ? string.Empty : password;
using (var pbkdf2 = new Rfc2898DeriveBytes(valueToHash, salt, iterationCount))
{
hashValue = pbkdf2.GetBytes(DerivedKeyLength);
}
return hashValue;
}
will this make it easier for you?
using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;
class Class1
{
static void Main(string[] args)
{
byte[] HashValue;
string MessageString = "This is the original message!";
//Create a new instance of the UnicodeEncoding class to
//convert the string into an array of Unicode bytes.
UnicodeEncoding UE = new UnicodeEncoding();
//Convert the string into an array of bytes.
byte[] MessageBytes = UE.GetBytes(MessageString);
//Create a new instance of the SHA1Managed class to create
//the hash value.
SHA1Managed SHhash = new SHA1Managed();
//Create the hash value from the array of bytes.
HashValue = SHhash.ComputeHash(MessageBytes);
//Display the hash value to the console.
foreach(byte b in HashValue)
{
Console.Write("{0} ", b);
}
}

Verification of Hashing password is not working

I have asked a question of which I did get a lot of great feedback, along with a good answer. I assume that I am doing something wrong with my verification check of the 2 hashes. Perhaps the code in the loop is fine, but my code with understanding of bytes and base64 etc. is the problem?
Here is the original question.
Password Hashing - Why salt 60,000 times
Problem is these hashes do not match if (resultHash.Equals(hashPassword))
Code
public string BuildVerify()
{
string password = "";
string salt = "";
byte[] result;
using (var sha256 = SHA256.Create())
{
password = "hovercraft";
// step 1: you can use RNGCryptoServiceProvider for something worth using
var passwordHashing = new PasswordHashing();
salt = passwordHashing.CreateRandomSalt();
// step 2
string hash =
Convert.ToBase64String(sha256.ComputeHash(Encoding.UTF8.GetBytes(salt + password)));
// step 3
result = sha256.ComputeHash(Encoding.UTF8.GetBytes(salt + hash));
// step 4
for (int i = 0; i < 60000; i++)
{
result =
sha256.ComputeHash(Encoding.UTF8.GetBytes(salt + Convert.ToBase64String(result)));
}
}
// TESTING VERIFY this works ..
string SaltAndPwd = string.Concat(password, salt);
SHA256 sha2 = SHA256Managed.Create();
byte[] buff = sha2.ComputeHash(Encoding.Unicode.GetBytes(SaltAndPwd));
string resultHash = Convert.ToBase64String(buff);
string hashPassword = Convert.ToBase64String(result);
if (resultHash.Equals(hashPassword))
{
// perfect
}
return "";
}
public class PasswordHashing
{
public string CreateRandomSalt()
{
string password = "";
password = HashPassword.CreateSalt(8) + "=";
password = password.Replace("/", "c");
return password;
}
}
public static string CreateSalt(int size)
{
RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
byte[] buff = new byte[size];
rng.GetBytes(buff);
return Convert.ToBase64String(buff);
}
Update - issue
Ok, I'm using the code from the answer, but obviously my assumptions are not correct as I cannot use my code to verify
// This should be stored in your DB for example along with the hash result
var newsalt = SOPasswordHasher.GetSalt();
// We calculate the hash then store the result. Next time you want to authenticate someone
// You'll have to reuse the same salt and recalculate the hash then compare
// the stored hash with the new one
var result = Convert.ToBase64String(SOPasswordHasher.Hash("hovercraft", newsalt));
string SaltAndPwd = string.Concat("hovercraft", newsalt);
SHA256 sha2 = SHA256Managed.Create();
byte[] buff = sha2.ComputeHash(Encoding.Unicode.GetBytes(SaltAndPwd));
string resultHash = Convert.ToBase64String(buff);
if (result.Equals(resultHash))
{
// perfect
}
Here's a reusable class that you can use (relying less on converting to base64):
class SOPasswordHasher
{
/// <summary>
/// Password Hasher
/// </summary>
/// <param name="password">The password you want to hash</param>
/// <param name="salt">byte array of (crypto-secure) random values</param>
/// <param name="iterations">Number of iterations. default is 60,000</param>
/// <returns>Byte array containing the hashed password</returns>
public static byte[] Hash(string password, byte[] salt, int iterations = 60000)
{
using (var sha256 = SHA256.Create())
{
byte[] passwordBytes = Encoding.UTF8.GetBytes(password);
// step 2
byte[] hash = sha256.ComputeHash(passwordBytes.Concat(salt).ToArray());
// step 3
byte[] result = sha256.ComputeHash(salt.Concat(hash).ToArray());
// step 4
for (int i = 0; i < iterations; i++)
{
result =
sha256.ComputeHash(salt.Concat(result).ToArray());
}
return result;
}
}
public static byte[] GetSalt(int size = 32)
{
byte[] salt = new byte[size];
using (var cryptoServiceProvider = new RNGCryptoServiceProvider())
{
cryptoServiceProvider.GetBytes(salt);
}
return salt;
}
}
and here's a usage example:
// This should be stored in your DB for example along with the hash result
var salt = SOPasswordHasher.GetSalt();
// We calculate the hash then store the result. Next time you want to authenticate someone
// You'll have to reuse the same salt and recalculate the hash then compare
// the stored hash with the new one
var result = Convert.ToBase64String(SOPasswordHasher.Hash("hovercraft", salt));
Important: I make no guarantee that this code is safe to use since I'm not a security expert. Bruce Schneier said it best: "Amateurs Produce Amateur Cryptography"

How can you generate the same MD5 Hashcode in C# and Java?

I have a function that generates a MD5 hash in C# like this:
MD5 md5 = new MD5CryptoServiceProvider();
byte[] result = md5.ComputeHash(data);
StringBuilder sb = new StringBuilder();
for (int i = 0; i < result.Length; i++)
{
sb.Append(result[i].ToString("X2"));
}
return sb.ToString();
In java my function looks like this:
MessageDigest m = MessageDigest.getInstance("MD5");
m.update(bytes,0,bytes.length);
String hashcode = new BigInteger(1,m.digest()).toString(16);
return hashcode;
While the C# code generates: "02945C9171FBFEF0296D22B0607D522D" the java codes generates: "5a700e63fa29a8eae77ebe0443d59239".
Is there a way to generate the same md5 hash for the same bytearray?
On demand:
This is the testcode in java:
File file = new File(System.getProperty("user.dir") + "/HashCodeTest.flv");
byte[] bytes = null;
try {
bytes = FileUtils.getBytesFromFile(file);
} catch (IOException e) {
fail();
}
try {
generatedHashCode = HashCode.generate(bytes);
} catch (NoSuchAlgorithmException e) {
fail();
}
and this is my code in C#
var blob = GetBlobByHttpPostedFile(httpPostedFile);
var hashCode = Md5Factory.ConvertByteArray(blob);
private static byte[] GetBlobByHttpPostedFile(HttpPostedFile httpPostedFile)
{
var contentLength = httpPostedFile.ContentLength;
var result = new byte[contentLength];
var inputStream = httpPostedFile.InputStream;
inputStream.Read(result, 0, contentLength);
return result;
}
Cheers
That should be fine - although you could make the Java code simpler by just calling
byte[] digest = m.digest(bytes);
instead of calling update then digest.
Are you absolutely sure you've got the same data in both cases? Could you post sample programs showing this failing with the same hard-coded data?
EDIT: Here's the sort of test I was thinking of. These two programs give the same result:
C#:
using System;
using System.Security.Cryptography;
using System.Text;
class Test
{
static void Main()
{
byte[] bytes = { 0x35, 0x24, 0x76, 0x12 };
MD5 md5 = new MD5CryptoServiceProvider();
byte[] result = md5.ComputeHash(bytes);
StringBuilder sb = new StringBuilder();
for (int i = 0; i < result.Length; i++)
{
sb.Append(result[i].ToString("x2"));
}
Console.WriteLine(sb);
}
}
Java:
import java.math.BigInteger;
import java.security.MessageDigest;
public class Test
{
public static void main(String[] args) throws Exception
{
byte[] bytes = { 0x35, 0x24, 0x76, 0x12 };
MessageDigest m = MessageDigest.getInstance("MD5");
byte[] digest = m.digest(bytes);
String hash = new BigInteger(1, digest).toString(16);
System.out.println(hash);
}
}
Hi I m using this code and it works
C# code :
public static string ConvertStringToMD5(string ClearText)
{
byte[] ByteData = Encoding.ASCII.GetBytes(ClearText);
//MD5 creating MD5 object.
MD5 oMd5 = MD5.Create();
//Hash değerini hesaplayalım.
byte[] HashData = oMd5.ComputeHash(ByteData);
//convert byte array to hex format
StringBuilder oSb = new StringBuilder();
for (int x = 0; x < HashData.Length; x++)
{
//hexadecimal string value
oSb.Append(HashData[x].ToString("x2"));
}
and Java code :
private String getMD5Digest(byte[] buffer) {
String resultHash = null;
try {
MessageDigest md5 = MessageDigest.getInstance("MD5");
byte[] result = new byte[md5.getDigestLength()];
md5.reset();
md5.update(buffer);
result = md5.digest();
StringBuffer buf = new StringBuffer(result.length * 2);
for (int i = 0; i < result.length; i++) {
int intVal = result[i] & 0xff;
if (intVal < 0x10) {
buf.append("0");
}
buf.append(Integer.toHexString(intVal));
}
resultHash = buf.toString();
} catch (NoSuchAlgorithmException e) {
}
return resultHash;
}
I came cross the similar issue that we were using Java MD5 Hash to determine whether a file has been processed. We found we cannot create same hash using .NET library. I tried all above suggestion, unfortunately it is not working for me.
The solution I found out later is: instead of create similar function in .NET, we call Java function directly in .NET. There is one great open source project called Ja.NET. Basically what i did is: create a Java class that create hash using the same code. compile it using Ja.NET javac. Then using bam compile the generated Java class file into DLL and use it in my .NET project.
I know this topic is old but I ran into the same issue just now and couldn't find an answer that worked for me. I was writing a patcher for a game and needed the md5 hashcode of files as a way to ensure that the files are up to date, but C# and Java gave me different strings although the files were identical.
Here's how I solved it:
C# Code:
public static string getMD5(string fullPath)
{
MD5 md5 = MD5.Create();
using (FileStream stream = new FileStream(fullPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
byte[] hash = md5.ComputeHash(stream);
StringBuilder sb = new StringBuilder();
for (int j = 0; j < hash.Length; j++)
{
sb.Append(hash[j].ToString("X2"));
}
return sb.ToString();
}
}
This creates a 32 character hex string. Apache Commons DigestUtils.md5Hex(InputStream) does the same, now the only different is that the C# example returns an uppercase string, so the solution is simply to convert the hash from the Java program to an uppercase string.
Java code:
public static String checkSumApacheCommons(String filePath)
{
String checksum = null;
try
{
checksum = DigestUtils.md5Hex(new FileInputStream(filePath));
}
catch (IOException ex)
{
ex.printStackTrace(System.out);
}
return checksum.toUpperCase();
}
The produced hashes look like F674865D8A44695A2443017CFA2B0C67.
Hope this helps someone.

Categories