I am doing md-5 hashing in both android and c# at the same time. But both the results should be the same for the same inputs. Is there any difference in the way its done in both the languages?
I get different outputs in both the cases. Here is the c# code for md-5 calculation:
//this method hashes the values sent to it using MD5
public static String hashwithmd5(String toHashMD5)
{
byte[] keyArray;
MD5CryptoServiceProvider hashmd5 = new MD5CryptoServiceProvider();
keyArray = hashmd5.ComputeHash(UTF8Encoding.UTF8.GetBytes(toHashMD5));
hashmd5.Clear();
return Convert.ToBase64String(keyArray, 0, keyArray.Length);
}
and here is the code for md5 in android using bouncycastle
public byte[] Hashing(String toHash) throws Exception{
byte[] hashBytes = toHash.getBytes("UTF-8");
EditText et = (EditText) findViewById(R.id.entry);
org.bouncycastle.crypto.digests.MD5Digest digest = new org.bouncycastle.crypto.digests.MD5Digest();
digest.reset();
digest.update(hashBytes, 0, hashBytes.length);
int length = digest.getDigestSize();
byte[] md5 = new byte[length];
digest.doFinal(md5, 0);
et.setText(md5.toString());
return md5;
}
the result of md5 in c# is :XUFAKrxLKna5cZ2REBfFkg==
the result of md5 in android is :[B#4053cf40
The C# code converts the hash to Base64, the java code does not. If you convert both raw hashes to e.g. hex strings, they'll be the same.
When you use this in Java:
byte[] md5 = new byte[length];
// ...
md5.toString()
you are not getting a representation of the byte values. You get the generic "string representation" of an object. Here, [B#4053cf40 basically means "array of bytes (that's for the '[B') which internally happens to be at address 4053cf40".
Use android.util.Base64 to convert your bytes to a Base64 encoded string.
#erik is correct. MD5 is no longer considered a "secure" hash; use SHA-256.
Erik is absolutely right. MD5 usage is near extinction, use any strong SHA
Related
My method AESEncrypt(string text) is returning a byte array.
If I encrypt a message, and use the returned byte array as an input for AESDecrypt(byte[] text), everything is working fine. The problem is, that I need to convert it to a string and vice versa, so I tried the following:
byte[] encrypted = enc.AESEncrypt("Testmessage");
string encryptedStr = Convert.ToBase64String(encrypted);
byte[] test = Convert.FromBase64String(encryptedStr);
Console.WriteLine((encrypted == test));
I also tried this with Encoding.ASCII.GetString(), Encoding.UTF8.GetString(),
but encrypted == test returns false everytime...
What method do I need to use to convert the AES byte[] to a string and vice versa?
This is the AESEncrypt method:
public byte[] AESEncrypt(string s)
{
byte[] encrypted;
using (AesManaged aes = new AesManaged()) {
ICryptoTransform encryptor = aes.CreateEncryptor(AESKey, AESIV);
using (MemoryStream ms = new MemoryStream()) {
using (CryptoStream cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write)) {
using (StreamWriter sw = new StreamWriter(cs)) {
sw.Write(s);
}
encrypted = ms.ToArray();
}
}
}
return encrypted;
}
An encrypted payload held in a byte array is not directly convertible to a string, or at least not without using an ANSI encoding and both sides (encoding and decoding) agreeing on the string's code page. And if you use any Unicode encoding (UTF-8, UTF-16, ...) you're bound to have bytes that contain invalid code points, so who can't be decoded to a character.
That's where base64 comes into play. This is a safe way to represent byte arrays as ASCII strings, a subset implemented by almost every (if not every) encoding. So using that base64 code is fine.
You'll simply want encrypted.SequenceEquals(test), as explained in Comparing two byte arrays in .NET.
The base64 is directly used for this.
here is an example:
Encode
public static string Base64Encode(string plainText)
{
var plainTextBytes = System.Text.Encoding.UTF8.GetBytes(plainText);
return System.Convert.ToBase64String(plainTextBytes);
}
Decode
public static string Base64Decode(string base64EncodedData)
{
var base64EncodedBytes = System.Convert.FromBase64String(base64EncodedData);
return System.Text.Encoding.UTF8.GetString(base64EncodedBytes);
}
Consider byte[] encrypted and byte[] test, when you test for equality with == by default the references are compared not their content. This explains, why you test encrypted == test fails.
You are also asking about how to convert byte[] into a string, which is not related to your encrypted == test test at all. In general you the various System.Text.Encoding.*.GetString(byteArray); preform the conversion but you need to know what encoding was used for the byteArray. This information has to be passed along separately, you might have a specification which says all byte arrays are encoded in UTF-8 or you might pass the encoding along together with the data but there exists no general answer.
So im trying to encrypt data using C# DES
have the following code
static public string Encrypt(string _dataToEncrypt) {
SymmetricAlgorithm algorithm = DES.Create();
ICryptoTransform transform = algorithm.CreateEncryptor(key, iv);
byte[] inputbuffer = Encoding.Unicode.GetBytes(_dataToEncrypt);
byte[] outputBuffer = transform.TransformFinalBlock(inputbuffer, 0, inputbuffer.Length);
return Convert.ToBase64String(outputBuffer);
}
static public string Decrypt(string _dataToDecrypt) {
SymmetricAlgorithm algorithm = DES.Create();
ICryptoTransform transform = algorithm.CreateDecryptor(key, iv);
byte[] inputbuffer = Convert.FromBase64String(_dataToDecrypt); // Here is the problem.
byte[] outputBuffer = transform.TransformFinalBlock(inputbuffer, 0, inputbuffer.Length);
return Encoding.Unicode.GetString(outputBuffer);
}
And im getting an error System.FormatException: 'Invalid length for a Base-64 char array or string.'
It works when string has an even number of characters.
Is it even real to encrypt/decrypt data with an odd number of characters ?
DES, as well as AES does not have limit on what can be encrypted, the problem is elsewhere.
It looks like it is a Bas64 encoding problem given the line the error occurs on.
Perhaps trailing "=" characters were stripped from the Base64.
Information:
DES is a block based encryption algorithm, as such the input must be an exact multiple of the block size, 8-bytes for DES. When the input is not always an exact multiple padding must be added, the easiest way to to let the implementation do that for you by specifying padding, generally PKCS#5 for DES.
For SymmetricAlgorithm use Padding Property PKCS7, it is always best to fully specify everything and not rely on defaults.
algorithm.Padding = PaddingMode.PKCS7;
I have a hashing method in C# that looks like:
MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider();
byte[] raw_input = Encoding.UTF32.GetBytes("hello");
byte[] raw_output = md5.ComputeHash(raw_input);
string output = "";
foreach (byte myByte in raw_output)
output += myByte.ToString("X2");
return output;
How can I implement this in PHP? Doing the following produces a different hash digest...
$output = hash('md5', 'hello');
PHP
This PHP code will do:
<?php
$str = "admin";
$strUtf32 = mb_convert_encoding($str, "UTF-32LE");
echo md5($strUtf32);
?>
This code outputs "1e3fcd02b1547f847cb7fc3add4484a5"
You need to find out which encoding PHP is using to convert your string to text. It's very unlikely that it's using UTF-32. It may well be using the platform default encoding, or possibly UTF-8.
using (MD5 md5 = MD5.Create())
{
byte[] input = Encoding.UTF8.GetBytes("hello");
byte[] hash = md5.ComputeHash(input);
return BitConverter.ToString(hash).Replace("-", "");
}
(This is the problem with languages/platforms which treat strings as binary data all over the place - it doesn't make it clear what's going on. There has to be a conversion to bytes here, as MD5 is defined for bytes, not Unicode characters. In the C# code you're doing it explicitly... in the PHP it's implicit and poorly documented.)
EDIT: If you've got to change the PHP, you could try this:
$text = mb_convert_encoding($text, "UTF-32LE");
$output = md5($text)
It depends whether PHP supports UTF-32 though...
When you apply md5 to Encoding.UTF32.GetBytes("admin");, that's same as
echo hash( "md5","a\0\0\0d\0\0\0m\0\0\0i\0\0\0n\0\0\0");
//1e3fcd02b1547f847cb7fc3add4484a5
In php.
You need to convert your string to UTF32-LE in PHP:
echo md5( mb_convert_encoding( "admin", "UTF-32LE" ) );
//1e3fcd02b1547f847cb7fc3add4484a5
In my Windows Phone application I need to get hash using SHA-1 Algorithm. How can I do this? For example I have string text="1234";
You would use the SHA1Managed class to compute the hash of a byte array. Probably do something like this:
var sha = new SHA1Managed();
var bytes = System.Text.Encoding.UTF8.GetBytes(text);
byte[] resultHash = sha.ComputeHash(bytes);
SHA1 sha = new SHA1CryptoServiceProvider();
byte[] result = sha.ComputeHash(System.Text.Encoding.UTF8.GetBytes(text));
You should use System.Security.Cryptography.SHA1Managed class.
I am trying to generate a Unix-Style password hash using MD5. I undestand that I need it to look like $1$<salt>$<hash>, but the <hash> part does not look the same, no matter what I do. Here is how I generate the hash:
MD5 md5 = System.Security.Cryptography.MD5.Create();
byte[] inputBytes = System.Text.Encoding.UTF8.GetBytes(pass);
byte[] hash = md5.ComputeHash(inputBytes);
StringBuilder sb = new StringBuilder();
for (int i = 0; i < hash.Length; i++)
{
sb.Append((char) hash[i]);
}
String calchash = sb.ToString();
I am pretty sure that it is now I am using the StringBuilder to make a string from the hashed bytes. But I don't know what the right settings would be.
Unix md5 crypt doesn't use plain md5. That would be insecure, because plain md5 is fast, and password hashes should be slow.
I found a relevant code-project article: http://www.codeproject.com/KB/recipes/Unix_md5crypt.aspx
It's about formatting. The Unix password hash is in hex format, while you're writing it down in binary. Replace the loop body with:
sb.Append(hash[i].ToString("x").PadLeft(2,'0'));
I think you should use hash[i].ToString("X") instead of just converting to char. Because hash bytes may be in any range from 0 to 255, which is not like md5 hash is looking.