I have tried to use java.security.MessageDigest or org.apache.commons.codec.digest.DigestUtils to do md5, but there comes out different results.
The sample code as below:
public static void main( String[] args )
{
System.out.println("MessageDigest: " + MD5("12345") );
MessageDigest md5Digest = DigestUtils.getMd5Digest();
System.out.println("MD5Hex with digest: " + DigestUtils.md5Hex(md5Digest.digest("12345".getBytes())));
System.out.println("MD5Hex: " + DigestUtils.md5Hex("12345"));
}
public final static String MD5(String s) {
char hexDigits[]={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
try {
byte[] btInput = s.getBytes();
// 獲得MD5摘要算法的 MessageDigest 對象
MessageDigest mdInst = MessageDigest.getInstance("MD5");
// 使用指定的字節更新摘要
mdInst.update(btInput);
// 獲得密文
byte[] md = mdInst.digest();
// 把密文轉換成十六進制的字符串形式
int j = md.length;
char str[] = new char[j * 2];
int k = 0;
for (int i = 0; i < j; i++) {
byte byte0 = md[i];
str[k++] = hexDigits[byte0 >>> 4 & 0xf];
str[k++] = hexDigits[byte0 & 0xf];
}
System.out.println();
return new String(str);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
The results as below:
MessageDigest: 827CCB0EEA8A706C4C34A16891F84E7B
MD5Hex with digest: aad43635bbd353cef6ea6546093fa0c7
MD5Hex: 827ccb0eea8a706c4c34a16891f84e7b
If I have give md5Digest.digest() into DigestUtils.md5Hex, the result is different from MessageDigest. But if I just do md5Hex(), it will be the same. What's the different between this two way?
Thanks
When you are calling DigestUtils.md5Hex(md5Digest.digest("12345".getBytes()))), you actually calculate the MD5 of the result of the previous MD5 calculation. Thus no wonder that double-MD5 differs from single MD5.
Related
I'm trying to hash data "text" to be transferred from Java Service to C# Service.
I'm using SHA256 as a Hashing algorithm, but despite the values and the salt being the same the result doesn't.
Here is my C# snippet
public string Sign(string textToHash, string salt){
byte[] convertedHash = new byte[salt.Length / 2];
for (int i = 0; i < salt.Length / 2; i++)
convertedHash[i] = (byte)int.Parse(salt.Substring(i * 2, 2), NumberStyles.HexNumber);
HMAC hasher = new HMACSHA256(convertedHash);
string hexHash = "";
using (hasher)
{
byte[] hashValue = hasher.ComputeHash(Encoding.UTF8.GetBytes(textToHash));
foreach (byte b in hashValue)
{
hexHash += b.ToString("X2");
}
}
return hexHash;
}
And, here is the Java snippet
public static String sign(String textToHash, String salt){
byte[] convertedHash = new byte[salt.length() / 2];
for (int i = 0; i < salt.length() / 2; i++)
{
convertedHash[i] = (byte)Integer.parseInt(salt.substring(i * 2, i * 2 + 2),16);
}
String hashedText = null;
try {
MessageDigest md = MessageDigest.getInstance("SHA-256");
md.update(convertedHash);
byte[] bytes = md.digest(textToHash.getBytes(StandardCharsets.UTF_8));
StringBuilder sb = new StringBuilder();
for (byte aByte : bytes) {
sb.append(Integer.toString((aByte & 0xff) + 0x100, 16).substring(1));
}
hashedText = sb.toString();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return hashedText;
}
In Java, I also tried
convertedHash = salt.getBytes();
But I got different results also.
Tests:
salt = ABCDEFG
text = hashme
Result in C#
70B38047C28FFEDCF7275C428E65310671CADB65F11A5C9A8CFBB3CF52112BA3
Result in Java
a8bc36606aade01591a1d12c8b3c87aca1fe55def79740def03a90b49f2c6b7c
So, any help about why the results aren't the same.
Thanks in advance.
To mimic the Java hashing, I used SHA256Managed rather than HMACSHA256 in C#
public static string Sign(string data, string salt)
{
UTF8Encoding encoder = new UTF8Encoding();
SHA256Managed sha256hasher = new SHA256Managed();
byte[] convertedHash = new byte[salt.Length / 2];
for (int i = 0; i < salt.Length / 2; i++)
convertedHash[i] = (byte)int.Parse(salt.Substring(i * 2, 2), NumberStyles.HexNumber);
byte[] dataBytes = encoder.GetBytes(data);
byte[] bytes = new byte[convertedHash.Length + dataBytes.Length];
Array.Copy(convertedHash, bytes, convertedHash.Length);
Array.Copy(dataBytes, 0, bytes, convertedHash.Length, dataBytes.Length);
byte[] hashedBytes = sha256hasher.ComputeHash(bytes);
return hashedBytes.Aggregate("", (current, t) => current + t.ToString("X2"));
}
HMACSHA256 is not a pure SHA-256.
I have the following Java code to generate hashes based on input text.
package main;
import java.util.Scanner;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public class String_Hash_Generator {
public static void main(String args[]) throws NoSuchAlgorithmException {
Scanner inputScanner = new Scanner(System.in);
System.out.print("Input: ");
String input = inputScanner.next();
/* MD2 */
MessageDigest objMD2 = MessageDigest.getInstance("MD2");
byte[] bytMD2 = objMD2.digest(input.getBytes());
BigInteger intNumMD2 = new BigInteger(1, bytMD2);
String hcMD2 = intNumMD2.toString(16);
while (hcMD2.length() < 32) {
hcMD2 = "0" + hcMD2;
}
/* MD5 */
MessageDigest objMD5 = MessageDigest.getInstance("MD5");
byte[] bytMD5 = objMD5.digest(input.getBytes());
BigInteger intNumMD5 = new BigInteger(1, bytMD5);
String hcMD5 = intNumMD5.toString(16);
while (hcMD5.length() < 32) {
hcMD5 = "0" + hcMD5;
}
/* SHA-1 */
MessageDigest objSHA1 = MessageDigest.getInstance("SHA-1");
byte[] bytSHA1 = objSHA1.digest(input.getBytes());
BigInteger intNumSHA1 = new BigInteger(1, bytSHA1);
String hcSHA1 = intNumSHA1.toString(16);
while (hcSHA1.length() < 40) {
hcSHA1 = "0" + hcSHA1;
}
/* SHA-256 */
MessageDigest objSHA256 = MessageDigest.getInstance("SHA-256");
byte[] bytSHA256 = objSHA256.digest(input.getBytes());
BigInteger intNumSHA256 = new BigInteger(1, bytSHA256);
String hcSHA256 = intNumSHA256.toString(16);
while (hcSHA256.length() < 64) {
hcSHA256 = "0" + hcSHA256;
}
/* SHA-384 */
MessageDigest objSHA384 = MessageDigest.getInstance("SHA-384");
byte[] bytSHA384 = objSHA384.digest(input.getBytes());
BigInteger intNumSHA384 = new BigInteger(1, bytSHA384);
String hcSHA384 = intNumSHA384.toString(16);
while (hcSHA384.length() < 96) {
hcSHA384 = "0" + hcSHA384;
}
/* SHA-512 */
MessageDigest objSHA512 = MessageDigest.getInstance("SHA-512");
byte[] bytSHA512 = objSHA512.digest(input.getBytes());
BigInteger intNumSHA512 = new BigInteger(1, bytSHA512);
String hcSHA512 = intNumSHA512.toString(16);
while (hcSHA512.length() < 128) {
hcSHA512 = "0" + hcSHA512;
}
System.out.println("\nMD2: " + hcMD2
+ "\nMD5: " + hcMD5
+ "\nSHA-1: " + hcSHA1
+ "\nSHA-256: " + hcSHA256
+ "\nSHA-384: " + hcSHA384
+ "\nSHA-512: " + hcSHA512);
}
}
The input needs to be Scanner, because it is essential that it is run in a Command Prompt.
How could a file hash generator be created that takes the file path, such as C:\Program Files\WinRAR\Rar.exe and generates the hashes (MD2, MD5, SHA-1, SHA-256, SHA-384, SHA-512)?
Edit: The only solutions I have been able to find only use the file's name, not the entire path.
First, you need a mechanism to print a byte[] as hex. From the top answer to How to convert a byte array to a hex string in Java? you can do,
final protected static char[] hexArray = "0123456789ABCDEF".toCharArray();
public static String bytesToHex(byte[] bytes) {
char[] hexChars = new char[bytes.length * 2];
for (int j = 0; j < bytes.length; j++) {
int v = bytes[j] & 0xFF;
hexChars[j * 2] = hexArray[v >>> 4];
hexChars[j * 2 + 1] = hexArray[v & 0x0F];
}
return new String(hexChars);
}
Then, you might use Files.readAllBytes(Path) to read your file(s). Finally, iterate an array of hash algorithms to calculate each hash. Something like,
public static void main(String args[]) {
Scanner inputScanner = new Scanner(System.in);
String[] hashAlgos = { "MD2", "MD5", "SHA-1", "SHA-256", "SHA-384", "SHA-512" };
System.out.print("Input: ");
String input = inputScanner.next();
try {
byte[] fileContents = Files.readAllBytes(new File(input).toPath());
for (String algo : hashAlgos) {
MessageDigest md = MessageDigest.getInstance(algo);
byte[] hash = md.digest(fileContents);
System.out.printf("%s %s%n", algo, bytesToHex(hash));
}
} catch (NoSuchAlgorithmException | IOException e) {
e.printStackTrace();
}
}
I am calculating the MD5 in PHP with following line (see documentation for more info):
md5($password, true); // returns raw output
I am using the following Java code:
byte[] bytesOfMessage = password.getBytes("UTF-8");
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] thedigest = md.digest(bytesOfMessage);
Above code doesn't return the same output as the one returned by the PHP code.
How can I solve it for Android/Java generate exactly the same MD5 with raw output not hash string?
Yes. I had the same problem. I find the right way:
That is my equivalent of PHP's md5(password, true):
final protected static char[] hexArray = "0123456789ABCDEF".toCharArray();
public byte[] md5x16(String text) {
try {
MessageDigest digester = MessageDigest.getInstance("MD5");
digester.update(text.getBytes());
byte[] md5Bytes = digester.digest();
String md5Text = new String(md5Bytes); // if you need in String format
// better use md5Bytes if applying further processing to the generated md5.
// Otherwise it may give undesired results.
return md5Bytes;
}
catch (Exception e) {
e.printStackTrace();
}
return null;
}
and equivalent of PHP's md5(password, false):
public static String md5(String text) {
try {
MessageDigest digester = MessageDigest.getInstance("MD5");
digester.update(text.getBytes());
byte[] md5Bytes = digester.digest();
String md5Text = null;
md5Text = bytesToHex(md5Bytes);
return md5Text;
}
catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return "";
}
public static String bytesToHex(byte[] bytes) {
char[] hexChars = new char[bytes.length * 2];
for (int j = 0; j < bytes.length; j++) {
int v = bytes[j] & 0xFF;
hexChars[j * 2] = hexArray[v >>> 4];
hexChars[j * 2 + 1] = hexArray[v & 0x0F];
}
return new String(hexChars);
}
And if you need to convert an equivalent of PHP's base64_encode(text), use this one:
public String convertToBase64(byte[] bytes) {
try {
String base64 = Base64.encodeToString(bytes, Base64.DEFAULT);
return base64;
}
catch (Exception e) {
}
return "";
}
I had the same issue, this is my Java program code:
public static String encryptPassword(String password) {
String hash = null;
try {
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(password.getBytes("UTF-8"));
byte[] raw = md.digest();
hash = (new BASE64Encoder()).encode(raw);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return hash;
}
And this is my php code:
<?php
$str = 'encodeIt';
$toutf8 = utf8_encode($str);
$var = md5($str,true);
echo base64_encode($var);
?>
They return always the same hash.
I am trying to convert a String to its MD5 representation with this code:
public static void main(String[] args) throws NoSuchAlgorithmException {
String s = "oshai";
MessageDigest m = MessageDigest.getInstance("MD5");
m.update(s.getBytes(),0,s.length());
String md5 = new BigInteger(1,m.digest()).toString(16);
System.out.println(md5.length());
}
The returned String has add number of digits (31, so it can be an Hex number). What am I doing wrong?
You don't want to use BigInteger. Try a more traditional toHexString method..
public static void main(String[] args) throws NoSuchAlgorithmException {
String s = "oshai";
MessageDigest m = MessageDigest.getInstance("MD5");
m.update(s.getBytes(),0,s.length());
String string = toHexString(m.digest());
System.out.println(string);
}
public static String toHexString(byte[] bytes) {
StringBuilder sb = new StringBuilder();
for(byte b : bytes) {
sb.append(String.format("%02x", b));
}
return sb.toString();
}
This method works for sure:
private String hashWithMD5(String text) throws UnsupportedEncodingException, NoSuchAlgorithmException {
MessageDigest messageDigest = MessageDigest.getInstance("MD5");
byte[] digest = messageDigest.digest(text.getBytes("UTF-8"));
StringBuilder sb = new StringBuilder();
for (int i = 0; i < digest.length; i++) {
sb.append(Integer.toString((digest[i] & 0xff) + 0x100, 16).substring(1));
}
return sb.toString();
}
I have faced an error with missing "00" at the left side, while converting string to the encrypted format.
Normally you won't find the bug in your app by using the common md5 method.
So, please test your app with the string "sandeep" (I have used it because it has a "00" at left side).
This issue messed my hours and finally i found the following solution from a link.
"I had an error with md5 string with 00 at leftside, ie, a string “sandeep” converted to “DCF16D903E5890AABA465B0B1BA51F ” than the actual “00DCF16D903E5890AABA465B0B1BA51F
I ended up with this method, that work cool in my app."
public static String md5(String inputString) {
try {
// Create MD5 Hash
MessageDigest msgDigest = java.security.MessageDigest.getInstance("MD5");
msgDigest.update(inputString.getBytes());
byte msgDigestBytes[] = msgDigest.digest();
// Create Hex String
StringBuffer hexString = new StringBuffer();
for (int i = 0; i < msgDigestBytes.length; i++) {
String h = Integer.toHexString(0xFF & msgDigestBytes[i]);
while (h.length() < 2)
h = "0" + h;
hexString.append(h);
}
return hexString.toString();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return "";
}
Ref:http://www.coderexception.com/CbHuB1uHPWxXUQXi/converting-string-to-md5-gives-add-number-of-digits
use this method :
public static String md5(String input) {
String md5 = null;
if (null == input)
return null;
try {
// Create MessageDigest object for MD5
MessageDigest digest = MessageDigest.getInstance("MD5");
// Update input string in message digest
digest.update(input.getBytes(), 0, input.length());
// Converts message digest value in base 16 (hex)
md5 = new BigInteger(1, digest.digest()).toString(16);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return md5;
}
How can I hash some String with SHA-256 in Java?
SHA-256 isn't an "encoding" - it's a one-way hash.
You'd basically convert the string into bytes (e.g. using text.getBytes(StandardCharsets.UTF_8)) and then hash the bytes. Note that the result of the hash would also be arbitrary binary data, and if you want to represent that in a string, you should use base64 or hex... don't try to use the String(byte[], String) constructor.
e.g.
MessageDigest digest = MessageDigest.getInstance("SHA-256");
byte[] hash = digest.digest(text.getBytes(StandardCharsets.UTF_8));
I think that the easiest solution is to use Apache Common Codec:
String sha256hex = org.apache.commons.codec.digest.DigestUtils.sha256Hex(stringText);
Another alternative is Guava which has an easy-to-use suite of Hashing utilities. For example, to hash a string using SHA256 as a hex-string you would simply do:
final String hashed = Hashing.sha256()
.hashString("your input", StandardCharsets.UTF_8)
.toString();
Full example hash to string as another string.
public static String sha256(final String base) {
try{
final MessageDigest digest = MessageDigest.getInstance("SHA-256");
final byte[] hash = digest.digest(base.getBytes("UTF-8"));
final StringBuilder hexString = new StringBuilder();
for (int i = 0; i < hash.length; i++) {
final String hex = Integer.toHexString(0xff & hash[i]);
if(hex.length() == 1)
hexString.append('0');
hexString.append(hex);
}
return hexString.toString();
} catch(Exception ex){
throw new RuntimeException(ex);
}
}
If you are using Java 8 you can encode the byte[] by doing
MessageDigest digest = MessageDigest.getInstance("SHA-256");
byte[] hash = digest.digest(text.getBytes(StandardCharsets.UTF_8));
String encoded = Base64.getEncoder().encodeToString(hash);
import java.security.MessageDigest;
public class CodeSnippets {
public static String getSha256(String value) {
try{
MessageDigest md = MessageDigest.getInstance("SHA-256");
md.update(value.getBytes());
return bytesToHex(md.digest());
} catch(Exception ex){
throw new RuntimeException(ex);
}
}
private static String bytesToHex(byte[] bytes) {
StringBuffer result = new StringBuffer();
for (byte b : bytes) result.append(Integer.toString((b & 0xff) + 0x100, 16).substring(1));
return result.toString();
}
}
String hashWith256(String textToHash) {
MessageDigest digest = MessageDigest.getInstance("SHA-256");
byte[] byteOfTextToHash = textToHash.getBytes(StandardCharsets.UTF_8);
byte[] hashedByetArray = digest.digest(byteOfTextToHash);
String encoded = Base64.getEncoder().encodeToString(hashedByetArray);
return encoded;
}
I traced the Apache code through DigestUtils and sha256 seems to default back to java.security.MessageDigest for calculation. Apache does not implement an independent sha256 solution. I was looking for an independent implementation to compare against the java.security library. FYI only.
In Java 8
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Scanner;
import javax.xml.bind.DatatypeConverter;
Scanner scanner = new Scanner(System.in);
String password = scanner.nextLine();
scanner.close();
MessageDigest digest = null;
try {
digest = MessageDigest.getInstance("SHA-256");
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
byte[] hash = digest.digest(password.getBytes(StandardCharsets.UTF_8));
String encoded = DatatypeConverter.printHexBinary(hash);
System.out.println(encoded.toLowerCase());
This was my approach using Kotlin:
private fun getHashFromEmailString(email : String) : String{
val charset = Charsets.UTF_8
val byteArray = email.toByteArray(charset)
val digest = MessageDigest.getInstance("SHA-256")
val hash = digest.digest(byteArray)
return hash.fold("", { str, it -> str + "%02x".format(it)})
}
This is what i have been used for hashing:
String pass = "password";
MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");
byte hashBytes[] = messageDigest.digest(pass.getBytes(StandardCharsets.UTF_8));
BigInteger noHash = new BigInteger(1, hashBytes);
String hashStr = noHash.toString(16);
Output: 5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8
Here is a slightly more performant way to turn the digest into a hex string:
private static final char[] hexArray = "0123456789abcdef".toCharArray();
public static String getSHA256(String data) {
StringBuilder sb = new StringBuilder();
try {
MessageDigest md = MessageDigest.getInstance("SHA-256");
md.update(data.getBytes());
byte[] byteData = md.digest();
sb.append(bytesToHex(byteData);
} catch(Exception e) {
e.printStackTrace();
}
return sb.toString();
}
private static String bytesToHex(byte[] bytes) {
char[] hexChars = new char[bytes.length * 2];
for ( int j = 0; j < bytes.length; j++ ) {
int v = bytes[j] & 0xFF;
hexChars[j * 2] = hexArray[v >>> 4];
hexChars[j * 2 + 1] = hexArray[v & 0x0F];
}
return String.valueOf(hexChars);
}
Does anyone know of a faster way in Java?
This method return a left padded String with zero:
Java 10 and after:
public static String sha256(String text) {
try {
var messageDigest = MessageDigest.getInstance("SHA-256");
var hash = messageDigest.digest(text.getBytes(StandardCharsets.UTF_8));
return String.format("%064x", new BigInteger(1, hash));
}
catch (NoSuchAlgorithmException e) {
e.printStackTrace();
return null;
}
}
Java 8:
public static String sha256(String text) {
try {
MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");
byte[] hash = messageDigest.digest(text.getBytes(StandardCharsets.UTF_8));
return String.format("%064x", new BigInteger(1, hash));
}
catch (NoSuchAlgorithmException e) {
e.printStackTrace();
return null;
}
}
BTW, you can use "%064X" for an uppercase result.
Example:
System.out.println(sha256("hello world 1"));
063dbf1d36387944a5f0ace625b4d3ee36b2daefd8bdaee5ede723637efb1cf4
Comparison to Linux cmd:
$ echo -n 'hello world 1' | sha256sum
063dbf1d36387944a5f0ace625b4d3ee36b2daefd8bdaee5ede723637efb1cf4 -
You can use MessageDigest in the following way:
public static String getSHA256(String data){
StringBuffer sb = new StringBuffer();
try{
MessageDigest md = MessageDigest.getInstance("SHA-256");
md.update(data.getBytes());
byte byteData[] = md.digest();
for (int i = 0; i < byteData.length; i++) {
sb.append(Integer.toString((byteData[i] & 0xff) + 0x100, 16).substring(1));
}
} catch(Exception e){
e.printStackTrace();
}
return sb.toString();
}
Here's a method that shows how to hash a String with the sha-256
algorithm and encode the result in hex format. This is an often used format to hash and store passwords in a database:
public static String sha256(final String data) {
try {
final byte[] hash = MessageDigest.getInstance("SHA-256").digest(data.getBytes(StandardCharsets.UTF_8));
final StringBuilder hashStr = new StringBuilder(hash.length);
for (byte hashByte : hash)
hashStr.append(Integer.toHexString(255 & hashByte));
return hashStr.toString();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
return null;
}
}
public static String sha256(String s) {
try {
return DatatypeConverter.printHexBinary(MessageDigest.getInstance("SHA-256").digest(s.getBytes(StandardCharsets.UTF_8))).toLowerCase();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return null;
}
In Java, MessageDigest class is used to calculate cryptographic hashing value. This class provides cryptographic hash function ( MD5, SHA-1 and SHA-256) to find hash value of text.
Code example for using SHA-256 algorithm.
public void printHash(String str) throws NoSuchAlgorithmException {
MessageDigest md=MessageDigest.getInstance("SHA-256");
byte[] sha256=md.digest(str.getBytes(StandardCharsets.UTF_8));
for(byte b : sha256){
System.out.printf("%02x",b);
}
}
private static String getMessageDigest(String message, String algorithm) {
MessageDigest digest;
try {
digest = MessageDigest.getInstance(algorithm);
byte data[] = digest.digest(message.getBytes("UTF-8"));
return convertByteArrayToHexString(data);
} catch (NoSuchAlgorithmException | UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
You can call above method with different algorithms like below.
getMessageDigest(message, "MD5");
getMessageDigest(message, "SHA-256");
getMessageDigest(message, "SHA-1");
You can refer this link for complete application.