Difference between HMACSHA512 constructor and factory - c#

Why does this returns a hash size of 512 bit ...
var text = "Hello World";
var buffer = Encoding.UTF8.GetBytes(text);
var hmac = new System.Security.Cryptography.HMACSHA512();
hmac.Key = GetRandomBits(512);
hmac.ComputeHash(buffer);
Assert.That(hmac.HashSize, Is.EqualTo(512));
... and this a hash size of 160 bit?
var text = "Hello World";
var buffer = Encoding.UTF8.GetBytes(text);
var hmac = System.Security.Cryptography.HMACSHA512.Create();
hmac.Key = GetRandomBits(512);
hmac.ComputeHash(buffer);
Assert.That(hmac.HashSize, Is.EqualTo(512)); // failure
The constructor and the factory are both related to HMACSHA512, so I assumend the same output.

There is no HMACSHA512.Create(). You're actually calling HMAC.Create() (because the language allows writing calls to static methods off of derived types)
So you're just getting "an HMAC", which seems to be HMACSHA1.

It looks to me like the Create factory method is not doing HMACSHA512 when used in this way.
The documentation breaks it down for us.
Return Value Type: System.Security.Cryptography.HMAC A new SHA-1
instance, unless the default settings have been changed by using the
element.
So it looks like the reason they are different in size is because the Create Method is returning a SHA-1 instance instead of the HMACSHA512 instance as you expected.

Related

How to recreate TpmPublic instance from result of TpmPublic.GetTpm2BRepresentation()

I am able to store the endorsement key from a TPM in a byte array using the following code (referencing TSS.NET):
TpmPublic ekPub = GetEndorsementKey();
byte[] ek = ekPub.GetTpm2BRepresentation();
I have tried this, but I don't know how to get from a Tpm2bPublicKeyRsa instance to an instance of TpmPublic:
Tpm2bPublicKeyRsa temp = new Tpm2bPublicKeyRsa(ek)
Notes:
I want to pass the endorsement key around as a byte array because it's convenient to Base64 encode the array for copy/paste.
I want to get back to an instance of TpmPublic so that I can transform that key (like this) into something I can use it server side in .NET (without a TPM) .
The solution I came up with was to use the GetTpmRepresentation method:
TpmPublic ekPub = GetEndorsementKey();
byte[] ekPubBytes = ekPub.GetTpmRepresentation();
That makes it easy to get the TpmPublic instance back using the marshaller:
var mashaller = new Marshaller(ekPubBytes);
TpmPublic ekPub = m.Get<TpmPublic>();

What is the .NET System.Numerics.BigInteger Equivalent of Org.BouncyCastle.Math.BigInteger.ToByteArrayUnsigned?

I am currently working with the .NET port of BouncyCastle and I am having some trouble converting a big integer into a System.Guid using the native .NET BigInteger.
For some context, I am using BouncyCastle in one ("source") application to convert a System.Guid to a Org.BouncyCastle.Math.BigInteger. This value is then saved as a string in the format 3A2B847A960F0E4A8D49BD62DDB6EB38.
Then, in another ("destination") application, I am taking this saved string value of a BigInteger and am trying to convert it back into a System.Guid.
Please note that in the destination application I do not want BouncyCastle as a reference and would like to use core .NET libraries for the conversion. However, since I am running into problems converting with core .NET classes, I am using BouncyCastle and the following code does exactly what I would like:
var data = "3A2B847A960F0E4A8D49BD62DDB6EB38";
var integer = new Org.BouncyCastle.Math.BigInteger( data, 16 );
var bytes = integer.ToByteArrayUnsigned();
var guid = new Guid( bytes ); // holds expected value: (7A842B3A-0F96-4A0E-8D49-BD62DDB6EB38)
As you can see, there is a ToByteArrayUnsigned method on the Org.BouncyCastle.Math.BigInteger that makes this work. If I use the ToByteArray on the System.Numerics.BigInteger (even when resizing the array as discussed in this question) it does not work and I get a different System.Guid than expected.
So, what is the best way to perform the equivalent to the above operation using native .NET classes?
Solution
Thanks to #John-Tasler's suggestion, it turns out this was due to endianess... darn you endianess... will your endiness ever end? :P
var parsed = System.Numerics.BigInteger.Parse( "3A2B847A960F0E4A8D49BD62DDB6EB38", NumberStyles.HexNumber ).ToByteArray();
Array.Resize( ref parsed, 16 );
var guid = new Guid( parsed.Reverse().ToArray() ); // Hoorrrrayyyy!
What's the actual value of the resulting Guid when using .NET's BigIntegrer?
It could be that the two implementations are just storing the bytes differently. Endianess, etc.
To see what comes back from each implementation's array of bytes:
var sb = new StringBuilder();
foreach (var b in bytes)
{
sb.AppendFormat("{0:X2} ", b);
}
sb.ToString();
It'd be an interesting comparison.
I would avoid BigInteger here entirely. Your data bytes are already in the correct order so you can convert to byte[] directly.
var data = "3A2B847A960F0E4A8D49BD62DDB6EB38";
var bytes = new byte[16];
for (var i = 0; i < 16; i++)
bytes[i] = byte.Parse(data.Substring(i * 2, 2), NumberStyles.HexNumber);
var guid = new Guid(bytes); // 7a842b3a-0f96-4a0e-8d49-bd62ddb6eb38

xxHash convert resulting in hash too long

I'm using xxHash for C# to hash a value for consistency.
ComputeHash returns a byte[], but I need to store the results in a long.
I'm able to convert the results into an int32 using the BitConverter. Here is what I've tried:
var xxHash = new System.Data.HashFunction.xxHash();
byte[] hashedValue = xxHash.ComputeHash(Encoding.UTF8.GetBytes(valueItem));
long value = BitConverter.ToInt64(hashedValue, 0);
When I use int this works fine, but when I change to ToInt64 it fails.
Here's the exception I get:
Destination array is not long enough to copy all the items in the collection. Check array index and length.
When you construct your xxHash object, you need to supply a hashsize:
var hasher = new xxHash(32);
valid hash sizes are 32 and 64.
See https://github.com/brandondahler/Data.HashFunction/blob/master/src/xxHash/xxHash.cs for the source.
Adding a new answer because current implementation of xxHash from Brandon Dahler uses a hashing factory where you initialize the factory with a configuration containing hashsize and seed:
using System.Data.HashFunction.xxHash;
//can also set seed here, (ulong) Seed=234567
xxHashConfig config = new xxHashConfig() { HashSizeInBits = 64 };
var factory = xxHashFactory.Instance.Create(config);
byte[] hashedValue = factory.ComputeHash(Encoding.UTF8.GetBytes(valueItem)).Hash;
BitConverter.ToInt64 expects hashedValue to have 8 bytes (= 64bits). You could manually extend, and then pass it.

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