C# MD5 hash not matches Java / PHP MD5 hash - c#

My exercise is to port an administration-backend from php to .net.
The backend communicates with an app written in java.
Some things compared with md5-hashes, in php and java the md5 hashes are equally.
I cannot change the md5 hash-code in the java app, because then will over 10k customer cards not work.
My problem is, the backend is ported and now the communication between the new backend (.net) and the java app.
My .net md5-hash code returns not the same hash as the java code.
java:
public static String getMD5(String input) {
try {
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] messageDigest = md.digest(input.getBytes());
BigInteger number = new BigInteger(1, messageDigest);
String hashtext = number.toString(16);
// Now we need to zero pad it if you actually want the full 32 chars.
while (hashtext.length() < 32)
hashtext = "0" + hashtext;
return hashtext;
}
catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
}
}
and my .net code:
public String hashMD5(String wert)
{
byte[] asciiBytes = ASCIIEncoding.UTF8.GetBytes(wert);
byte[] hashedBytes = MD5CryptoServiceProvider.Create().ComputeHash(asciiBytes);
string hashedString = BitConverter.ToString(hashedBytes).Replace("-", "").ToLower();
return hashedString;
}
my java code returns for bb27aee4 :
46d5acfcd281bca9f1df7c9e38d50576
and my .net code returns:
b767fe33172ec6cbea569810ee6cfc05
I don't know what I have to do...
Please help and thanks in advance.

Its not the problem of MD5 hash generator
MD5 hash for bb27aee4 : 46d5acfcd281bca9f1df7c9e38d50576 &
MD5 hash for BB27AEE4 : b767fe33172ec6cbea569810ee6cfc05
So basically in .NET you are generating MD5 hash for BB27AEE4 instead of bb27aee4
So check for the error in your code
Good Luck

The reason you're seeing different results from your hash is because the encoding used for your string differs. In your .NET code, you specify UTF8 explicitly, while there is no guarantee your Java code does the same; it may very well be using ASCII, which results in different hashes being generated.
If you explicitly specify the same encoding in both your .NET and Java code, you'll end up with the same MD5 hashes as well.

Related

get double hash result like js-sha1 library in c#

I try to hash a double (1529480427715.5532) with SHA1 algorithm and i have this hash in c#:
use in string format: "3e8f41233f90a85f9963afaa571ba76afb8bb08d"
use in double format: "c880857c399c7b9cc9c6395197e700543c400b17"
but in fact i want to get this hash "da39a3ee5e6b4b0d3255bfef95601890afd80709" as result like when i'm using js-sha1 library.
Given this code to convert from float64 (that is double in C#) to Uint8array, you can:
// c880857c399c7b9cc9c6395197e700543c400b17
var hash = sha1(convertTypedArray(new Float64Array([1529480427715.5532]), Uint8Array));
or even shorter, without using that link, because sha1 accepts ArrayBuffer as a parameter:
var hash = sha1(new Float64Array([1529480427715.5532]).buffer);
Note that sha1 accepts only some types of input, number isn't one of them.
From the examples of the library it seems strings, Array, Uint8Array, ArrayBuffer are supported.
As written by #Freggar,
// da39a3ee5e6b4b0d3255bfef95601890afd80709
var hash = sha1('');
And, using strings:
// 3e8f41233f90a85f9963afaa571ba76afb8bb08d
var hash = sha1('1529480427715.5532');

Convert encrypt/decrypt from Java to C# using bouncycastle

I'm trying to convert a couple of function from Java to c# using Portable.BouncyCastle and while there are plenty of example out there, I don't seem to be able to find one to match my requirements as most example seem to explain one specific encryption/decryption method while this function appears to be more generic. I could be wrong of course as I'm a complete newbie to this and don't have any experience in either BouncyCastle, Java or encryption, so please bear with me on this one.
The java function is:
public static byte[] Cipher(int mode, byte[] key,
byte[] data, string algorithm, AlgorithmParameterSpec spec)
{
Cipher cipher = Cipher.getInstance(algorithm);
SecretKeySpec keySpec = new SecretKeySpec(key, algorithm);
if (spec != null)
cipher.init(mode, keySpec, spec);
else
cipher.init(mode, keySpec);
return cipher.doFinal(data);
}
I found some code from BouncyCasle where I can match most of the functionality from what I can see:
byte[] K = Hex.Decode("404142434445464748494a4b4c4d4e4f");
byte[] N = Hex.Decode("10111213141516");
byte[] P = Hex.Decode("68656c6c6f20776f726c642121");
byte[] C = Hex.Decode("39264f148b54c456035de0a531c8344f46db12b388");
KeyParameter key = ParameterUtilities.CreateKeyParameter("AES", K);
IBufferedCipher inCipher = CipherUtilities.
GetCipher("AES/CCM/NoPadding");
inCipher.Init(true, new ParametersWithIV(key, N));
byte[] enc = inCipher.DoFinal(P);
1. SecretKeySpec:
SecretKeySpec keySpec = new SecretKeySpec(key, algorithm);
How do I create this using BC? Is that the equivalent of the SecretKeySpec:
KeyParameter key = ParameterUtilities.CreateKeyParameter("AES", K);
If it is, can I pass the "AES/CCM/NoPadding" instead of AES as it is done in Java?
2. spec parameter:
It passes parameters of type IvParameterSpec to the Cypher function when called from `Java` via the `AlgorithmParameterSpec spec` parameter:
Cipher(ENCRYPT_MODE, key, clearBytes,
algorithm,
new IvParameterSpec(iv))
`BouncyCastle` does not have an overloaded function for `.Init` to allow me to pass the spec parameter as it does in `Java`, so how do I mimic this behaviour?
3. IvParameterSpec: You can see that when cypher is called from java, it passes the AlgorithmParameterSpec spec as new IvParameterSpec(iv) but with BouncyCastle, it seems to be expecting a key?
ParametersWithIV(key, N)
Will that difference have any impact on the encryption/decryption?
This is current my attempt at "converting" this function:
public static byte[] Cipher(bool isEncrypt, byte[] key, byte[] data,
string algorithm, ICipherParameters spec)
{
IBufferedCipher cipher = CipherUtilities.GetCipher(algorithm);
KeyParameter keySpec = ParameterUtilities.
CreateKeyParameter(algorithm, key);
cipher.Init(isEncrypt, new ParametersWithIV(keySpec,
keySpec.GetKey()));
return cipher.DoFinal(data);
}
As you can see I've changed the spec parameter to ICipherParameters spec but I don't know if this will work as when using Bouncy, it looks like that when I create a new ParametersWithIV, it needs a key and from the test sample I provided above, that key is created using KeyParameter key = ParameterUtilities.CreateKeyParameter("AES", K); so technically won't work when trying to call my Cipher function as I will have called this function yet. Should I change spec parameter to iv and pass a byte[] instead?
Apologies if there is confusion or if things are not explained correctly but as I said, I'm new to this and trying to understand it better while also converting. I hope most of it makes sense and you'll be able to help.
Many Thanks.
PS: Note that I'm not in a position to test these in Java yet, but I will hopefully have an environment set up correctly in the new few days which will hopefully help testing values between .net & java.
UPDATE 1
Passing AES/CCM/NoPadding to:
KeyParameter key = ParameterUtilities.CreateKeyParameter
Throws an error, so this partially answers one of my questions. Is there a function in BouncyCastle to determine the correct value that is required i.e. AES when AES/CCM/NoPadding is passed?
Ended up using the code below as it appears to be working as expected but still annoyed I had to hardcode the AES as the key of IV parameter part. Ideally I would have liked this to have been based on my Algorithm. So, now I have a single function to encrypt and decrypt:
public static byte[] Cipher(bool forEncryption, byte[] key,
byte[] data, string algorithm, byte[] iv)
{
IBufferedCipher cipher = CipherUtilities.GetCipher(algorithm);
KeyParameter keySpec = ParameterUtilities.CreateKeyParameter("AES", key);
cipher.Init(forEncryption, new ParametersWithIV(keySpec, iv));
return cipher.DoFinal(data);
}
Hope this helps.

Generating 64 Chars key for API

I want to generate a API key for new clients that want to use any of my API services.
because I'm using a open API service i don't want to use authentication only identify the client usage by the API key
I tried to use this code
public static string GetAPIKey()
{
string sig = string.Empty;
using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider())
{
var ex = rsa.ExportParameters(true);
sig = Convert.ToBase64String(ex.DQ);
sig = sig
.Replace("+", "")
.Replace("/", "")
.TrimEnd('=');
}
return sig.Substring(0, 64);
}
In my tests i do get a random 64 length string, but something not feeling right with the method usage. proberly because of the RSACryptoServiceProvider usage, especially when i try to generate the DQ property
Do you know any better implementation of generating a random 64 string?
If you do not want to use a GUID you can use the standard Random class in C#.
private static readonly Random Random = new Random();
public static string GetApiKey()
{
var bytes = new byte[48];
Random.NextBytes(bytes);
var result = Convert.ToBase64String(bytes);
return result;
}
Since 48 bytes will map to 64 characters in Base64, this gives you 64 random characters. It does not guarantee uniqueness however.
Why not just use a GUID?
Use it twice to generate a 64 character string, which is completely random and unique.

Computing md5 hash

I am computing md5hash of files to check if identical so I wrote the following
private static byte[] GetMD5(string p)
{
FileStream fs = new FileStream(p, FileMode.Open);
HashAlgorithm alg = new HMACMD5();
byte[] hashValue = alg.ComputeHash(fs);
fs.Close();
return hashValue;
}
and to test if for the beginning I called it like
var v1 = GetMD5("C:\\test.mp4");
var v2 = GetMD5("C:\\test.mp4");
and from debugger I listed v1 and v2 values and they are different !! why is that ?
It's because you're using HMACMD5, a keyed hashing algorithm, which combines a key with the input to produce a hash value. When you create an HMACMD5 via it's default constructor, it will use a random key each time, therefore the hashes will always be different.
You need to use MD5:
private static byte[] GetMD5(string p)
{
using(var fs = new FileStream(p, FileMode.Open))
{
using(var alg = new MD5CryptoServiceProvider())
{
return alg.ComputeHash(fs);
}
}
}
I've changed the code to use usings as well.
From the HMACMD5 constructor doc:
HMACMD5 is a type of keyed hash algorithm that is constructed from the
MD5 hash function and used as a Hash-based Message Authentication Code
(HMAC). The HMAC process mixes a secret key with the message data,
hashes the result with the hash function, mixes that hash value with
the secret key again, and then applies the hash function a second
time. The output hash will be 128 bits in length.
With this constructor, a 64-byte, randomly generated key is used.
(Emphasis mine)
With every call to GetMD5(), you're generating a new random key.
You might want to use System.Security.Cryptography.MD5Cng
My guess is that you did something like:
Console.WriteLine(v1);
Console.WriteLine(v2);
or
Console.WriteLine(v1 == v2);
That just shows that the variable values refer to distinct arrays - it doesn't say anything about the values within those arrays.
Instead, try this (to print out the hex):
Console.WriteLine(BitConverter.ToString(v1));
Console.WriteLine(BitConverter.ToString(v2))
Use ToString() methode to get the value of the array byte

C# MD5 Hash results not expected result

I've tried every example I can find on the web but I cannot get my .NET code to produce the same MD5 Hash results from my VB6 app.
The VB6 app produces identical results to this site:
http://www.functions-online.com/md5.html
But I cannot get the same results for the same input in C# (using either the MD5.ComputeHash method or the FormsAuthentication encryption method)
Please help!!!!
As requested, here is some code. This is pulled straight from MSDN:
public string hashString(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();
}
My test string is:
QWERTY123TEST
The results from this code is:
8c31a947080131edeaf847eb7c6fcad5
The result from Test MD5 is:
f6ef5dc04609664c2875895d7da34eb9
Note: The result from the TestMD5 is what I am expecting
Note: I've been really, really stupid, sorry - just realised I had the wrong input. As soon as I hard-coded it, it worked. Thanks for the help
This is a C# MD5 method that i know works, i have used it to authenticate via different web restful APIs
public static string GetMD5Hash(string input)
{
System.Security.Cryptography.MD5CryptoServiceProvider x = new System.Security.Cryptography.MD5CryptoServiceProvider();
byte[] bs = System.Text.Encoding.UTF8.GetBytes(input);
bs = x.ComputeHash(bs);
System.Text.StringBuilder s = new System.Text.StringBuilder();
foreach (byte b in bs)
{
s.Append(b.ToString("x2").ToLower());
}
return s.ToString();
}
What makes the "functions-online" site (http://www.functions-online.com/md5.html) an authority on MD5? For me, it works OK only for ISO-8859-1. But when I try pasting anything other than ISO-8859-1 into it, it returns the same MD5 hash. Try Cyrillic capital B by itself, code point 0x412. Or try Han Chinese symbol for water, code point 0x98A8.
As far as I know, the posted C# applet is correct.

Categories

Resources