This question already has answers here:
convert password encryption from java to php
(4 answers)
Closed 7 years ago.
I have JAVA AES encryption logic
private static byte[] getMD5(String input) {
try {
byte[] bytesOfMessage = input.getBytes("UTF-8");
MessageDigest md = MessageDigest.getInstance("MD5");
return md.digest(bytesOfMessage);
} catch (Exception e) {
}
return null;
}
What will be the php equivalent of this function?
I have used md5($string) in php but the output is different in both the cases.
In the code that you have posted you get the byte array of the md5 hash. PHP's md5() function returns the md5 hash as a hex.
So, if you want to get the md5 hash as string in java you can like this:
private static String getMD5(String input) {
try {
byte[] bytesOfMessage = input.getBytes("UTF-8");
MessageDigest md = MessageDigest.getInstance("MD5");
// byte array of md5 hash
byte[] md5 = md.digest(bytesOfMessage);
// we convert bytes to hex as php's md5() would do
StringBuffer stringBuffer = new StringBuffer();
for (int i = 0; i < md5.length; i++) {
stringBuffer.append(Integer.toString((md5[i] & 0xff) + 0x100, 16).substring(1));
}
return stringBuffer.toString();
} catch (Exception e) {
}
return null;
}
From PHP you can get the row md5 binary by doing md5('some string', true). See md5() function documentation about it.
To get the byte array you can do unpack('c*', md5('some string',true)). See unpack() function and the possible formats for more info.
Related
My job is to rewrite a bunch of Java codes is C#.
This is the JAVA code:
public static String CreateMD5(String str) {
try {
byte[] digest = MessageDigest.getInstance("MD5").digest(str.getBytes("UTF-8"));
StringBuffer stringBuffer = new StringBuffer();
for (byte b : digest) {
// i can not understand here
stringBuffer.append(Integer.toHexString((b & 255) | 256).substring(1, 3));
}
return stringBuffer.toString();
} catch (UnsupportedEncodingException | NoSuchAlgorithmException unused) {
return null;
}
}
Ok.As you can see this code is trying to make MD5 hash.But the thing i can not understand is the part that i have shown.
I tried this code in C# to rewrite this JAVA code:
public static string CreateMD5(string input)
{
// Use input string to calculate MD5 hash
using (System.Security.Cryptography.MD5 md5 = System.Security.Cryptography.MD5.Create())
{
byte[] inputBytes = System.Text.Encoding.ASCII.GetBytes(input);
byte[] hashBytes = md5.ComputeHash(inputBytes);
// Convert the byte array to hexadecimal string
StringBuilder sb = new StringBuilder();
for (int i = 0; i < hashBytes.Length; i++)
{
sb.Append(hashBytes[i].ToString("X2"));
}
return sb.ToString();
}
}
Well both codes are making MD5 hash strings but the results are different.
There is a difference in encoding between the two code snippets you've shown - your Java code uses UTF-8, but your C# code uses ASCII. This will result in a different MD5 hash computation.
Change your C# code from:
byte[] inputBytes = System.Text.Encoding.ASCII.GetBytes(input);
to:
byte[] inputBytes = System.Text.Encoding.UTF8.GetBytes(input);
This should™ fix your problem, provided there are no other code conversion errors.
I use this code in PHP to encrypt the password:
return sha1("kD0a1".md5("xA4".$password)."f4A");
Does anyone know an effective replacement for use in Android? I tried different functions for MD5 and SHA1 but in Java it always generates a different HASH than in PHP.
For example, as follows:
public static String passwordHash(String password) {
return sha1("kD0a1"+md5("xA4"+password)+"f4A");
}
public static String md5(String s) {
try {
MessageDigest digest = java.security.MessageDigest.getInstance("MD5");
digest.update(s.getBytes());
byte messageDigest[] = digest.digest();
StringBuffer hexString = new StringBuffer();
for (int i=0; i<messageDigest.length; i++)
hexString.append(Integer.toHexString(0xFF & messageDigest[i]));
return hexString.toString();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return "";
}
public static String sha1(String clearString) {
try {
MessageDigest messageDigest = MessageDigest.getInstance("SHA-1");
messageDigest.update(clearString.getBytes("UTF-8"));
byte[] bytes = messageDigest.digest();
StringBuilder buffer = new StringBuilder();
for (byte b : bytes) {
buffer.append(Integer.toString((b & 0xff) + 0x100, 16).substring(1));
}
return buffer.toString();
}
catch (Exception ignored) {
ignored.printStackTrace();
return null;
}
}
However, PHP and Java will return a different HASH string to me.
PASS: test
PHP: 17bf2c08f4b9447cf8316736e13833316d3edc23
JAVA: 8434696e252b89af0db033eb255c88a91a42ce14
However, if I enter "passTest" for example, it will generate a hash correctly
PASS: passTest
PHP: db4aedf1d4072b7b645996394aa74743f14eeb7a
JAVA: db4aedf1d4072b7b645996394aa74743f14eeb7a
And "passwordTest" is wrong again.
PASS: passwordTest
PHP: 1ad47c24d556187f1de5db66ff623bbe08a27f33
JAVA: 0f058b3aea48e69c028a7ee2693a98d6074b10a8
I can't explain that sometimes it works and sometimes it doesn't, and at the same time it just changes the String for the password.
Do you think there could be a problem with coding or something? I thought TextView did it, but even if I enter a String outside of TextView, it behaves the same way.
Thank you in advance for any advice.
I would add that I am testing on SDK 31
M.
following code may help you to achieve what you want, it's a method named hashing and salt password, furthermore, the salt method prevents the collision of passwords that have been registered on your database
public static String hashPassword(String password) throws NoSuchAlgorithmException {
MessageDigest md = MessageDigest.getInstance("SHA-512");
md.reset();
md.update(password.getBytes());
byte[] mdArray = md.digest();
StringBuilder sb = new StringBuilder(mdArray.length * 2);
for(byte b : mdArray) {
int v = b & 0xff;
if(v < 16)
sb.append('0');
sb.append(Integer.toHexString(v));
}
return sb.toString();
}
here is the salt method
public static String getSalt() throws NoSuchAlgorithmException {
SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
byte[] salt = new byte[32];
sr.nextBytes(salt);
return Base64.getEncoder().encodeToString(salt);
}
for further reading about different hashing&salting password, consult the below link, it might help you to solid your understands
https://howtodoinjava.com/java/java-security/how-to-generate-secure-password-hash-md5-sha-pbkdf2-bcrypt-examples/
NB: you should use a strong implementation to hash your password to prevent cracking
private String getString(byte[] bytes)
{
StringBuffer sb = new StringBuffer();
for (int i = 0; i < bytes.length; i++)
{
byte b = bytes[i];
sb.append(0xFF & b);
}
return sb.toString();
}
public String encrypt(String source)
{
try
{
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] bytes = md.digest(source.getBytes());
return getString(bytes);
}
catch (Exception e)
{
e.printStackTrace(); }
return null;
}
If my text = "test"
The First Part toString()) produces a value of "Encryption$2#6966b26b"
And the second part then gets that and produces a value of "91431072057033211115202222781313839180246"
But why is the md5 a number and not 31f521a06d5060d1f38159c74a1f7cf2 or something similar?
The function "encrypt()" returns a MD5 hash. You should rename it to "hash", because hashing != encrypting.
If you want to encrypt a string, you can look here: https://gist.github.com/bricef/2436364
It's clearly stated in code yuou are using MD5 hashing algorithm
Now your question is why:
But why is the md5 a number and not 31f521a06d5060d1f38159c74a1f7cf2 or something similar?
your answer is simple, look at code which generates you string from your byte array.
byte b = bytes[i];
sb.append(0xFF & b);
you take byte, ie 0x20 then you perform logical and operation with integer 0x255 and then you add decimal representation of result yo your StringBuilder.
What you want to do is more like
sb.append(Integer.toHexString(0xff&b));
I would say MD5 hash, because the code says MessageDigest.getInstance("MD5") :D
This is the code used in c#
public static string Encode_SHA512(string input) {
try {
using (SHA512 sha = SHA512.Create()) {
byte[] hash = sha.ComputeHash(Encoding.Unicode.GetBytes(input));
return Convert.ToBase64String(hash);
}
} catch (Exception ex) {
throw new Exception("Error al generar hash SHA512", ex);
}
}
And this is the code used in java (One of many attempts)
public static String Encode_SHA512(String input) {
MessageDigest md = MessageDigest.getInstance("SHA-512");
byte[] digest = md.digest(input.getBytes("UTF-16LE"));
return String.format("%0128x", new BigInteger(1, digest));
}
But always the result is different. How can I use the same encryption of the C # code in java?
The problem is in your Java version you are not converting to a base64 encoded string correctly. If you update your Java code to the following then they both produce the same hash:
public static String Encode_SHA512(String input) throws NoSuchAlgorithmException, UnsupportedEncodingException {
MessageDigest md = MessageDigest.getInstance("SHA-512");
byte [] inputBytes = input.getBytes("UTF-16LE");
byte[] digest = md.digest(inputBytes);
return Base64.getEncoder().encodeToString(digest);
}
The line return String.format("%0128x", new BigInteger(1, digest)); is replaced with return Base64.getEncoder().encodeToString(digest); which currently base 64 encodes the resultant hash. Perhaps why the code was confusing is that the byte[] produced by the digest method looked different as in Java the byte type is twos complement (which is signed) so -128 to + 127 whereas in C# it is unsigned so 0 to 255 hence in the debugger any byte with starting with a 1 would look different as it would appear negative in Java but positive in C#.
I have a SQL table with usernames and passwords. The passwords are encoded using MessageDigest's digest() method. If I encode a password - let's say "abcdef12" - with MessageDigest's digest() method and then convert it to hexadecimal values, the String is different than if I do the same using PHP's SHA1-method. I'd expect these values to be exactly the same though.
Code that is used to encode the passwords:
MessageDigest md = MessageDigest.getInstance("SHA-1");
byte[] passbyte;
passbyte = "abcdef12".getBytes("UTF-8");
passbyte = md.digest(passbyte);
The conversion of the String to hexadecimal is done using this method:
public static String convertStringToHex(String str) {
char[] chars = str.toCharArray();
StringBuffer hex = new StringBuffer();
for (int i = 0; i < chars.length; i++) {
hex.append(Integer.toHexString((int) chars[i]));
}
return hex.toString();
}
Password: abcdef12
Here's the password as returned by a lot of SHA1-hash online generators and PHP SHA1()-function: d253e3bd69ce1e7ce6074345fd5faa1a3c2e89ef
Here's the password as encoded by MessageDigest: d253e3bd69ce1e7ce674345fd5faa1a3c2e2030ef
Am I forgetting something?
Igor.
Edit: I've found someone with a similar problem: C# SHA-1 vs. PHP SHA-1...Different Results? . The solution was to change encodings.. but I can't change encodings on the server-side since the passwords in that SQL-table are not created by my application.
I use client-side SHA1-encoding using a JavaScript SHA1-class (more precisely: a Google Web Toolkit-class). It works and encodes the string as expected, but apparently using ASCII characters?..
I have the same digest as PHP with my Java SHA-1 hashing function:
public static String computeSha1OfString(final String message)
throws UnsupportedOperationException, NullPointerException {
try {
return computeSha1OfByteArray(message.getBytes(("UTF-8")));
} catch (UnsupportedEncodingException ex) {
throw new UnsupportedOperationException(ex);
}
}
private static String computeSha1OfByteArray(final byte[] message)
throws UnsupportedOperationException {
try {
MessageDigest md = MessageDigest.getInstance("SHA-1");
md.update(message);
byte[] res = md.digest();
return toHexString(res);
} catch (NoSuchAlgorithmException ex) {
throw new UnsupportedOperationException(ex);
}
}
I've added to my unit tests:
String sha1Hash = StringHelper.computeSha1OfString("abcdef12");
assertEquals("d253e3bd69ce1e7ce6074345fd5faa1a3c2e89ef", sha1Hash);
Full source code for the class is on github.
Try this - it is working for me:
MessageDigest md = MessageDigest.getInstance(algorithm);
md.update(original.getBytes());
byte[] digest = md.digest();
StringBuffer sb = new StringBuffer();
for (byte b : digest) {
sb.append(Integer.toString((b & 0xff) + 0x100, 16).substring(1));
}
return sb.toString();
Regards,
Konki
It has nothing to do with the encodings. The output would be entirely different.
For starters, your function convertStringToHex() doesn't output leading zeros, that is, 07 becomes just 7.
The rest (changing 89 to 2030) is also likely to have something to do with that function. Try looking at the value of passbyte after passbyte = md.digest(passbyte);.
Or try this:
MessageDigest md = MessageDigest.getInstance("SHA-1");
md.update(clearPassword.getBytes("UTF-8"));
return new BigInteger(1 ,md.digest()).toString(16));
Cheers Roy