It was hard for me to explain in the title, but I would like to create a program which takes certain text, say hello0, hash it in sha256, and see if it has two leading zeros. If so, print hash. If not, make it hello1, then hello2 and so on until two leading zeros are found. Here is a few ways I found on how to create my sha256 hash from text:
import java.security.MessageDigest;
public class sha
{
public static void main(String[] args)throws Exception
{
int yeah = 40;
String password = "previousblock14currentblock" + yeah;
MessageDigest md = MessageDigest.getInstance("SHA-256");
md.update(password.getBytes());
byte byteData[] = md.digest();
//convert the byte to hex format method 1
StringBuffer sb = new StringBuffer();
for (int i = 0; i < byteData.length; i++) {
sb.append(Integer.toString((byteData[i] & 0xff) + 0x100, 16).substring(1));
}
System.out.println("Hex format : " + sb.toString());
StringBuffer hexString = new StringBuffer();
for (int i=0;i<byteData.length;i++) {
String hex=Integer.toHexString(0xff & byteData[i]);
if(hex.length()==1) hexString.append('0');
hexString.append(hex);
}
System.out.println("Hex format : " + hexString.toString());
}
}
When you run the code you receive Hex format : 0a0a30b1031fa60b8fa9478a070b03333df75017fd61c1b1c7e16bd929831ef5. This has one leading zero but I want two. I don't know what to do next, but i believe I set everything up correctly. How would I go about creating a while or if statement, each time adding yeah by 1? Would this be the best way of doing it?
The issue is that when I create a while loop the sha256 hash wont update, so it always prints 0a0a30b1031fa60b8fa9478a070b03333df75017fd61c1b1c7e16bd929831ef5. I'm wondering if I'm doing something wrong and wanted to see how someone else would do it.
thank you for your help.
public class Sha {
private static String byteArrayToHexString(byte[] array) {
StringBuffer sb = new StringBuffer();
for (int i = 0; i < array.length; i++) {
sb.append(Integer.toString((array[i] & 0xff) + 0x100, 16).substring(1));
}
return sb.toString();
}
public static void main(String[] args) throws Exception {
final int MAX_PASS_ATTEMPTS = 40000;
final String PASS_PREFIX = "previousblock14currentblock";
MessageDigest md = MessageDigest.getInstance("SHA-256");
for (int i = 0; i < MAX_PASS_ATTEMPTS; i++) {
String password = PASS_PREFIX + i;
md.reset();
md.update(password.getBytes());
byte[] hash = md.digest();
//System.out.println(byteArrayToHexString(hash));
if (hash[0] == 0 && hash[1] == 0) {
System.out.println("Password: " + password);
System.out.println("Hash: " + byteArrayToHexString(hash));
return;
}
}
System.out.println("No luck after " + MAX_PASS_ATTEMPTS + " tries.");
}
}
By the way, this is the great resource to learn about Java control flow statements.
I am currently trying to recreate a Google One Time Password generator. I use a shared secret generated when I setup Google Authenticator.
I tried looking into the Google Authenticator sources and all around the internet really and I find a lot of similarities with my code but I can't really find where i'm wrong.
The first part seems correct. As for the hmac, I don't think I could mess up here but I might be wrong. The truncating part is still a bit blurry for me and I tried a lot of different implementations but I just cannot get a working OTP. (I'm using Google Authenticator to compare the results)
private String truncateHash(byte[] hash) {
int offset = hash[hash.length - 1] & 0xF;
long truncatedHash = 0;
for (int i = 0; i < 4; ++i) {
truncatedHash <<= 8;
truncatedHash |= (hash[offset + i] & 0xFF);
}
truncatedHash &= 0x7FFFFFFF;
truncatedHash %= 1000000;
int code = (int) truncatedHash;
String result = Integer.toString(code);
for (int i = result.length(); i < 6; i++) {
result = "0" + result;
}
return result;
}
private byte[] hmacSha1(byte[] value, byte[] keyBytes) {
try {
Mac mac = HmacUtils.getHmacSha1(keyBytes);
byte[] rawHmac = mac.doFinal(value);
return new Hex().encode(rawHmac);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public String GoogleAuthenticatorCode(String secret) throws UnsupportedEncodingException {
Base32 base = new Base32();
byte[] key = base.decode(secret);
//Update from Andrew Rueckert's response
long value = new Date().getTime() / TimeUnit.SECONDS.toMillis(30);
byte[] data = new byte[8];
for (int i = 8; i-- > 0; value >>>= 8) {
data[i] = (byte) value;
}
//
System.out.println("Time remaining : " + new Date().getTime() / 1000 % 30);
byte[] hash = hmacSha1(data, key);
return truncateHash(hash);
}
UPDATE :
I tried copying and pasting the code from Andrew Rueckert's response's link as well as this one https://github.com/wstrange/GoogleAuth/blob/master/src/main/java/com/warrenstrange/googleauth/GoogleAuthenticator.java and the one from RFC 4226. Neither of these give me a correct OTP
Can anyone enlighten me please?
Your byte value[] needs to be the byte representation of the time as a long, and it looks like it's currently the byte representation of that number as a String of digit characters. Instead of
Double time = floor(new Date().getTime() / 1000 / 30);
String message = String.valueOf(time.intValue());
byte[] value = message.getBytes("UTF-8");
byte[] hash = hmacSha1(value, key);
You'd want something like:
// decimal truncation is free when dealing with int/long
long value = new Date().getTime() / 1000 / 30;
byte[] data = new byte[8];
for (int i = 8; i-- > 0; value >>>= 8) {
data[i] = (byte) value;
}
byte[] hash = hmacSha1(data, key);
I managed to get a Google TOTP implementation set up by following this guide, if you want one more resource to look into.
I solved my problem so I thought I would post it there in case someone needs it.
It was partialy due to the Base32 class I was using which didn't return a correct key. The truncating wasn't correct either.
It's compatible with Google Authenticator app.
import org.apache.commons.codec.binary.Hex;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.util.Date;
import java.util.concurrent.TimeUnit;
public class Authentication {
Authentication() {};
private String truncateHash(byte[] hash) {
String hashString = new String(hash);
int offset = Integer.parseInt(hashString.substring(hashString.length() - 1, hashString.length()), 16);
String truncatedHash = hashString.substring(offset * 2, offset * 2 + 8);
int val = Integer.parseUnsignedInt(truncatedHash, 16) & 0x7FFFFFFF;
String finalHash = String.valueOf(val);
finalHash = finalHash.substring(finalHash.length() - 6, finalHash.length());
return finalHash;
}
private byte[] hmacSha1(byte[] value, byte[] keyBytes) {
SecretKeySpec signKey = new SecretKeySpec(keyBytes, "HmacSHA1");
try {
Mac mac = Mac.getInstance("HmacSHA1");
mac.init(signKey);
byte[] rawHmac = mac.doFinal(value);
return new Hex().encode(rawHmac);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public String GoogleAuthenticatorCode(String secret) throws Exception {
if (secret == null || secret == "") {
throw new Exception("Secret key does not exist.");
}
long value = new Date().getTime() / TimeUnit.SECONDS.toMillis(30);
Base32 base = new Base32(Base32.Alphabet.BASE32, false, true);
byte[] key = base.fromString(secret);
byte[] data = new byte[8];
for (int i = 8; i-- > 0; value >>>= 8) {
data[i] = (byte) value;
}
byte[] hash = hmacSha1(data, key);
return truncateHash(hash);
}
}
The Base32 I used is available here if needed along with the rest of the project : https://github.com/Poncholay/OTPGenerator/blob/master/src/main/java/com/requireris/app/web/rest/Base32.java
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 this method below in java and need the exact equivalent in PHP as both hashes are being compared..
The Java Method Is:
public String getMD5(String inStr)
{
MessageDigest md5 = null;
try {
md5 = MessageDigest.getInstance("MD5");
} catch (Exception e) {
e.printStackTrace();
}
char[] charArray = inStr.toCharArray();
byte[] byteArray = new byte[charArray.length];
for (int i = 0; i < charArray.length; i++)
byteArray[i] = (byte) charArray[i];
byte[] md5Bytes = md5.digest(byteArray);
StringBuffer hexValue = new StringBuffer();
for (int i = 0; i < md5Bytes.length; i++) {
int val = ((int) md5Bytes[i]) & 0xff;
if (val < 16)
hexValue.append("0");
hexValue.append(Integer.toHexString(val));
}
return hexValue.toString();
}
I am currently using the crypt method for php.
Any ideas?
Thanks.
Is this not working for you?
$str = 'apple';
$hash = md5($str);
This would generate a md5 hash in php. Are the output of both functions not equal?
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());
}