I have a byte array , I also have 2 methods which one is HexEncode ( converts a byte array to hex String ) the other one is HexDecode ( converts a hex string to byte array )
at first I print the byte array , converted string and hexEncode
then I encode it , then again decode this ,
when print it , both of strings and hexEncodes are equal
but byte arrays are not the same.
whats the problem ?
how can I encode and decode it in a way which both byte arrays
will be same like others ?
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
public class MainClass {
public static void main ( String args[]) throws NoSuchAlgorithmException{
SecureRandom prng = SecureRandom.getInstance("SHA1PRNG");
SecureRandom r = new SecureRandom();
BigInteger p = new BigInteger(1024 / 2, 100, r);
MessageDigest sha = MessageDigest.getInstance("SHA-1");
byte[] result = sha.digest(p.toByteArray());
//now I have a random byte array :)
System.out.println(result);
System.out.println(hexEncode(result));
String temp1 = new String(result);
System.out.println(temp1);
byte[] after = hexStringToByteArray(hexEncode(result));
System.out.println(after );
System.out.println(hexEncode(after));
String temp2 = new String(after);
System.out.println(temp2);
if ( Arrays.equals(result, after) ){
System.out.println("OK");
}
else{
System.out.println("Problem");
}
}
private static String hexEncode(byte[] aInput){
StringBuilder result = new StringBuilder();
char[] digits = {'0', '1', '2', '3', '4','5','6','7','8','9','a','b','c','d','e','f'};
for (int idx = 0; idx < aInput.length; ++idx) {
byte b = aInput[idx];
result.append(digits[ (b&0xf0) >> 4 ]);
result.append(digits[ b&0x0f]);
}
return result.toString();
}
public static byte[] hexStringToByteArray(String s) {
int len = s.length();
byte[] data = new byte[len / 2];
for (int i = 0; i < len; i += 2) {
data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
+ Character.digit(s.charAt(i+1), 16));
}
return data;
}
}
sample output is :
[B#29453f44
66384c6457e27cbfed4a45c080235f52e50e88a5
f8LdWâ|¿íJEÀ€#_R別
[B#5cad8086
66384c6457e27cbfed4a45c080235f52e50e88a5
f8LdWâ|¿íJEÀ€#_R別
OK
Use Arrays.equals(byte[] b1, byte[] b2) instead of equals:
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Arrays;
public class MainClass {
public static void main ( String args[]) throws NoSuchAlgorithmException{
SecureRandom prng = SecureRandom.getInstance("SHA1PRNG");
SecureRandom r = new SecureRandom();
BigInteger p = new BigInteger(1024 / 2, 100, r);
MessageDigest sha = MessageDigest.getInstance("SHA-1");
byte[] result = sha.digest(p.toByteArray());
//now I have a random byte array :)
System.out.println(result);
System.out.println(hexEncode(result));
String temp1 = new String(result);
System.out.println(temp1);
byte[] after = hexStringToByteArray(hexEncode(result));
System.out.println(after );
System.out.println(hexEncode(after));
String temp2 = new String(after);
System.out.println(temp2);
if ( Arrays.equals(after, result)){
System.out.println("OK");
}
else{
System.out.println("Problem");
}
}
private static String hexEncode(byte[] aInput){
StringBuilder result = new StringBuilder();
char[] digits = {'0', '1', '2', '3', '4','5','6','7','8','9','a','b','c','d','e','f'};
for (int idx = 0; idx < aInput.length; ++idx) {
byte b = aInput[idx];
result.append(digits[ (b&0xf0) >> 4 ]);
result.append(digits[ b&0x0f]);
}
return result.toString();
}
public static byte[] hexStringToByteArray(String s) {
int len = s.length();
byte[] data = new byte[len / 2];
for (int i = 0; i < len; i += 2) {
data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
+ Character.digit(s.charAt(i+1), 16));
}
return data;
}
}
Related
I used ricmoo/aes-js to encrypt node server response,
Cypher.js
"use strict";
var aesjs = require("aes-js");
var sha256 = require("js-sha256");
const getKeyArray = function() {
let buffer = sha256.arrayBuffer("mykey");
let keyArray = new Uint8Array(buffer);
const keySize = 16;
let arr = new Array();
for (var i = 0; i < keySize; i++) {
arr.push(keyArray[i]);
}
return arr;
};
module.exports = {
getKey: function() {
return getKeyArray();
},
encrypt: function(text) {
var textBytes = aesjs.utils.utf8.toBytes(text);
// The counter is optional, and if omitted will begin at 1
var aesCtr = new aesjs.ModeOfOperation.ctr(
getKeyArray(),
new aesjs.Counter(Math.floor(Math.random() * Number.MAX_SAFE_INTEGER))
);
var counterArray = aesCtr._counter._counter.slice()
var encryptedBytes = aesCtr.encrypt(textBytes);
// To print or store the binary data, you may convert it to hex
var encryptedHex = aesjs.utils.hex.fromBytes(encryptedBytes);
var ivHex = aesjs.utils.hex.fromBytes(counterArray);
return ivHex + ":" + encryptedHex;
},
decrypt: function(encryptedHex) {
let split = encryptedHex.split(":");
// When ready to decrypt the hex string, convert it back to bytes
var encryptedBytes = aesjs.utils.hex.toBytes(split[1]);
let ivHex = split[0];
var ivBytes = aesjs.utils.hex.toBytes(ivHex);
var counter = new aesjs.Counter(ivBytes);
// The counter mode of operation maintains internal state, so to
// decrypt a new instance must be instantiated.
var aesCtr = new aesjs.ModeOfOperation.ctr(getKeyArray(), ivBytes);
var decryptedBytes = aesCtr.decrypt(encryptedBytes);
// Convert our bytes back into text
var decryptedText = aesjs.utils.utf8.fromBytes(decryptedBytes);
return decryptedText;
}
};
And the decryption in Java
Cypher.java
import javax.crypto.Cipher;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
class Cypher {
private final static char[] hexArray = "0123456789ABCDEF".toCharArray();
private static String KEY = "mykey";
/**
* Decrypt a given hex string,
* #param hexString
* #return
*/
static String decrypt(String hexString) throws Exception{
Cipher cipher = Cipher.getInstance("AES/CTR/NoPadding");
String ivHex = hexString.split(":")[0];
hexString = hexString.split(":")[1];
IvParameterSpec ivSpec = new IvParameterSpec(hexStringToByteArray(ivHex));
cipher.init(Cipher.DECRYPT_MODE, getEncryptionKey(KEY), ivSpec);
byte[] decrypted = cipher.doFinal(hexStringToByteArray(hexString));
return new String(decrypted);
}
private static SecretKeySpec getEncryptionKey(String key) throws Exception {
MessageDigest digest = MessageDigest.getInstance("SHA-256");
digest.update(key.getBytes("UTF-8"));
byte[] keyBytes = new byte[16];
System.arraycopy(digest.digest(), 0, keyBytes, 0, keyBytes.length);
SecretKeySpec secretKeySpec = new SecretKeySpec(keyBytes, "AES");
return secretKeySpec;
}
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);
}
static byte[] hexStringToByteArray(String s) {
int len = s.length();
byte[] data = new byte[len / 2];
for (int i = 0; i < len; i += 2) {
data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
+ Character.digit(s.charAt(i+1), 16));
}
return data;
}
}
My question is:
1- Is this code above acceptable or it has any major issue?
2- How can I improve it?
Edit 2
I have updated the question, now the code in question uses random IV in the encryption & decryption process.
Edit
Please do not use the code below, because it doesn't generate the IVs randomly, see the comments below.
Old Answer
It was not easy at all, but finally I got it to work, here is my full working code (encryption on node.js and decryption on Android):
Cypher.js
"use strict";
var aesjs = require("aes-js");
var sha256 = require("js-sha256");
const getKeyArray = function() { // decryption on Android doesn't support 256 bit keys with AES/CTR, so I'm using only 128 bits
let buffer = sha256.arrayBuffer("mystrongkey");
let keyArray = new Uint8Array(buffer);
const keySize = 16;
let arr = new Array;
for (var i = 0; i < keySize; i++) {
arr.push(keyArray[i]);
}
return arr;
}
module.exports = {
getKey: function() {
return getKeyArray();
},
getIV: function() {
return new aesjs.Counter(5);
},
encrypt: function(text) {
var textBytes = aesjs.utils.utf8.toBytes(text);
// The counter is optional, and if omitted will begin at 1
var aesCtr = new aesjs.ModeOfOperation.ctr(getKeyArray(), this.getIV());
var encryptedBytes = aesCtr.encrypt(textBytes);
// To print or store the binary data, you may convert it to hex
var encryptedHex = aesjs.utils.hex.fromBytes(encryptedBytes);
return encryptedHex;
},
decrypt: function(encryptedHex) {
// When ready to decrypt the hex string, convert it back to bytes
var encryptedBytes = aesjs.utils.hex.toBytes(encryptedHex);
// The counter mode of operation maintains internal state, so to
// decrypt a new instance must be instantiated.
var aesCtr = new aesjs.ModeOfOperation.ctr(getKeyArray(), this.getIV());
var decryptedBytes = aesCtr.decrypt(encryptedBytes);
// Convert our bytes back into text
var decryptedText = aesjs.utils.utf8.fromBytes(decryptedBytes);
return decryptedText;
}
};
Cypher.java
package com.mypackage;
import javax.crypto.Cipher;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
class Cypher {
private final static char[] hexArray = "0123456789ABCDEF".toCharArray();
private static String KEY = "mystrongkey";
/**
* Decrypt a given hex string,
* 08768efebc = Hello
* #param hexString
* #return
*/
static String decrypt(String hexString) throws Exception{
Cipher cipher = Cipher.getInstance("AES/CTR/NoPadding");
IvParameterSpec ivSpec = new IvParameterSpec(new byte[] { // got this one by console.log(Cypher.getIv()) from Cypher.js
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
5
});
cipher.init(Cipher.DECRYPT_MODE, getEncryptionKey(KEY), ivSpec);
byte[] decrypted = cipher.doFinal(hexStringToByteArray(hexString));
return new String(decrypted);
}
static String encrypt(String string) throws Exception {
Cipher cipher = Cipher.getInstance("AES/CTR/NoPadding");
IvParameterSpec ivSpec = new IvParameterSpec(new byte[] {
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
5
});
cipher.init(Cipher.ENCRYPT_MODE, getEncryptionKey(KEY), ivSpec);
byte[] encrypted = cipher.doFinal(string.getBytes());
return bytesToHex(encrypted);
}
private static SecretKeySpec getEncryptionKey(String key) throws Exception {
MessageDigest digest = MessageDigest.getInstance("SHA-256");
digest.update(key.getBytes("UTF-8"));
byte[] keyBytes = new byte[16];
System.arraycopy(digest.digest(), 0, keyBytes, 0, keyBytes.length);
SecretKeySpec secretKeySpec = new SecretKeySpec(keyBytes, "AES");
return secretKeySpec;
}
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);
}
static byte[] hexStringToByteArray(String s) {
int len = s.length();
byte[] data = new byte[len / 2];
for (int i = 0; i < len; i += 2) {
data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
+ Character.digit(s.charAt(i+1), 16));
}
return data;
}
}
Hope this will save time of somebody trying to decrypt from node.js
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 was writing some code to simulate the proof-of-work done by the Bitcoin network while generating blocks when I suddenly became curious: How can you create a datum that contains it's own hash?
Just for fun, I wrote a program that attempts to create data that contains it's own hash. 4 random bytes are generated, then a nonce is added at the end and the whole value is hashed with CRC32. The nonce in incremented and the process repeats until the program finds a hash that matches the original 4 bytes.
Note: The nonce can increase indefinitely.
Here's an example of the output after approx 1,980,000,000 attempts:
Found a match!
Data: 7a73a2d4ab833876
Original hash: 7a73a2d4 new hash: 7a73a2d4
Is there a potential use for this?
package selfhash;
import java.math.BigInteger;
import java.nio.ByteBuffer;
import java.security.MessageDigest;
import java.security.SecureRandom;
import java.util.Arrays;
import java.util.zip.CRC32;
import java.util.zip.Checksum;
/**
*
* #author dylan
*/
public class SelfHash {
static byte[] data;
static byte[] hash = new byte[4];
public static void main(String[] args) {
// TODO code application logic here
SecureRandom random = new SecureRandom();
random.nextBytes(hash);
data = new byte[hash.length + 1];
System.arraycopy(hash, 0, data, 0, hash.length);
long c = 0;
while (true) {
recalculateData();
byte[] dataHash = crc32AsByteArray(data);
if (c % 10000000 == 0) {
System.out.println("Calculated " + c + " hashes");
System.out.println("Data: " + byteArrayToHex(data));
System.out.println("Original hash: " + byteArrayToHex(hash) + " new hash: " + byteArrayToHex(dataHash));
}
if (Arrays.equals(hash, dataHash)) {
System.out.println("Found a match!");
System.out.println("Data: " + byteArrayToHex(data));
System.out.println("Original hash: " + byteArrayToHex(hash) + " new hash: " + byteArrayToHex(dataHash));
break;
}
c++;
}
}
public static void recalculateData() {
int position = hash.length;
while (true) {
int valueAtPosition = unsignedToBytes(data[position]);
if (valueAtPosition == 255) {
//increase size of data
if (position == data.length-1) {
byte[] newData = new byte[data.length + 1];
System.arraycopy(data, 0, newData, 0, data.length);
data = newData;
}
data[position] = (byte) (0);
position++;
} else {
data[position] = (byte) (valueAtPosition + 1);
break;
}
}
}
public static byte[] hexToByteArray(String hexString) {
int len = hexString.length();
byte[] data = new byte[len / 2];
for (int i = 0; i < len; i += 2) {
data[i / 2] = (byte) ((Character.digit(hexString.charAt(i), 16) << 4)
+ Character.digit(hexString.charAt(i + 1), 16));
}
return data;
}
private static final char[] BYTE2HEX = ("000102030405060708090A0B0C0D0E0F"
+ "101112131415161718191A1B1C1D1E1F"
+ "202122232425262728292A2B2C2D2E2F"
+ "303132333435363738393A3B3C3D3E3F"
+ "404142434445464748494A4B4C4D4E4F"
+ "505152535455565758595A5B5C5D5E5F"
+ "606162636465666768696A6B6C6D6E6F"
+ "707172737475767778797A7B7C7D7E7F"
+ "808182838485868788898A8B8C8D8E8F"
+ "909192939495969798999A9B9C9D9E9F"
+ "A0A1A2A3A4A5A6A7A8A9AAABACADAEAF"
+ "B0B1B2B3B4B5B6B7B8B9BABBBCBDBEBF"
+ "C0C1C2C3C4C5C6C7C8C9CACBCCCDCECF"
+ "D0D1D2D3D4D5D6D7D8D9DADBDCDDDEDF"
+ "E0E1E2E3E4E5E6E7E8E9EAEBECEDEEEF"
+ "F0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF").toLowerCase().toCharArray();
;
public static String byteArrayToHex(byte[] bytes) {
final int len = bytes.length;
final char[] chars = new char[len << 1];
int hexIndex;
int idx = 0;
int ofs = 0;
while (ofs < len) {
hexIndex = (bytes[ofs++] & 0xFF) << 1;
chars[idx++] = BYTE2HEX[hexIndex++];
chars[idx++] = BYTE2HEX[hexIndex];
}
return new String(chars);
}
public static String sha256AsHexString(byte[] bytes) {
try {
MessageDigest digest = MessageDigest.getInstance("SHA-256");
return byteArrayToHex(digest.digest(bytes));
} catch (Exception e) {
throw new Error(e);
}
}
public static byte[] sha256AsByteArray(byte[] bytes) {
try {
MessageDigest digest = MessageDigest.getInstance("SHA-256");
return digest.digest(bytes);
} catch (Exception e) {
throw new Error(e);
}
}
public static byte[] crc32AsByteArray(byte[] bytes) {
Checksum checksum = new CRC32();
checksum.update(bytes, 0, bytes.length);
long value = checksum.getValue();
byte[] resultExcess = ByteBuffer.allocate(8).putLong(value).array();
byte[] result = new byte[4];
System.arraycopy(resultExcess, 4, result, 0, 4);
return result;
}
public static int unsignedToBytes(byte b) {
return b & 0xFF;
}
}
I can't think of a use.
CRC's are linear, and so the equations can be solved very fast to get the second four bytes. You don't need two billion trials to find it. See spoof.c.
I am using following code block to generate MD5 hashes:
public static String encode(String data) throws Exception {
/* Check the validity of data */
if (data == null || data.isEmpty()) {
throw new IllegalArgumentException("Null value provided for "
+ "MD5 Encoding");
}
/* Get the instances for a given digest scheme MD5 or SHA */
MessageDigest m = MessageDigest.getInstance("MD5");
/* Generate the digest. Pass in the text as bytes, length to the
* bytes(offset) to be hashed; for full string pass 0 to text.length()
*/
m.update(data.getBytes(), 0, data.length());
/* Get the String representation of hash bytes, create a big integer
* out of bytes then convert it into hex value (16 as input to
* toString method)
*/
String digest = new BigInteger(1, m.digest()).toString(16);
return digest;
}
When I run the above code segment with String data as [12, B006GQIIEM, MH-ANT2000], the output is a 31 character hash - 268d43a823933c9dafaa4ac0e756d6a.
Is there any problem with the MD5 hash function or there is some problem in the code above?
The only issue in your code is when MSB is less than Ox10, the result hash string will only have 31 bytes, instead of 32 bytes, missing the leading zero.
Create your md5 string in this way:
byte messageDigest[] = m.digest();
hexString = new StringBuffer();
for (int i=0;i<messageDigest.length;i++) {
String hex=Integer.toHexString(0xFF & messageDigest[i]);
if(hex.length()==1)
hexString.append('0');
hexString.append(hex);
}
You can try this:
...
String digest = String.format("%032x", new BigInteger(1, m.digest()));
Note: it is "%032x", not "%32x".
This is how I use MD5 hash. Calculate MD5 hash from string and return 32-byte hexadecimal representation.
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public class MySimpleMD5 {
private static String convertToHex(byte[] data) {
StringBuffer buf = new StringBuffer();
for (int i = 0; i < data.length; i++) {
int halfbyte = (data[i] >>> 4) & 0x0F;
int two_halfs = 0;
do {
if ((0 <= halfbyte) && (halfbyte <= 9))
buf.append((char) ('0' + halfbyte));
else
buf.append((char) ('a' + (halfbyte - 10)));
halfbyte = data[i] & 0x0F;
} while(two_halfs++ < 1);
}
return buf.toString();
}
public static String MD5(String text)
throws NoSuchAlgorithmException, UnsupportedEncodingException {
MessageDigest md;
md = MessageDigest.getInstance("MD5");
byte[] md5hash = new byte[32];
md.update(text.getBytes("iso-8859-1"), 0, text.length());
md5hash = md.digest();
return convertToHex(md5hash);
}
}
You can also try this:
private static String getMd5Hash(String input) throws NoSuchAlgorithmException {
MessageDigest m = MessageDigest.getInstance("MD5");
byte[] data = m.digest(EncodingUtils.getBytes(input, "UTF8"));
StringBuilder sBuilder = new StringBuilder();
for (int i = 0; i < data.length; i++) {
for (byte b : data) {
if(b == 0x00){
sBuilder.append("00");
} else if ((b & 0x0F) == b) {
sBuilder.append("0");
break;
} else {
break;
}
}
BigInteger bigInt = new BigInteger(1, data);
sBuilder.append(bigInt.toString(16));
}
// Return the hexadecimal string.
return sBuilder.toString().substring(0, 32);
}
A UUID in the form of "b2f0da40ec2c11e00000242d50cf1fbf" has been transformed (see the following code segment) into a hex string as 6232663064613430656332633131653030303030323432643530636631666266. I want to code a reverse routine and get it back to the original format as in "b2f0...", but had a hard time to do so, any help?
byte[] bytes = uuid.getBytes("UTF-8");
StringBuilder hex = new StringBuilder(bytes.length* 2);
Formatter fmt = new Formatter(hex);
for (byte b : bytes)
fmt.format("%x", b);
final String input = "6232663064613430656332633131653030303030323432643530636631666266";
System.out.println("input: " + input);
final StringBuilder result = new StringBuilder();
for (int i = 0; i < input.length(); i += 2) {
final String code = input.substring(i, i + 2);
final int code2 = Integer.parseInt(code, 16);
result.append((char)code2);
}
System.out.println("result: " + result);
It prints:
input: 6232663064613430656332633131653030303030323432643530636631666266
result: b2f0da40ec2c11e00000242d50cf1fbf
Here you go:
import java.util.Formatter;
class Test {
public static void main(String[] args) {
String uuid = "b2f0da40ec2c11e00000242d50cf1fbf";
byte[] bytes = uuid.getBytes();
StringBuilder hex = new StringBuilder(bytes.length * 2);
Formatter fmt = new Formatter(hex);
for (byte b : bytes) {
fmt.format("%x", b);
}
System.out.println(hex);
/******** reverse the process *******/
/**
* group the bytes in couples
* convert them to integers (base16)
* and store them as bytes
*/
for (int i = 0; i < bytes.length; i++) {
bytes[i] = (byte) Integer.parseInt(hex.substring(2 * i, 2 * i + 2), 16);
}
/**
* build a string from the bytes
*/
String original = new String(bytes);
System.out.println(original);
}
}