I have this bit of t-sql code
set #UrlHash = convert(bigint, hashbytes('MD5', #Url))
I wonder if I can write a function in C# which returns me the exact same hash as the line above without going to SQL.
Is it possible?
Requirement is that C# MUST created exact same hash.
The select
SELECT CONVERT(BIGINT, HASHBYTES('MD5', 'http://stackoverflow.com'))
will yield the following result:
-3354682182756996262
If you now try to create a MD5 hash in C#
MD5 md5 = MD5.Create();
byte[] textToHash = Encoding.UTF8.GetBytes("http://stackoverflow.com");
byte[] result = md5.ComputeHash(textToHash);
long numeric = BitConverter.ToInt64(result, 0);
numeric will be 8957512937738269783.
So what's the issue (besides the fact that a MD5 hash is 128-bit and BIGINT/long is just 64-bit)?
It's an endian issue (the bytes are in the wrong order). Let's fix it using the BitConverter class and reverse the bytes as needed:
MD5 md5 = MD5.Create();
byte[] textToHash = Encoding.UTF8.GetBytes("http://stackoverflow.com");
byte[] result = md5.ComputeHash(textToHash);
if (BitConverter.IsLittleEndian)
Array.Reverse(result);
long numeric = BitConverter.ToInt64(result, 0);
numeric is now -3354682182756996262 as you want.
You should use MD5 class, here is the example from http://blogs.msdn.com/b/csharpfaq/archive/2006/10/09/how-do-i-calculate-a-md5-hash-from-a-string_3f00_.aspx, with output as int 64 :
public int64 CalculateMD5Hash(string input)
{
// step 1, calculate MD5 hash from input
MD5 md5 = System.Security.Cryptography.MD5.Create();
byte[] inputBytes = System.Text.Encoding.ASCII.GetBytes(input);
byte[] hash = md5.ComputeHash(inputBytes);
return BitConverter.ToInt64(hash, 0);
}
Isn't an MD5 hash standard? Can't you use a standard MD5 C# implementation? What about using the code in here?
Related
There is the function for sha256 computing:
static string GetHash(string input)
{
byte[] bytes = Encoding.UTF8.GetBytes(input); //1
SHA256 SHA256 = SHA256Managed.Create();
byte[] hashBytes = SHA256.ComputeHash(bytes); //2
var output = BitConverter.ToString(hashBytes); //3
return output;
}
It gets utf8-bytes from c# string, next it computes hash and returns one as string.
I'am confusing about BitConverter. Its ToString(byte[]) method depends on machine architecture (liitle/big endian). My purpose is providing specific endianess (big-endian) for output string.
How can I do it?
I think it can be like:
byte[] bytes = Encoding.UTF8.GetBytes(input); //1
if (BitConverter.IsLittleEndian)
{
Array.Reverse(bytes)
}
//..
But I dont' know how UTF8.GetBytes works (UTF8.GetBytes docs doesn't contains anything about endianness). Is it depending on endianness also? If so I suppose it is right way to reverse array after 1 step, is it?
I think it doesn't matter here because UTF-8 is byte oriented as stated here :
Isn’t on big endian machines UTF-8's byte order different than on little endian machines? So why then doesn’t UTF-8 require a BOM?
I need to send a request from PHP to a C# WEB API.
As part of the authentication it requires an MD5 hash of an empty byte array.
How can I generate an MD5 hash of an empty byte array on PHP?
I would do it like this in C#.
byte[] Content = new byte[0];
using (var md5 = MD5.Create())
{
return md5.ComputeHash(content);
}
You can do it in many way:
$hash = md5(null, true);
// or
$hash = md5('', true);
// or
$hash = md5(false, true);
https://superuser.com/questions/557925/how-can-zero-byte-files-generate-a-hash-value
If you can't compute it in PHP, then just use a constant and, for empty array, use that hash value.
I need to encrypt a guid and the encrypted string length should be 32 char max, not more than that. Please suggest me an encryption method available in C# for that.
I was using AES in CFB mode, as in Code Project, but that is producing 64 char long.
Well, a GUID is inherently 16 bytes of data... so that's what you should encrypt. That's a single block in AES. As per Reid's comment, the exact size of the output will depend on how you've configured things, but to convert the result into text, you'll probably want to use base64 if you need ASCII text with a fairly minimal size.
Base64 allows you to use 24 bytes to produce a 32 character result - so you should try different padding/cipher modes until you find one where the output is 24 bytes or less, if this 32 character requirement is a "hard" one (and you need ASCII; if you don't need ASCII then there's a lot more room to play...)
If a GUID is 16 bytes (I'll take that as a given) then you can simply do a single AES ECB mode encrypt without padding of the plaintext (i.e. the GUID). You can then convert to hexadecimals. That will with 100% certainty result in a 32 character result.
Note that ECB does not use an IV, which means that you can distinguish different GUID's from each other (as each GUID will be mapped to exactly one ciphertext). But the ciphertext should otherwise simply be identical to the security of the used block cipher and key.
public class EncryptGUI
{
private Aes aes;
public EncryptGUI (byte[] key)
{
aes = Aes.Create ();
aes.Mode = CipherMode.ECB;
aes.Padding = PaddingMode.None;
aes.Key = key;
}
public String encryptUID (byte[] guid)
{
ICryptoTransform aesDecryptor = aes.CreateDecryptor ();
byte[] result = aesDecryptor.TransformFinalBlock (guid, 0, guid.Length);
return ToHex (result);
}
public static string ToHex (byte[] data)
{
StringBuilder hex = new StringBuilder (data.Length * 2);
foreach (byte b in data)
hex.AppendFormat ("{0:x2}", b);
return hex.ToString ();
}
public static void Main (string[] args)
{
byte[] key = new byte[16];
EncryptGUI main = new EncryptGUI (key);
byte[] guid = new byte[16];
Console.Out.WriteLine (main.encryptUID (guid));
}
}
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
I have a function md5_encode
public string MD5_encode(string str_encode)
{
MD5 md5Hash = MD5.Create();
// Convert the input string to a byte array and compute the hash.
byte[] data = md5Hash.ComputeHash(Encoding.UTF8.GetBytes(str_encode));
// 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();
}
i can't decode it. I search in internet and found something like that
public static string Encrypt(string toEncrypt, bool useHashing)
{
byte[] keyArray;
byte[] toEncryptArray = UTF8Encoding.UTF8.GetBytes(toEncrypt);
System.Configuration.AppSettingsReader settingsReader = new AppSettingsReader();
// Get the key from config file
string key = (string)settingsReader.GetValue("SecurityKey", typeof(String));
//System.Windows.Forms.MessageBox.Show(key);
if (useHashing)
{
MD5CryptoServiceProvider hashmd5 = new MD5CryptoServiceProvider();
keyArray = hashmd5.ComputeHash(UTF8Encoding.UTF8.GetBytes(key));
hashmd5.Clear();
}
else
keyArray = UTF8Encoding.UTF8.GetBytes(key);
TripleDESCryptoServiceProvider tdes = new TripleDESCryptoServiceProvider();
tdes.Key = keyArray;
tdes.Mode = CipherMode.ECB;
tdes.Padding = PaddingMode.PKCS7;
ICryptoTransform cTransform = tdes.CreateEncryptor();
byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);
tdes.Clear();
return Convert.ToBase64String(resultArray, 0, resultArray.Length);
}
but i don't know that code work, Someone help me, decode function MD5_encode(string str_encode) or show me detail about different MD5_encode(string str_encode) and Encrypt(string toEncrypt, bool useHashing)
tks a lot for any help :)
MD5_encode uses MD5 (a cryptographic hash function) to generate a hash. The name is misleading as it isn't an encoding. A hash generate a value of a fixed size independent of the input, and cryptographic hash are especially designed not to be reversible.
Encrypt uses Triple DES to encrypt the input using as key either a value stored in the settings or the hash of this value.
You can decrypt the result of Encrypt using tdes.CreateDecryptor after removing the Base64 encoding.
PS: 3DES is old, you should use something more recent like AES
PS: ECB is insecure in a lot of cases, you should at least use CBC with a random IV.
Although MD5 is susceptible to a number of attacks that prove otherwise, MD5 is a hashing method. Hashes are designed to be one-way only. Just imagine if all of the hashing algorithms in the world today allowed anyone to easily get the original data from the hash data! Eeeeek!
I know very little about Encryption, but my goal is to essentially decrypt strings. I have been given the AES(128) key.
However, I must retrieve the IV from the Encrypted string, which is the first 16 bits.
Heres the doc for salesforce for more information (if what i explained was incorrect)
Encrypts the blob clearText using the specified algorithm and private
key. Use this method when you want Salesforce to generate the
initialization vector for you. It is stored as the first 128 bits (16
bytes) of the encrypted blob
http://www.salesforce.com/us/developer/docs/apexcode/Content/apex_classes_restful_crypto.htm (encryptWithManagedIV)
For Retrieving the IV I've tried something like this (I don't believe it's right though):
public string retrieveIv()
{
string iv = "";
string input = "bwZ6nKpBEsuAKM8lDTYH1Yl69KkHN1i3XehALbfgUqY=";
byte[] bytesToEncode = Encoding.UTF8.GetBytes(input);
for(int i = 0; i <= 15; i++){
iv += bytesToEncode[i].ToString(); ;
}
return iv;
}
(Just ignore the fact that the input is hardcoded and not parameterized; easier for testing purposes)
Then use the Best answer from this question to decrypt the string
The IV shouldn't be expressed as a string - it should be as a byte array, as per the AesManaged.IV property.
Also, using Encoding.UTF8 is almost certainly wrong. I suspect you want:
public static byte[] RetrieveIv(string encryptedBase64)
{
// We don't need to base64-decode everything... just 16 bytes-worth
encryptedBase64 = encryptedBase64.Substring(0, 24);
// This will be 18 bytes long (4 characters per 3 bytes)
byte[] encryptedBinary = Convert.FromBase64String(encryptedBase64);
byte[] iv = new byte[16];
Array.Copy(encryptedBinary, 0, iv, 0, 16);
return iv;
}