How to hash file (MD5, SHA..v.v..) in UWP - c#

I'm coding an Universal App, how can I hash a file with md5 or SHA algorithm ?
I searched, found this: system.security.cryptography, but it's not available in my project.
I'm using Visual Studio 2015.

In UWP, it is Windows.Security.Cryptography namespace and Windows.Security.Cryptography.Core namespace.
In the CryptographicBuffer class there is sample showing how to use this class.
Here is my demo about getting MD5 hash:
private string strAlgNameUsed;
public string GetMD5Hash(String strMsg)
{
string strAlgName = HashAlgorithmNames.Md5;
IBuffer buffUtf8Msg = CryptographicBuffer.ConvertStringToBinary(strMsg, BinaryStringEncoding.Utf8);
HashAlgorithmProvider objAlgProv = HashAlgorithmProvider.OpenAlgorithm(strAlgName);
strAlgNameUsed = objAlgProv.AlgorithmName;
IBuffer buffHash = objAlgProv.HashData(buffUtf8Msg);
if (buffHash.Length != objAlgProv.HashLength)
{
throw new Exception("There was an error creating the hash");
}
string hex = CryptographicBuffer.EncodeToHexString(buffHash);
return hex;
}

I'm going to throw this in, just because it is UWP... and if you use storageFolder.GetFileAsync to get to the file, the method will have to return an Async Task or a void. Forgive me if this isn't perfect, I'm more familiar with asp.net. But this does return a valid MD5 Hash on a file that was created in the LocalState folder:
private async Task<string> GetMD5Hash()
{
StorageFolder localFolder = ApplicationData.Current.LocalFolder;
var storageFolder = localFolder; // await KnownFolders.GetFolderForUserAsync(null, KnownFolderId.PicturesLibrary);
var file = await storageFolder.GetFileAsync("signature.png");
byte[] computedHash = new MD5CryptoServiceProvider().ComputeHash(File.ReadAllBytes(file.Path));
var sBuilder = new StringBuilder();
foreach (byte b in computedHash)
{
sBuilder.Append(b.ToString("x2").ToLower());
}
string result = sBuilder.ToString();
return result;
}

Related

Verify string signed with private key in iOS with C# code

I am working on a bluetooth based application where I create a string in Swift and sign it with RSA private key. The string is sent to a WPF app via bluetooth. The wpf app already has its public key. I want to verify the string the in WPF app. But I am not able to do it. I am getting error for algorithm type.
Following is my Swift code:
func signWithPrivateKey(textToEncrypt: String) -> Data? {
guard let privateKey: SecKey = privateKey else {
return nil
}
let algorithm: SecKeyAlgorithm = .rsaSignatureMessagePSSSHA512
guard SecKeyIsAlgorithmSupported(privateKey, .sign, algorithm) else {
return nil
}
var error: Unmanaged<CFError>?
let data = textToEncrypt.data(using: .utf8)!
guard let signature = SecKeyCreateSignature(privateKey,
algorithm,
data as CFData,
&error) as Data? else {
return nil
}
return signature
}
C# code to verify the string:
var deferral = args.GetDeferral();
var request = await args.GetRequestAsync();
var reader = DataReader.FromBuffer(request.Value);
byte[] fileContent = new byte[reader.UnconsumedBufferLength];
reader.ReadBytes(fileContent);
string text = Encoding.UTF8.GetString(fileContent, 0, fileContent.Length);
Debug.WriteLine(Convert.ToBase64String(fileContent));
String EncryptedMessage = Convert.ToBase64String(fileContent);
Debug.WriteLine(text);
using (var rsa = new RSACryptoServiceProvider())
{
var encoder = new UTF8Encoding();
byte[] bytesToVerify = encoder.GetBytes("Guten Morgan");
//byte[] signedBytes = Convert.FromBase64String(text);
try
{
bool success = rsa.VerifyData(bytesToVerify, CryptoConfig.MapNameToOID("SHA-512"), fileContent);
Debug.WriteLine(success);
}catch (CryptographicException e)
{
Debug.WriteLine(e.Message);
}
}
Getting following error:
System.ArgumentNullException: 'Value cannot be null. (Parameter 'hashAlg')'
I have mentioned the algorithm type as rsaSignatureMessagePSSSHA512 in Swift app and trying to verify it with SHA-512 but getting error.
Can someone please help me how to verify the signature in C#.
Edit:
I have modified the WPF code as following and it is not crashing now, but I am still not able to verify it
Credential credential = CredentialManager.ReadCredential("CredentialManagerTests");
String publicKey = credential.Password;
Debug.WriteLine(publicKey);
var deferral = args.GetDeferral();
var request = await args.GetRequestAsync();
var reader = DataReader.FromBuffer(request.Value);
byte[] fileContent = new byte[reader.UnconsumedBufferLength];
reader.ReadBytes(fileContent);
string text = Encoding.UTF8.GetString(fileContent, 0, fileContent.Length);
Debug.WriteLine(Convert.ToBase64String(fileContent));
byte[] privateKeyPkcs1DER = ConvertPKCS1PemToDer(publicKey);
using (var rsa = new RSACryptoServiceProvider())
{
var encoder = new UTF8Encoding();
byte[] bytesToVerify = encoder.GetBytes("Guten Morgan");
rsa.ImportRSAPublicKey(privateKeyPkcs1DER, out _);
try
{
bool success = rsa.VerifyData(bytesToVerify, fileContent, HashAlgorithmName.SHA512, RSASignaturePadding.Pkcs1);
Debug.WriteLine(success);
}
catch (CryptographicException e)
{
Debug.WriteLine(e.Message);
}
}
Edit2:
String to sent: "Guten Morgan"
Signature: "G8ePlCyPeivAHPygMHXeCTszTy9EV4y6Gsku9GQJV71t+M7ATFZjxkh9u0DVjR0ei76a4dixzgXKLZLQNy/mxwrvUvolPHE0HUFAErkzfeHcrB8/QlHlEoEdt9vf34L8KNy6yVOHWC2sytgvw009EsKUr3LYb8kSkCeaCVEEEAwAELt3z/YzfnbwR0GXatlNpmaoLOXh0mEep8Xh5AHf6RhbgS0VBFSXSbz3ALbwu5DtlaIv4P1nFOP80w2NBs7HrHOMdR0PKdgiD+suErCYWKINzToKDsdO8XNaKdw3jekYBRXl6GNfAwQeADCq0MDsvptCRVZ//fzU2fXRcaYsRA=="
Algo: SHA512
**Public Key: **
MIIBCgKCAQEA4lS13W+TXZhUXy5yB2NpeulCVb1ZSaReopeKrahjKmUx4NQxVXruEYCY3LpjZcSy8xiudVG3GBIMnPLtaMbc5WAYDj1M2OwnpNHdQ8SKtZ1tdA6iRjfOXGUa1n8FMIMKU5ynTSAiSoh+8gGrY0L6jTsCSdLO5ZU53LQFHSESM8JuBeNZozolb/cKb38ylercVeVpo8egoA8UqHezK23VUJ23faxMmMZDJxVn5pfFedxBTLxwU65KQY8Z4izaFjuPLoGe5JZkXyYNMcrYloDCBG5m9BFiXVkoLEDmGFGfWLMJcqL+D2CszqJ4h712ZR6LYRNtIbo/HG9KR7XCtap3QwIDAQAB.
Private Key:
MIIEowIBAAKCAQEAuAoCUOejL7EBI0P4nfZQkAr8/a37SR/umJB5sUOyy2IyaWuSX1tBOco4XThTkCYj2ubgbf0fGsQ7FRgF6bwbeynhDYS7ptPkvUHF4BaSUsu2KtKkoslvl67M83ESKtOSm0s0CImw60MDlPDr/1SPhkYgSfoQ81CXytrZPkWtB/YekT2ph3PRqyOeMNl0O88Clt2mdR4dZeZWv6WGaaoP1kr8RY9iB6hrg2RdOFXixIOdo7cP3+3w9s4svnIX7RNLIIrUxJHQUYA0oxkiZ9y0peWR5mElywjkg/AFm8RxZsXjHowrqlYGkFKzPTq2/dhwId0Yit95aYVIDE5Dj9n3nQIDAQABAoIBAAFiDd9mxjqrBVuq/JjPS46xjnInlw5XH5dk6o0y+Yp+u+s/5DM0P9q70s2ciUA5kSZpesFI2C1+0QTZD95QTBKSX38XAsP/rqXfcym6cbIOltleiN8yTVTh+udPb7gDrAPfvk3cHwi9ka7SWquqCoQTTdXQe8UgU2uyVlSZ+HFpXFE55ltp4CbnFBH39Sa8pqbpwIwb2+PCFkx7xVUIJ2t1vJd2yBUjEBFJv0SiUy9DWwbXiyoqtZXtVft8Vm7xhimSDN2o6KcnXYEq2eb3UhOKI09tRsYLA3bF66bvVxvcnykuUpLHFOxhBKfD8Vsh+SWHdv6zT52gkF7KDUxDYLECgYEA25iGkCcYx+cfzIdVmIbqa662IzkgUlCdpX37tBNHjyE+72Ehw6odZ0e3iTewm/vYBI6hyCW+T/G6ksl2enjOxBH0DhaQEYLqhSGq63/XOsFsmW7tH4YmInURv4RL4KEIB8HNGLfhllJt92KsrBNzei+SjdtElQhULhw4Mle6PWUCgYEA1ox8DxPTE8HQ5Jw+7D0ut+FyYkysciMSFYpmFX5qlbMlfl0WRL4mVFv/tOBerahsCDdaaOKJKafQVbJIU8G9U0m8PAttcM4OMjexwHzT0EBdf9cNACAXQP/arJEbf8YkPr7/IwI6YGiMFzDKRqcrYMNzl9rZXQEyJGj6u4x/6dkCgYBYIWiv5eD+KXYLoazqoAro2J9kl4KvRodeaadg5/PqL4+Qhs0EN/vA/XldaqpIj9RsT8oCB5PPhdY5Hv2bvWxOKF5oYQnE3WO9tntgNFhuzj4Ffg1Qf4hCf/V1hWTma/pLEq57YyD4MXDMvh9KmCvaN8l7gSqPHV6betva6HZoOQKBgQCwZMxSsR/nrIAMlRF+tUbF08txWkylgoQJxcHshgUnkySOYgY++n8U+JahpZ7x8/juQGRKu4W+A8Tb0Dp68lywL31deJ/AEQnG69duxLJ5E5JL2wlLQxcbT8AABUWwpb2DARFPPTO1s/8JyglkUWjuo4NUJJB1UNhi6xTKQdeg8QKBgESvEWQKqvk3YCpVwCNv5C+1aAVS6Fq/sGmLlVsbQ5W6EENYDg4pq2fgghH9lcRb1BdHjFm25ikADbGWgBOG1fvrD9KsR9RY98x8XM3EQ5EJ2Y2vjQfWBA2da8nr9ETRzY00IjHCzb5AhISWIit7Itaa9H202v1zZCIUY+O/YGGX
Edit3:
My below method was wrong:
private byte[] ConvertPKCS1PemToDer(string pemContents)
{
return Convert.FromBase64String(pemContents
.TrimStart("-----BEGIN PUBLIC KEY-----".ToCharArray())
.TrimEnd("-----END PUBLIC KEY-----".ToCharArray())
.Replace("\r\n", ""));
}
Instead of BEGIN PUBLIC KEY it was BEGIN PRIVATE KEY.
I have fixed it as mentioned above but getting following error on Convert line in above function:
System.FormatException: 'The input is not a valid Base-64 string as it contains a non-base 64 character, more than two padding characters, or an illegal character among the padding characters.'
Edit4:
I have now created a new project only to test my code and have added following code:
Private key for reference:
"MIIEogIBAAKCAQEArMO9cJHbKYKkozTtqPI9fhecyiibJrvsv5KLLPlQcIi0uo6yfLD4MUFS5UbwaGATnCrLRKr27iQLWwWKxsJdEQMZDMF6EiCQSXEB2AmSEPW4NOh5kbj05cJoDrvSeac3lllsjPlOaVQSrgmiOFoJ1t98utfOJ6FCzam9DZZR7r/OwTZ0754rAp4dqwkamcTaSkW2zQhr++mw4WZZiKGJCPYKKXguGJbRTtr+dcZ4JwrvdYudCguuCVfa+1D6k0NswWEu58DELZ0XPuLu8qFiIA9MI5K/ECHXwozi8UxmDhG9NJuh+uRZZ4s7LVnkNDN8np6vhuwKNL5rP0msUciItwIDAQABAoIBAAgEaSZoyepbD2fVC3TMPB/2df9dpSUbSxrixhto541UBIPtVzQVkoi6ne2uqMu3LpAB3mKfcYvAkJDImqrkQc/tWNHbG4lCXtGIxrZoMtjKFJQ824/UAknQzpCeP7UjpHRYapEb+qW2/JJDU9oDRd2B4S+FZXdVAPJXjPutCy40IziykyhU9Fu0fwCN/ry764EyI4gtN/WgDHwc2C8B7sriW81KtB8vJW10waoot3MRBfXxxhk3wyiNputBg1KDz+O2+iUrO4p1OKdvL9S9u65MN9Klm+i03aexNrjbMHu/lxDUa6buSgfXh5+Na6PLHur/3aCqfZdpJ/OO7AxarqECgYEA4884gGubJmiq8OayGdpnaZa4L/2NEwOEnN2G09ySXuUhIyOzOJmeiw3R0BTOB0ZRzrk/Ozq3/T2z1ScUGr3a7hmgGBm3azNjJCbYZ51/XJPE7B5UhDFejZPGRT8vVnUzjYah4Eipp4hSIe79Ja17vTFTtY7bGGl11a6VaPvHuCECgYEAwiTAs60JqUIFw8qmBzWwIHybbKSS0Pc8AWdMYLVSnqiQKZVDnyypUDv14+VEMbCdW21ShMCrNK0QTWnqkV7ln91jxPNvQbSoLBTXgpxbvoxg57jg6sdtiUuPjdBBc74kV9oW1zX2saLvPOO4fjUw3z1b+6/v1SjRlhIqtQrsRdcCgYBeDgYz7zmFaB17jKPnzKZ5j8LH/ZUrTn6IDWZHPoAoMc22plyud65flvsTQCO4GS5ZfV4/5ARmx/zhelrwl4Y2W9ofWS7DUdoS6P7b+MjGvjPFkNgwI/n31hU8LdQrjAQW4IkhAp8ZDk1quTNHRRMbj6wR/8MxlwkRih0h1SImQQKBgGnuQdMH9ICNDLYzKXo/mhVvyCJ0fcNVU0F0yqDt7uGxGdAGqLn+VXf474bkvtvaAVI0iVT0B7abQ4zp4NpnDCW5V8nMBgW0/BnpWVnj1M9YqztkjhysqiDCwNZhLoVn1060KchNooh0XdM8cZszjLISOdFPwy3ssscOrIzSI+9LAoGAMDcGC5P9gVBCNd8ox5OlozNwAmHmHwpqFJcOxNx4lCE5DkT+6DEscoLMZ4LkNVzMHb0LmyhDnF24eIn/v7FRb6ZF5YzlpIdQC2tvXaJoyPwLPee7XGGr9IRkupbrNzPWVhTUYK9kJvI7SWPF2DBFK8fiC5S96USVp++kOjp/faE="
String publicKey = "MIIBCgKCAQEArMO9cJHbKYKkozTtqPI9fhecyiibJrvsv5KLLPlQcIi0uo6yfLD4MUFS5UbwaGATnCrLRKr27iQLWwWKxsJdEQMZDMF6EiCQSXEB2AmSEPW4NOh5kbj05cJoDrvSeac3lllsjPlOaVQSrgmiOFoJ1t98utfOJ6FCzam9DZZR7r/OwTZ0754rAp4dqwkamcTaSkW2zQhr++mw4WZZiKGJCPYKKXguGJbRTtr+dcZ4JwrvdYudCguuCVfa+1D6k0NswWEu58DELZ0XPuLu8qFiIA9MI5K/ECHXwozi8UxmDhG9NJuh+uRZZ4s7LVnkNDN8np6vhuwKNL5rP0msUciItwIDAQAB";
String signature = "ntGm9Vx38l26ZSEitc1L+G6YZw3Dt4dmXoQQUjSAcKD1d4bFm8QI6CIncTBQ0+rGWUh7fr2DWQBB1OPgoZRoDs23SGvl+KTqUBo6Ym+kIK4KXwBrMt3YXNFpXuXVk36+4+oBPFhcMAwG4fIG5MnMEHqv/F+NNA71a10irB0frMpwpU/FZDGEbCnvOxGe6qIUsYt/dMbf1UT1AjKqQA0EmNqvIsU5DuHcpScb5xuV8aPJg6vPPKafLa8LbBiCA4dyxUcUYSjSaTQ6D9YoZ3Ich/dRBCyIdw9vESBSrOUGvwOmNl+5X+r2UyFN8RgYwW61M3iYdmkwJYYVUbMA69vCOA==";
byte[] signatureBytes = Encoding.UTF8.GetBytes(signature);
using (var rsa = new RSACryptoServiceProvider())
{
rsa.ImportRSAPublicKey(Convert.FromBase64String(publicKey), out _);
var encoder = new UTF8Encoding();
byte[] bytesToVerify = encoder.GetBytes("Guten Morgen");
try
{
bool success = rsa.VerifyData(bytesToVerify, CryptoConfig.MapNameToOID("SHA512"), signatureBytes);
Debug.WriteLine(success);
}
catch (CryptographicException e)
{
Debug.WriteLine(e.Message);
}
}
But success variable is still false.

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);
}
}

How to get SHA1 and MD5 checksum from HttpPostedFileBase file.InputStream

I want to get the checksum of uploaded file in MVC.
Currently I am doing this
public ActionResult Index(HttpPostedFileBase file, string path)
{
if (file != null)
{
string checksumMd5 = HashGenerator.GetChecksum(file.InputStream, HashGenerator.MD5);;
string checksumSha1 = HashGenerator.GetChecksum(file.InputStream, HashGenerator.SHA1);
//other logic follows....
}
but when I do following in Console app and read file from File path then,
string path = #"C:\Users\anandv4\Desktop\Manifest-5977-681-673.txt";
var md5hash = HashGenerator.GetChecksum(path, HashGenerator.MD5);
var sha1 = HashGenerator.GetChecksum(path, HashGenerator.SHA1);
the values of both are different.
Code for generating hash :
public static string GetChecksum(string fileName, HashAlgorithm algorithm)
{
using (var stream = new BufferedStream(File.OpenRead(fileName), 1000000))
{
return BitConverter.ToString(algorithm.ComputeHash(stream)).Replace("-", string.Empty);
}
}
public static string GetChecksum(Stream stream, HashAlgorithm algorithm)
{
using (stream)
{
return BitConverter.ToString(algorithm.ComputeHash(stream)).Replace("-", string.Empty);
}
}
Can anyone explain me what is the difference between the two. Utlimately both the methods resolve to Stream in GetChecksum method
If you are hashing a stream, you need to set the current position of the stream to 0 before computing the hash.
file.InputStream.Seek(0, SeekOrigin.Begin);
For me, this is a great place for an extension method, eg.:
//compute hash using extension method:
string checksumMd5 = file.InputStream.GetMD5hash();
Which is supported by the class:
using System;
using System.IO;
public static class Extension_Methods
{
public static string GetMD5hash(this Stream stream)
{
stream.Seek(0, SeekOrigin.Begin);
using (var md5Instance = System.Security.Cryptography.MD5.Create())
{
var hashResult = md5Instance.ComputeHash(stream);
stream.Seek(0, SeekOrigin.Begin);
return BitConverter.ToString(hashResult).Replace("-", "").ToLowerInvariant();
}
}
}

C# execute method on other thread

i have a method that read some files and get hashes SHA1Managed and then compare it with other hashes from a list, how can i do this method on other thread?
public bool CheckFile(string file, string filehash)
{
if (File.Exists(file))
{
using (FileStream stream = File.OpenRead(file))
{
SHA1Managed sha = new SHA1Managed();
byte[] checksum = sha.ComputeHash(stream);
string sendCheckSum = BitConverter.ToString(checksum)
.Replace("-", string.Empty);
return sendCheckSum.ToLower() == filehash;
}
}
else return false;
}
If you just want to run it in a background thread you'd actually need to move the task creation up one level since your function returns a result. Depending on how the calling code works something like this might work for you.
var backgroundTask = Task.Factory.StartNew(() =>
{
var result = CheckFile("file", "filehash");
//do something with the result
});
Try by this codes:
public async Task<bool> CheckFile(string file, string filehash)
{
await Task.Run<bool>(()=> {
if (File.Exists(file))
{
using (FileStream stream = File.OpenRead(file))
{
SHA1Managed sha = new SHA1Managed();
byte[] checksum = sha.ComputeHash(stream);
string sendCheckSum = BitConverter.ToString(checksum)
.Replace("-", string.Empty);
return sendCheckSum.ToLower() == filehash;
}
}
else return false;
});
}

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