The java code below generates a SHA-256 hash of the input msg, using the key. However, all my attempts to write code that does same operation in C# have not yielded the same results given same input. I would need help getting the C# equivalent as I have tried a lot already with little success.
I think I've been able to translate most of the code into C# correctly, apart from the part which updates the digest (m.update()), first with the key, then later with the message before hashing.
JAVA CODE
public static String generateHash256Value(String msg, String key) {
MessageDigest m = null;
String hashText = null;
System.out.println("Value to hash::::::::::" + msg);
byte[] actualKeyBytes = HexToByte(secret_key);
try {
m = MessageDigest.getInstance("SHA-256");
m.update(actualKeyBytes, 0, actualKeyBytes.length);
try {
m.update(msg.getBytes("UTF-8"), 0, msg.length());
}
catch (UnsupportedEncodingException ex) {
ex.printStackTrace();
}
hashText = new BigInteger(1, m.digest()).toString(16);
if (hashText.length() < 64) { //must be 64 in length
int numberOfZeroes = 64 - hashText.length();
String zeroes = "";
for (int i = 0; i < numberOfZeroes; i++) {
zeroes = zeroes + "0";
}
hashText = zeroes + hashText;
}
}
catch (NoSuchAlgorithmException ex) {
ex.printStackTrace();
}
hashText = hashText.toUpperCase();
return hashText;
}
public static byte[] hex2Byte(String str) {
byte[] bytes = new byte[str.length() / 2];
for (int i = 0; i < bytes.length; i++) {
bytes[i] = (byte) Integer
.parseInt(str.substring(2 * i, 2 * i + 2), 16);
}
return bytes;
}
C# CODE (attempt)
private static string DoSpecialSha256Hash(string message, string key)
{
String hashText = null;
Console.WriteLine("Value to hash::::::::::" + message);
byte[] keyByte = hex2Byte(key);
Encoding encoder = new System.Text.UTF8Encoding();
var hashAlgo = new SHA256Managed();
var messageBytes = encoder.GetBytes(message);
var toDigest = Combine(keyByte, messageBytes);
hashText = ByteToString(hashAlgo.ComputeHash(toDigest, 0, message.Length));
if (hashText.Length < 64)
{ //must be 64 in length
int numberOfZeroes = 64 - hashText.Length;
String zeroes = "";
for (int i = 0; i < numberOfZeroes; i++)
{
zeroes = zeroes + "0";
}
hashText = zeroes + hashText;
}
hashText = hashText.ToUpper();
return hashText;
}
public static byte[] HexToByte(String hex)
{
return Enumerable.Range(0, hex.Length)
.Where(x => x % 2 == 0)
.Select(x => Convert.ToByte(hex.Substring(x, 2), 16))
.ToArray();
}
private static string ByteToString(byte[] buff)
{
string sbinary = "";
for (int i = 0; i < buff.Length; i++)
{
sbinary += buff[i].ToString("X2"); // hex format
}
return (sbinary);
}
private static byte[] Combine(params byte[][] arrays)
{
byte[] rv = new byte[arrays.Sum(a => a.Length)];
int offset = 0;
foreach (byte[] array in arrays)
{
System.Buffer.BlockCopy(array, 0, rv, offset, array.Length);
offset += array.Length;
}
return rv;
}
Thanks,
I have a wordlist with ~68000 words from level 20 at 0xf.at and want to hash two words to get a hash. Then compare this hash to an existing hash until i found the two words.
I have tried it in java but I am unexpirenced and it is to slow.
import java.io.*;
public class Main {
public static void main(String[] args) throws FileNotFoundException,
IOException {
try (BufferedReader br = new BufferedReader(new FileReader("E:/Trojan/Desktop/wordlist.txt"))) {
StringBuilder sb = new StringBuilder();
String line = br.readLine();
Hash h = new Hash();
String myHash = "cd48323bcf01557f5deadc2ec301affb";
while (line != null) {
sb.append(line);
sb.append(System.lineSeparator());
line = br.readLine();
}
String everything = sb.toString();
String lines[] = everything.split("\\r?\\n");
for (int j = 1; j <= 68848; j++) {
for (int i = 1; i <= 68847; i++) {
//System.out.println(i+":"+lines[i]+" "+j+":"+lines[j]);
if (h.getHash(lines[i]+lines[j], "MD5") == myHash){
System.out.println(lines[i]+lines[j]);
break;
}
}
}
}
}
}
And the md5 hash function i took from an exmaple of stackoverflow:
public class Hash {
/**
*
* #param txt, text in plain format
* #param hashType MD5 OR SHA1
* #return hash in hashType
*/
public static String getHash(String txt, String hashType) {
try {
java.security.MessageDigest md = java.security.MessageDigest.getInstance(hashType);
byte[] array = md.digest(txt.getBytes());
StringBuffer sb = new StringBuffer();
for (int i = 0; i < array.length; ++i) {
sb.append(Integer.toHexString((array[i] & 0xFF) | 0x100).substring(1,3));
}
return sb.toString();
} catch (java.security.NoSuchAlgorithmException e) {
//error action
}
return null;
}
public static String md5(String txt) {
return Hash.getHash(txt, "MD5");
}
public static String sha1(String txt) {
return Hash.getHash(txt, "SHA1");
}
}
How can I get this faster?
You create too many temporary objects inside method getHash. Try reduce. E.g.
private static final char[] HEX ={'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f',};
public static String getHash(String txt, MessageDigest md) {
byte[] array = md.digest(txt.getBytes());
char[] result = new char[array.length*2];
for (int i = 0; i < array.length; ++i) {
byte b = array[i];
result[2*i] = HEX[(b&0x0f0)>>>4];
result[2*i+1] = HEX[b&0x0f];
}
return new String(result);
}
EDIT
Moreover you do not need String objects at all. You should return byte[] and use Arrays.equals method.
this is stringToHexAsciiString.
//将字符串转成ASCII十六进制的java方法
public static String stringToHexAsciiString(String value)
{
StringBuffer sbu = new StringBuffer();
char[] chars = value.toCharArray();
for (int i = 0; i < chars.length; i++)
{
sbu.append(Integer.toHexString(chars[i]));
}
return sbu.toString();
}
this is asciiToString begin
//将ASCII转成字符串的java方法
public static String asciiToString(String value)
{
StringBuffer sbu = new StringBuffer();
//System.out.println("value.length()/2 = " + value.length()/2);
byte[] chars = new byte[value.length()/2];
chars = hexStringToByte(value);
//System.out.println("chars.length = " + chars.length);
for(int i=0; i<chars.length; i++){
//sbu.append((char) Integer.parseInt(chars[i]));
byte[] change = new byte[1];
change[0] = chars[i];
//System.out.println("change[0] = " + change[0]);
sbu.append((char) chars[i]);
//System.out.println("i = " + i + " " + sbu.toString());
}
return sbu.toString();
}
public static byte[] hexStringToByte(String hexString){
if (hexString == null || hexString.equals("")) {
return null;
}
hexString = hexString.toUpperCase();
int length = hexString.length() / 2;
char[] hexChars = hexString.toCharArray();
byte[] d = new byte[length];
for (int i = 0; i < length; i++) {
int pos = i * 2;
d[i] = (byte) (charToByte(hexChars[pos]) << 4 |charToByte(hexChars[pos + 1]));
// d[i] = (byte) (hexChars[pos] << 4 |hexChars[pos + 1]);
}
return d;
}
private static byte charToByte(char c) {
return (byte) "0123456789ABCDEF".indexOf(c);
}
use test english is ok,chinese is bad.
String strAscii = Encrypter.stringToHexAsciiString("汉1232").trim();
String asciiStr = Encrypter.asciiToString("6c4931323332".toUpperCase());
System.out.println("asciiStr:"+asciiStr);
System.out.println("strAscii:"+strAscii);
asciiToString result is chinese become messy code
asciiStr:lI1232
strAscii:6c4931323332
need to 汉1232.stringToHexAsciiString result :chinese char is 2 byte,english is 1 byte。how to div chinese hex and english hex。
I don't know what's the problem in your code... or what exactly you want, this is not clear in your question.
But if you just want convert a String to Hex format then you can try the following code:
import org.apache.commons.codec.binary.Hex;
public class StringToAscii
{
public static void main( String[] args )
{
try {
String s = "汉1232";
System.out.println(s);
String hexString = new String(Hex.encodeHexString(s.getBytes("UTF-8")));
System.out.println(hexString);
String unicode = new String(Hex.decodeHex(hexString.toCharArray()));
System.out.println(unicode);
}catch (Exception e)
{
e.printStackTrace();
}
}
}
The output on my laptop is:
汉1232
e6b18931323332
汉1232
EDIT
I changed $checksum = md5($someString+$bkey); to $checksum = md5($someString.$bkey);
I need to perform the following operations in Java:
$hexString = '90aa';#sample value
$bkey = pack('H*',$hexString);
$someString='qwe';#sample value
$checksum = md5($someString.$bkey);
echo $checksum;
I can't convert hexString to bkey in Java to get the same result as php script. Except bkey everything is working properly.
If I remove bkey then:
PHP:
$someString='qwe';#sample value
$checksum = md5($someString);
echo $checksum;
result: 76d80224611fc919a5d54f0ff9fba446
Java:
String someString = "qwe";
MessageDigest messageDigest = MessageDigest.getInstance("MD5");
String checksum = new BigInteger(1, messageDigest.digest(someString
.getBytes())).toString(16);
System.out.println(checksum);
result: 76d80224611fc919a5d54f0ff9fba446
As you can see, it works
With bkey:
PHP:
$hexString = '90aa';#sample value
$bkey = pack('H*',$hexString);
$someString='qwe';#sample value
$checksum = md5($someString.$bkey);
echo $checksum;
result: 18f5f1a9bf898131945dd9e315759fe4
Java:
public static void main(String[] args) throws NoSuchAlgorithmException {
String hexString = "90aa";
String bkey = hexToString(hexString);
String someString = "qwe";
MessageDigest messageDigest = MessageDigest.getInstance("MD5");
String input = someString + bkey;
String checksum = new BigInteger(1, messageDigest.digest(input
.getBytes())).toString(16);
System.out.println(checksum);
}
public static String hexToString(String hex) {
StringBuilder output = new StringBuilder();
for (int i = 0; i < hex.length(); i += 2) {
String str = hex.substring(i, i + 2);
output.append((char) Integer.parseInt(str, 16));
}
return output.toString();
}
result: 44bb634dee436833dd65caa5043ffeb9
As you can see results are different.
How to convert hex String to String to get the same result?
The problem is not actually in your Java code, but in the PHP code.
The line $checksum = md5($someString+$bkey); does not do what you think it does, it should be:
$checksum = md5($someString . $bkey); # use concatenate, not sum
Although, that gives abetter PHP MD5, but does not help make the Java code match the PHP
EDIT
The problem on the Java side is in the character encoding. The Java char values for the inoacked versions of 90aa are not valid unicode characters. Thus the toByteArray() ,ethods ar enot doing great things. If you treat all of the Java code at a byte level (and ignore any high-bytes in any chars in the Java), then you get the same result as the PHP:
public static void main(String[] args) throws NoSuchAlgorithmException, UnsupportedEncodingException {
String hexString = "90aa";
byte[] bkey = hexToString(hexString);
String someString = "qwe";
MessageDigest messageDigest = MessageDigest.getInstance("MD5");
byte[] input = join(stringToBytes(someString), bkey);
String checksum = new BigInteger(1, messageDigest.digest(input)).toString(16);
System.out.println(checksum);
System.out.println(Charset.defaultCharset().displayName());
}
private static byte[] join(byte[] a, byte[] b) {
// join two byte arrays
final byte[] ret = new byte[a.length + b.length];
System.arraycopy(a, 0, ret, 0, a.length);
System.arraycopy(b, 0, ret, a.length, b.length);
return ret;
}
public static byte[] hexToString(String hex) {
// hexToString that works at a byte level, not a character level
byte[] output = new byte[(hex.length() + 1) / 2];
for (int i = hex.length() - 1; i >= 0; i -= 2) {
int from = i - 1;
if (from < 0) {
from = 0;
}
String str = hex.substring(from, i + 1);
output[i/2] = (byte)Integer.parseInt(str, 16);
}
return output;
}
public static byte[] stringToBytes(final String input) {
// unlike Stirng.toByteArray(), we ignore any high-byte values of the characters.
byte[] ret = new byte[input.length()];
for (int i = input.length() - 1; i >=0; i--) {
ret[i] = (byte)input.charAt(i);
}
return ret;
}
The above Java code produces the MD5sum 18f5f1a9bf898131945dd9e315759fe4 which is what PHP gives too
I am trying to convert a string like "testing123" into hexadecimal form in java. I am currently using BlueJ.
And to convert it back, is it the same thing except backward?
Here's a short way to convert it to hex:
public String toHex(String arg) {
return String.format("%040x", new BigInteger(1, arg.getBytes(/*YOUR_CHARSET?*/)));
}
To ensure that the hex is always 40 characters long, the BigInteger has to be positive:
public String toHex(String arg) {
return String.format("%x", new BigInteger(1, arg.getBytes(/*YOUR_CHARSET?*/)));
}
import org.apache.commons.codec.binary.Hex;
...
String hexString = Hex.encodeHexString(myString.getBytes(/* charset */));
http://commons.apache.org/codec/apidocs/org/apache/commons/codec/binary/Hex.html
Use DatatypeConverter.printHexBinary():
public static String toHexadecimal(String text) throws UnsupportedEncodingException
{
byte[] myBytes = text.getBytes("UTF-8");
return DatatypeConverter.printHexBinary(myBytes);
}
Example usage:
System.out.println(toHexadecimal("Hello StackOverflow"));
Prints:
48656C6C6F20537461636B4F766572666C6F77
Note: This causes a little extra trouble with Java 9 and newer since the API is not included by default. For reference e.g. see this GitHub issue.
The numbers that you encode into hexadecimal must represent some encoding of the characters, such as UTF-8. So first convert the String to a byte[] representing the string in that encoding, then convert each byte to hexadecimal.
public static String hexadecimal(String input, String charsetName) throws UnsupportedEncodingException {
if (input == null) throw new NullPointerException();
return asHex(input.getBytes(charsetName));
}
private static final char[] HEX_CHARS = "0123456789abcdef".toCharArray();
public static String asHex(byte[] buf)
{
char[] chars = new char[2 * buf.length];
for (int i = 0; i < buf.length; ++i)
{
chars[2 * i] = HEX_CHARS[(buf[i] & 0xF0) >>> 4];
chars[2 * i + 1] = HEX_CHARS[buf[i] & 0x0F];
}
return new String(chars);
}
Here an other solution
public static String toHexString(byte[] ba) {
StringBuilder str = new StringBuilder();
for(int i = 0; i < ba.length; i++)
str.append(String.format("%x", ba[i]));
return str.toString();
}
public static String fromHexString(String hex) {
StringBuilder str = new StringBuilder();
for (int i = 0; i < hex.length(); i+=2) {
str.append((char) Integer.parseInt(hex.substring(i, i + 2), 16));
}
return str.toString();
}
All answers based on String.getBytes() involve encoding your string according to a Charset. You don't necessarily get the hex value of the 2-byte characters that make up your string. If what you actually want is the equivalent of a hex viewer, then you need to access the chars directly. Here's the function that I use in my code for debugging Unicode issues:
static String stringToHex(String string) {
StringBuilder buf = new StringBuilder(200);
for (char ch: string.toCharArray()) {
if (buf.length() > 0)
buf.append(' ');
buf.append(String.format("%04x", (int) ch));
}
return buf.toString();
}
Then, stringToHex("testing123") will give you:
0074 0065 0073 0074 0069 006e 0067 0031 0032 0033
byte[] bytes = string.getBytes(CHARSET); // you didn't say what charset you wanted
BigInteger bigInt = new BigInteger(bytes);
String hexString = bigInt.toString(16); // 16 is the radix
You could return hexString at this point, with the caveat that leading null-chars will be stripped, and the result will have an odd length if the first byte is less than 16. If you need to handle those cases, you can add some extra code to pad with 0s:
StringBuilder sb = new StringBuilder();
while ((sb.length() + hexString.length()) < (2 * bytes.length)) {
sb.append("0");
}
sb.append(hexString);
return sb.toString();
To get the Integer value of hex
//hex like: 0xfff7931e to int
int hexInt = Long.decode(hexString).intValue();
I would suggest something like this, where str is your input string:
StringBuffer hex = new StringBuffer();
char[] raw = tokens[0].toCharArray();
for (int i=0;i<raw.length;i++) {
if (raw[i]<=0x000F) { hex.append("000"); }
else if(raw[i]<=0x00FF) { hex.append("00" ); }
else if(raw[i]<=0x0FFF) { hex.append("0" ); }
hex.append(Integer.toHexString(raw[i]).toUpperCase());
}
Java 17 introduces a utility class for hexadecimal formatting: java.util.HexFormat
Convert to hex:
public String toHex(String value) {
return HexFormat.of().formatHex(value.getBytes());
}
Convert from hex:
public String fromHex(String value) {
return new String(HexFormat.of().parseHex(value));
}
More about HexFormat here
Documentation: here
Convert a letter in hex code and hex code in letter.
String letter = "a";
String code;
int decimal;
code = Integer.toHexString(letter.charAt(0));
decimal = Integer.parseInt(code, 16);
System.out.println("Hex code to " + letter + " = " + code);
System.out.println("Char to " + code + " = " + (char) decimal);
To go the other way (hex to string), you can use
public String hexToString(String hex) {
return new String(new BigInteger(hex, 16).toByteArray());
}
One line HEX encoding/decoding without external libs (Java 8 and above):
Encoding :
String hexString = inputString.chars().mapToObj(c ->
Integer.toHexString(c)).collect(Collectors.joining());
Decoding :
String decodedString = Stream.iterate(0, i -> i+2)
.limit(hexString.length()/2 + Math.min(hexString.length()%2,1))
.map(i -> "" + (char)Integer.parseInt("" + hexString.charAt(i) + hexString.charAt(i+1),16))
.collect(Collectors.joining());
First convert it into bytes using getBytes() function and then convert it into hex usign this :
private static String hex(byte[] bytes) {
StringBuilder sb = new StringBuilder();
for (int i=0; i<bytes.length; i++) {
sb.append(String.format("%02X ",bytes[i]));
}
return sb.toString();
}
Using Multiple Peoples help from multiple Threads..
I know this has been answered, but i would like to give a full encode & decode method for any others in my same situation..
Here's my Encoding & Decoding methods..
// Global Charset Encoding
public static Charset encodingType = StandardCharsets.UTF_8;
// Text To Hex
public static String textToHex(String text)
{
byte[] buf = null;
buf = text.getBytes(encodingType);
char[] HEX_CHARS = "0123456789abcdef".toCharArray();
char[] chars = new char[2 * buf.length];
for (int i = 0; i < buf.length; ++i)
{
chars[2 * i] = HEX_CHARS[(buf[i] & 0xF0) >>> 4];
chars[2 * i + 1] = HEX_CHARS[buf[i] & 0x0F];
}
return new String(chars);
}
// Hex To Text
public static String hexToText(String hex)
{
int l = hex.length();
byte[] data = new byte[l / 2];
for (int i = 0; i < l; i += 2)
{
data[i / 2] = (byte) ((Character.digit(hex.charAt(i), 16) << 4)
+ Character.digit(hex.charAt(i + 1), 16));
}
String st = new String(data, encodingType);
return st;
}
Much better:
public static String fromHexString(String hex, String sourceEncoding ) throws IOException{
ByteArrayOutputStream bout = new ByteArrayOutputStream();
byte[] buffer = new byte[512];
int _start=0;
for (int i = 0; i < hex.length(); i+=2) {
buffer[_start++] = (byte)Integer.parseInt(hex.substring(i, i + 2), 16);
if (_start >=buffer.length || i+2>=hex.length()) {
bout.write(buffer);
Arrays.fill(buffer, 0, buffer.length, (byte)0);
_start = 0;
}
}
return new String(bout.toByteArray(), sourceEncoding);
}
import java.io.*;
import java.util.*;
public class Exer5{
public String ConvertToHexadecimal(int num){
int r;
String bin="\0";
do{
r=num%16;
num=num/16;
if(r==10)
bin="A"+bin;
else if(r==11)
bin="B"+bin;
else if(r==12)
bin="C"+bin;
else if(r==13)
bin="D"+bin;
else if(r==14)
bin="E"+bin;
else if(r==15)
bin="F"+bin;
else
bin=r+bin;
}while(num!=0);
return bin;
}
public int ConvertFromHexadecimalToDecimal(String num){
int a;
int ctr=0;
double prod=0;
for(int i=num.length(); i>0; i--){
if(num.charAt(i-1)=='a'||num.charAt(i-1)=='A')
a=10;
else if(num.charAt(i-1)=='b'||num.charAt(i-1)=='B')
a=11;
else if(num.charAt(i-1)=='c'||num.charAt(i-1)=='C')
a=12;
else if(num.charAt(i-1)=='d'||num.charAt(i-1)=='D')
a=13;
else if(num.charAt(i-1)=='e'||num.charAt(i-1)=='E')
a=14;
else if(num.charAt(i-1)=='f'||num.charAt(i-1)=='F')
a=15;
else
a=Character.getNumericValue(num.charAt(i-1));
prod=prod+(a*Math.pow(16, ctr));
ctr++;
}
return (int)prod;
}
public static void main(String[] args){
Exer5 dh=new Exer5();
Scanner s=new Scanner(System.in);
int num;
String numS;
int choice;
System.out.println("Enter your desired choice:");
System.out.println("1 - DECIMAL TO HEXADECIMAL ");
System.out.println("2 - HEXADECIMAL TO DECIMAL ");
System.out.println("0 - EXIT ");
do{
System.out.print("\nEnter Choice: ");
choice=s.nextInt();
if(choice==1){
System.out.println("Enter decimal number: ");
num=s.nextInt();
System.out.println(dh.ConvertToHexadecimal(num));
}
else if(choice==2){
System.out.println("Enter hexadecimal number: ");
numS=s.next();
System.out.println(dh.ConvertFromHexadecimalToDecimal(numS));
}
}while(choice!=0);
}
}
new BigInteger(1, myString.getBytes(/*YOUR_CHARSET?*/)).toString(16)
Here are some benchmarks comparing different approaches and libraries. Guava beats Apache Commons Codec at decoding. Commons Codec beats Guava at encoding. And JHex beats them both for decoding and encoding.
JHex example
String hexString = "596f752772652077656c636f6d652e";
byte[] decoded = JHex.decodeChecked(hexString);
System.out.println(new String(decoded));
String reEncoded = JHex.encode(decoded);
Everything is in a single class file for JHex. Feel free to copy paste if you don't want yet another library in your dependency tree. Also note, it is only available as Java 9 jar until I can figure out how to publish multiple release targets with Gradle and the Bintray plugin.
Convert String to Hexadecimal:
public String hexToString(String hex) {
return Integer.toHexString(Integer.parseInt(hex));
}
definitely this is the easy way.
check this solution for String to hex and hex to String vise-versa
public class TestHexConversion {
public static void main(String[] args) {
try{
String clearText = "testString For;0181;with.love";
System.out.println("Clear Text = " + clearText);
char[] chars = clearText.toCharArray();
StringBuffer hex = new StringBuffer();
for (int i = 0; i < chars.length; i++) {
hex.append(Integer.toHexString((int) chars[i]));
}
String hexText = hex.toString();
System.out.println("Hex Text = " + hexText);
String decodedText = HexToString(hexText);
System.out.println("Decoded Text = "+decodedText);
} catch (Exception e){
e.printStackTrace();
}
}
public static String HexToString(String hex){
StringBuilder finalString = new StringBuilder();
StringBuilder tempString = new StringBuilder();
for( int i=0; i<hex.length()-1; i+=2 ){
String output = hex.substring(i, (i + 2));
int decimal = Integer.parseInt(output, 16);
finalString.append((char)decimal);
tempString.append(decimal);
}
return finalString.toString();
}
Output as follows :
Clear Text = testString For;0181;with.love
Hex Text = 74657374537472696e6720466f723b303138313b776974682e6c6f7665
Decoded Text = testString For;0181;with.love
A short and convenient way to convert a String to its Hexadecimal notation is:
public static void main(String... args){
String str = "Hello! This is test string.";
char ch[] = str.toCharArray();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < ch.length; i++) {
sb.append(Integer.toHexString((int) ch[i]));
}
System.out.println(sb.toString());
}