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.
Related
I am trying to add data to the zip file header field. Specifically into the extra field specified in the zip header using java. Is it possible ?
public class test {
public static void main(String[] args) {
String path = "finalName.zip";
RandomAccessFile file = null;
try {
file = new RandomAccessFile(path, "rw");
byte[] buf = new byte[(int) file.length() / 1024];
file.read(buf);
byte[] newHeader = "NEW DATA".getBytes();
System.out.println("Original zip : " + bytesToHex(buf));
System.out.println("newHeader : " + bytesToHex(newHeader));
int length = newHeader.length;
buf[28] = (byte) length;
byte[] firstPart = Arrays.copyOf(buf, 30);
byte[] endPart = Arrays.copyOfRange(buf, 30, buf.length );
System.out.println("firstPart zip original : " + bytesToHex(firstPart));
System.out.println("endPart zip original : " + bytesToHex(endPart));
byte[] firstPartAndHeader = new byte[30 + length];
System.arraycopy(firstPart, 0, firstPartAndHeader, 0, firstPart.length);
System.arraycopy(newHeader, 0, firstPartAndHeader, firstPart.length, newHeader.length);
System.out.println("firstPartAndHeader zip original : " + bytesToHex(firstPartAndHeader));
byte[] combined = new byte[firstPartAndHeader.length + endPart.length];
System.arraycopy(firstPartAndHeader, 0, combined, 0, firstPartAndHeader.length);
System.arraycopy(endPart, 0, combined, firstPartAndHeader.length, endPart.length);
System.out.println("combined zip original : " + bytesToHex(combined));
file.seek(0);
file.write(combined);
file.close();
} catch (IOException e) {
e.printStackTrace();
}
}
private final 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);
}
}
The way I did is corrupting the file. I have added the length of the extra header in byte 28 and the extra header from byte 30. Is there something more that needs to be done ?
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();
}
}
As said in the title, I must read a binary file where specifications are written here :
https://osu.ppy.sh/wiki/Db_(file_format)#collection.db
It's written by a program written in C#. Except I don't have an idea on how to proceed to get the datas, an to store them into objects.
Any ideas or examples on the way to proceed ? Thanks a lot :)
According to specification:
import java.io.*;
import java.nio.*;
import java.util.*;
public class OsuReader
{
public static void main(String[] args) throws IOException
{
String kind = args[0];
OsuReader reader = new OsuReader(args[1]);
if (kind.equals("collection"))
{
CollectionDB db = reader.readCollectionDB();
System.out.printf("Version: %d\n", db.version);
for (CollectionItem item : db.collections)
{
System.out.println();
System.out.printf("Name: %s\n", item.name);
for (String hash : item.md5Hashes)
{
System.out.printf(" Hash: %s\n", hash);
}
}
}
else if (kind.equals("scores"))
{
ScoresDB db = reader.readScoresDB();
System.out.printf("Version: %d", db.version);
for (Beatmap beatmap : db.beatmaps)
{
System.out.println("---");
System.out.printf("Beatmap hash: %s\n", beatmaps.hash);
for (Score score : beatmaps.scores)
{
System.out.println(" ---");
System.out.printf(" Mode: %s (%d)\n", score.mode.name(), score.mode.byteValue);
System.out.printf(" Version: %d\n", score.version);
System.out.printf(" Beatmap MD5: %s\n", score.beatmapMd5Hash);
System.out.printf(" Player name: %s\n", score.playerName);
System.out.printf(" Replay MD5: %s\n", score.replayMd5Hash);
System.out.printf(" Scores: %d / %d / %d / %d / %d / %d\n",
score.numberOf300s, score.numberOf100s, score.numberOf50s, score.numberOfGekis,
score.numberOfKatus, score.numberOfMisses);
System.out.printf(" Replay score: %d\n", score.replayScore);
System.out.printf(" Max combo: %d\n", score.maxCombo);
System.out.printf(" Perfect combo: %s\n", score.perfectCombo ? "Yes" : "No");
System.out.printf(" Mods used: %s\n", score.modsUsed);
System.out.printf(" Timestamp: %s\n", score.timestamp);
}
}
}
}
private DataInputStream reader;
public OsuReader(String filename) throws IOException
{
this(new FileInputStream(filename));
}
public OsuReader(InputStream source)
{
this.reader = new DataInputStream(source);
}
// --- Primitive values ---
public byte readByte() throws IOException
{
// 1 byte
return this.reader.readByte();
}
public short readShort() throws IOException
{
// 2 bytes, little endian
byte[] bytes = new byte[2];
this.reader.readFully(bytes);
ByteBuffer bb = ByteBuffer.wrap(bytes).order(ByteOrder.LITTLE_ENDIAN);
return bb.getShort();
}
public int readInt() throws IOException
{
// 4 bytes, little endian
byte[] bytes = new byte[4];
this.reader.readFully(bytes);
ByteBuffer bb = ByteBuffer.wrap(bytes).order(ByteOrder.LITTLE_ENDIAN);
return bb.getInt();
}
public long readLong() throws IOException
{
// 8 bytes, little endian
byte[] bytes = new byte[8];
this.reader.readFully(bytes);
ByteBuffer bb = ByteBuffer.wrap(bytes).order(ByteOrder.LITTLE_ENDIAN);
return bb.getLong();
}
public int readULEB128() throws IOException
{
// variable bytes, little endian
// MSB says if there will be more bytes. If cleared,
// that byte is the last.
int value = 0;
for (int shift = 0; shift < 32; shift += 7)
{
byte b = this.reader.readByte();
value |= ((int) b & 0x7F) << shift;
if (b >= 0) return value; // MSB is zero. End of value.
}
throw new IOException("ULEB128 too large");
}
public float readSingle() throws IOException
{
// 4 bytes, little endian
byte[] bytes = new byte[4];
this.reader.readFully(bytes);
ByteBuffer bb = ByteBuffer.wrap(bytes).order(ByteOrder.LITTLE_ENDIAN);
return bb.getFloat();
}
public double readDouble() throws IOException
{
// 8 bytes little endian
byte[] bytes = new byte[8];
this.reader.readFully(bytes);
ByteBuffer bb = ByteBuffer.wrap(bytes).order(ByteOrder.LITTLE_ENDIAN);
return bb.getDouble();
}
public boolean readBoolean() throws IOException
{
// 1 byte, zero = false, non-zero = true
return this.reader.readBoolean();
}
public String readString() throws IOException
{
// variable length
// 00 = empty string
// 0B <length> <char>* = normal string
// <length> is encoded as an LEB, and is the byte length of the rest.
// <char>* is encoded as UTF8, and is the string content.
byte kind = this.reader.readByte();
if (kind == 0) return "";
if (kind != 11)
{
throw new IOException(String.format("String format error: Expected 0x0B or 0x00, found 0x%02X", (int) kind & 0xFF));
}
int length = readULEB128();
if (length == 0) return "";
byte[] utf8bytes = new byte[length];
this.reader.readFully(utf8bytes);
return new String(utf8bytes, "UTF-8");
}
public Date readDate() throws IOException
{
long ticks = readLong();
long TICKS_AT_EPOCH = 621355968000000000L;
long TICKS_PER_MILLISECOND = 10000;
return new Date((ticks - TICKS_AT_EPOCH)/TICKS_PER_MILLISECOND);
}
// --- Composite structures ---
public CollectionDB readCollectionDB() throws IOException
{
CollectionDB result = new CollectionDB();
result.version = readInt();
int count = readInt();
result.collections = new ArrayList<CollectionItem>(count);
for (int i = 0; i < count; i++)
{
CollectionItem item = readCollectionItem();
result.collections.add(item);
}
return result;
}
public CollectionItem readCollectionItem() throws IOException
{
CollectionItem item = new CollectionItem();
item.name = readString();
int count = readInt();
item.md5Hashes = new ArrayList<String>(count);
for (int i = 0; i < count; i++)
{
String md5Hash = readString();
item.md5Hashes.add(md5Hash);
}
return item;
}
public ScoresDB readScoresDB() throws IOException
{
ScoresDB result = new ScoresDB();
result.version = readInt();
int count = readInt();
result.beatmaps = new ArrayList<Beatmap>(count);
for (int i = 0; i < count; i++)
{
Beatmap beatmap = readBeatmap();
result.beatmaps.add(beatmap);
}
return result;
}
public Beatmap readBeatmap() throws IOException
{
Beatmap result = new Beatmap();
result.md5Hash = readString();
int count = readInt();
result.scores = new ArrayList<Score>();
for (int i = 0; i < count; i++)
{
Score score = readScore();
result.scores.add(score);
}
return result;
}
public Score readScore() throws IOException
{
Score result = new Score();
result.mode = GameplayMode.valueOf(readByte());
result.version = readInt();
result.beatmapMd5Hash = readString();
result.playerName = readString();
result.replayMd5Hash = readString();
result.numberOf300s = readShort();
result.numberOf100s = readShort();
result.numberOf50s = readShort();
result.numberOfGekis = readShort();
result.numberOfKatus = readShort();
result.numberOfMisses = readShort();
result.replayScore = readInt();
result.maxCombo = readShort();
result.perfectCombo = readBoolean();
result.modsUsed = OsuMod.valueOf(readInt());
result.unknown1 = readString();
result.timestamp = readDate();
result.unknown2 = readInt();
result.unknown3 = readInt();
result.unknown4 = readInt();
return result;
}
public class CollectionDB
{
public int version; // 20150203
public List<CollectionItem> collections;
}
public class CollectionItem
{
public String name;
public List<String> md5Hashes;
}
public class ScoresDB
{
public int version; // 20150204
public List<Beatmap> beatmaps;
}
public class Beatmap
{
public String md5Hash;
public List<Score> scores;
}
public enum GameplayMode
{
OsuStandard((byte) 0),
Taiko((byte) 1),
CTB((byte) 2),
Mania((byte) 3);
public final byte byteValue;
private GameplayMode(byte byteValue)
{
this.byteValue = byteValue;
}
public static GameplayMode valueOf(byte byteValue)
{
for (GameplayMode item : values())
{
if (item.byteValue == byteValue) return item;
}
throw new IllegalArgumentException("byteValue");
}
}
public enum OsuMod
{
NoFail(1),
Easy(2),
NoVideo(4),
Hidden(8),
HardRock(16),
SuddenDeath(32),
DoubleTime(64),
Relax(128),
HalfTime(256),
Nightcore(512),
Flashlight(1024),
Autoplay(2048),
SpunOut(4096),
Relax2(8192),
Perfect(16384),
Key4(32768),
Key5(65536),
Key6(131072),
Key7(262144),
Key8(524288),
keyMod(1015808),
FadeIn(1048576),
Random(2097152),
LastMod(4194304);
public final int bit;
private OsuMod(int bit)
{
this.bit = bit;
}
public static EnumSet<OsuMod> valueOf(int bits)
{
EnumSet<OsuMod> result = EnumSet.noneOf(OsuMod.class);
for (OsuMod flag : OsuMod.values())
{
if ((bits & flag.bit) == flag.bit)
{
result.add(flag);
}
}
return result;
}
}
public class Score
{
public GameplayMode mode;
public int version; // 20150203
public String beatmapMd5Hash;
public String playerName;
public String replayMd5Hash;
public short numberOf300s;
public short numberOf100s;
public short numberOf50s;
public short numberOfGekis;
public short numberOfKatus;
public short numberOfMisses;
public int replayScore;
public short maxCombo;
public boolean perfectCombo;
public EnumSet<OsuMod> modsUsed;
public String unknown1;
public Date timestamp;
public int unknown2;
public int unknown3;
public int unknown4;
}
}
So ! Because the specifications are :
First : int -> number of version
Second : int -> number of collections
But ! All the integers are unsigned and little-endian. So I did this !
public static void main(String[] args) {
try {
DataInputStream in = new DataInputStream(new BufferedInputStream(new FileInputStream("src/collection/collection.db")));
byte b1 = in.readByte();
byte b2 = in.readByte();
byte b3 = in.readByte();
byte b4 = in.readByte();
int s = 0;
s = s | (b4 & 0xff);
s = (s << 8);
s = s | (b3 & 0xff);
s = (s << 8);
s = s | (b2 & 0xff);
s = (s << 8);
s = s | (b1 & 0xff);
System.out.println("Version des collections : " + s);
b1 = in.readByte();
b2 = in.readByte();
b3 = in.readByte();
b4 = in.readByte();
s = 0;
s = s | (b4 & 0xff);
s = (s << 8);
s = s | (b3 & 0xff);
s = (s << 8);
s = s | (b2 & 0xff);
s = (s << 8);
s = s | (b1 & 0xff);
System.out.println("Nombre de collections : " +s);
} catch (Exception e) {
System.out.print("mdr fail");
}
}
I hope I helped people who are searching too.
I am parsing an array into multiple smaller arrays but the returned result to my main is the last object in the original array. I understand why it is happening but I don't know how to fix it.
Here is my main class calling my class parseUDP to parse the array:
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
public class MarketDataReader {
public static void main(String[] args) {
try {
byte[] i = null;
//byte[] decodedArray = null;
String readableMessage = "Null Null";
ipaddrConnection ip = new ipaddrConnection();
parseUDP p = new parseUDP();
DecodeMessage message = new DecodeMessage();
while(1==1){
i = ip.getPacket();
byte[] decodedArray = p.parseUDP(i);
//decodedArray = p.
StringBuilder sb = new StringBuilder();
for (byte b : decodedArray)
{
sb.append(String.format("%02X ", b));
}
System.out.println("new: " + sb.toString());
//readableMessage = message.decode(decodedArray);
//System.out.println(readableMessage);
}
} catch (IOException ex) {
Logger.getLogger(MarketDataReader.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
Here is my class to parse the original Array into smaller arrays:
public class parseUDP {
public byte[] parseUDP(byte[] i) {
final ByteBuffer buffer = ByteBuffer.wrap(i);
byte[] newArr = null;
byte[] headerArr = new byte[12];
byte[] head;
byte[] completeArray= null;
head = Arrays.copyOf(i, 12);
buffer.get(headerArr);
while (buffer.hasRemaining()) {
buffer.order(ByteOrder.LITTLE_ENDIAN);
buffer.mark();
int length = buffer.getShort() & 0xffff;
if (length == 0) {
break;
}
//System.out.println(length);
newArr = new byte[length];
buffer.reset();
buffer.get(newArr, 0, length);
completeArray = new byte[head.length + newArr.length];
for(int x = 0; x < head.length; x++)
{
completeArray[x] = head[x];
}
for(int x = head.length, j = 0; j < newArr.length; x++, j++)
{
completeArray[x] = newArr[j];
}
return completeArray;
}
return completeArray;
}
}
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;
}
}