Potential use for data that contains its own hash? - java

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

Adding data to zip file header

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 ?

File Hash Generator in Command Prompt using File Path

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();
}
}

Parse the osu! binary database in Java

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.

parsed array only returns last object

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;
}
}

convert a byte to string then string to byte but not equal

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;
}
}

Categories

Resources