I want to calculate the size of the bitcoin block - java

I want to calculate the size of the bitcoin block
And I saw the subject: link here,
and in one response someone says "merkle root hash - 32 bytes"
Then I went to this block: link here
merkle root is: 8f5318a45316efedf56ebcadd55889ab377ba78d9a8ac14a81a83e52ad45e07f
i tried to calculate the root, but it appeared with me that it was 64 bytes.
my way of calculating bytes:
byte[] bytes1 = "Here merkle root".getBytes();
System.out.println(bytes1.length);
Result 64 rather than 32

The merkle root is 32 bytes, presented with hex encoding (using 0-9a-z). That means that two characters will be used to represent each byte and the result string will have twice as many characters as the original data has bytes.
You can not convert a string to bytes by doing getBytes() as that gets the bytes representing the string.
You can parse the string into either a number (a big number) with BigInteger or into a byte array manually or using external library (not included in the JDK).
public static void main(String[] args) {
String merkle = "8f5318a45316efedf56ebcadd55889ab377ba78d9a8ac14a81a83e52ad45e07f";
System.out.println("String length: " + merkle.length());
System.out.println("Actual decimal value: " + new BigInteger(merkle, 16));
byte[] bytes = toBytes(merkle);
System.out.println("Total bytes: " + bytes.length);
System.out.println("Actual bytes: " + Arrays.toString(bytes));
}
private static byte[] toBytes(String input) {
byte[] result = new byte[input.length() / 2];
for (int i = 0; i < result.length; i++) {
result[i] = (byte)((Character.digit(input.charAt(i * 2), 16) << 4)
+ Character.digit(input.charAt(i * 2 + 1), 16));
}
return result;
}

Related

Padding Binary Output with 0's [duplicate]

for example, for 1, 2, 128, 256 the output can be (16 digits):
0000000000000001
0000000000000010
0000000010000000
0000000100000000
I tried
String.format("%16s", Integer.toBinaryString(1));
it puts spaces for left-padding:
` 1'
How to put 0s for padding. I couldn't find it in Formatter. Is there another way to do it?
P.S. this post describes how to format integers with left 0-padding, but it is not for the binary representation.
I think this is a suboptimal solution, but you could do
String.format("%16s", Integer.toBinaryString(1)).replace(' ', '0')
There is no binary conversion built into the java.util.Formatter, I would advise you to either use String.replace to replace space character with zeros, as in:
String.format("%16s", Integer.toBinaryString(1)).replace(" ", "0")
Or implement your own logic to convert integers to binary representation with added left padding somewhere along the lines given in this so.
Or if you really need to pass numbers to format, you can convert your binary representation to BigInteger and then format that with leading zeros, but this is very costly at runtime, as in:
String.format("%016d", new BigInteger(Integer.toBinaryString(1)))
Here a new answer for an old post.
To pad a binary value with leading zeros to a specific length, try this:
Integer.toBinaryString( (1 << len) | val ).substring( 1 )
If len = 4 and val = 1,
Integer.toBinaryString( (1 << len) | val )
returns the string "10001", then
"10001".substring( 1 )
discards the very first character. So we obtain what we want:
"0001"
If val is likely to be negative, rather try:
Integer.toBinaryString( (1 << len) | (val & ((1 << len) - 1)) ).substring( 1 )
You can use Apache Commons StringUtils. It offers methods for padding strings:
StringUtils.leftPad(Integer.toBinaryString(1), 16, '0');
I was trying all sorts of method calls that I haven't really used before to make this work, they worked with moderate success, until I thought of something that is so simple it just might work, and it did!
I'm sure it's been thought of before, not sure if it's any good for long string of binary codes but it works fine for 16Bit strings. Hope it helps!! (Note second piece of code is improved)
String binString = Integer.toBinaryString(256);
while (binString.length() < 16) { //pad with 16 0's
binString = "0" + binString;
}
Thanks to Will on helping improve this answer to make it work with out a loop.
This maybe a little clumsy but it works, please improve and comment back if you can....
binString = Integer.toBinaryString(256);
int length = 16 - binString.length();
char[] padArray = new char[length];
Arrays.fill(padArray, '0');
String padString = new String(padArray);
binString = padString + binString;
A simpler version of user3608934's idea "This is an old trick, create a string with 16 0's then append the trimmed binary string you got ":
private String toBinaryString32(int i) {
String binaryWithOutLeading0 = Integer.toBinaryString(i);
return "00000000000000000000000000000000"
.substring(binaryWithOutLeading0.length())
+ binaryWithOutLeading0;
}
I do not know "right" solution but I can suggest you a fast patch.
String.format("%16s", Integer.toBinaryString(1)).replace(" ", "0");
I have just tried it and saw that it works fine.
Starting with Java 11, you can use the repeat(...) method:
"0".repeat(Integer.numberOfLeadingZeros(i) - 16) + Integer.toBinaryString(i)
Or, if you need 32-bit representation of any integer:
"0".repeat(Integer.numberOfLeadingZeros(i != 0 ? i : 1)) + Integer.toBinaryString(i)
try...
String.format("%016d\n", Integer.parseInt(Integer.toBinaryString(256)));
I dont think this is the "correct" way to doing this... but it works :)
I would write my own util class with the method like below
public class NumberFormatUtils {
public static String longToBinString(long val) {
char[] buffer = new char[64];
Arrays.fill(buffer, '0');
for (int i = 0; i < 64; ++i) {
long mask = 1L << i;
if ((val & mask) == mask) {
buffer[63 - i] = '1';
}
}
return new String(buffer);
}
public static void main(String... args) {
long value = 0b0000000000000000000000000000000000000000000000000000000000000101L;
System.out.println(value);
System.out.println(Long.toBinaryString(value));
System.out.println(NumberFormatUtils.longToBinString(value));
}
}
Output:
5
101
0000000000000000000000000000000000000000000000000000000000000101
The same approach could be applied to any integral types. Pay attention to the type of mask
long mask = 1L << i;
A naive solution that work would be
String temp = Integer.toBinaryString(5);
while (temp.length() < Integer.SIZE) temp = "0"+temp; //pad leading zeros
temp = temp.substring(Integer.SIZE - Short.SIZE); //remove excess
One other method would be
String temp = Integer.toBinaryString((m | 0x80000000));
temp = temp.substring(Integer.SIZE - Short.SIZE);
This will produce a 16 bit string of the integer 5
// Below will handle proper sizes
public static String binaryString(int i) {
return String.format("%" + Integer.SIZE + "s", Integer.toBinaryString(i)).replace(' ', '0');
}
public static String binaryString(long i) {
return String.format("%" + Long.SIZE + "s", Long.toBinaryString(i)).replace(' ', '0');
}
This is an old trick, create a string with 16 0's then append the trimmed binary string you got from String.format("%s", Integer.toBinaryString(1)) and use the right-most 16 characters, lopping off any leading 0's. Better yet, make a function that lets you specify how long of a binary string you want. Of course there are probably a bazillion other ways to accomplish this including libraries, but I'm adding this post to help out a friend :)
public class BinaryPrinter {
public static void main(String[] args) {
System.out.format("%d in binary is %s\n", 1, binaryString(1, 4));
System.out.format("%d in binary is %s\n", 128, binaryString(128, 8));
System.out.format("%d in binary is %s\n", 256, binaryString(256, 16));
}
public static String binaryString( final int number, final int binaryDigits ) {
final String pattern = String.format( "%%0%dd", binaryDigits );
final String padding = String.format( pattern, 0 );
final String response = String.format( "%s%s", padding, Integer.toBinaryString(number) );
System.out.format( "\npattern = '%s'\npadding = '%s'\nresponse = '%s'\n\n", pattern, padding, response );
return response.substring( response.length() - binaryDigits );
}
}
This method converts an int to a String, length=bits. Either padded with 0s or with the most significant bits truncated.
static String toBitString( int x, int bits ){
String bitString = Integer.toBinaryString(x);
int size = bitString.length();
StringBuilder sb = new StringBuilder( bits );
if( bits > size ){
for( int i=0; i<bits-size; i++ )
sb.append('0');
sb.append( bitString );
}else
sb = sb.append( bitString.substring(size-bits, size) );
return sb.toString();
}
You can use lib https://github.com/kssource/BitSequence. It accept a number and return bynary string, padded and/or grouped.
String s = new BitSequence(2, 16).toBynaryString(ALIGN.RIGHT, GROUP.CONTINOUSLY));
return
0000000000000010
another examples:
[10, -20, 30]->00001010 11101100 00011110
i=-10->00000000000000000000000000001010
bi=10->1010
sh=10->00 0000 0000 1010
l=10->00000001 010
by=-10->1010
i=-10->bc->11111111 11111111 11111111 11110110
for(int i=0;i<n;i++)
{
for(int j=str[i].length();j<4;j++)
str[i]="0".concat(str[i]);
}
str[i].length() is length of number say 2 in binary is 01 which is length 2
change 4 to desired max length of number. This can be optimized to O(n).
by using continue.
import java.util.Scanner;
public class Q3{
public static void main(String[] args) {
Scanner scn=new Scanner(System.in);
System.out.println("Enter a number:");
int num=scn.nextInt();
int numB=Integer.parseInt(Integer.toBinaryString(num));
String strB=String.format("%08d",numB);//makes a 8 character code
if(num>=1 && num<=255){
System.out.println(strB);
}else{
System.out.println("Number should be in range between 1 and 255");
}
}
}

wrong output of CRC32 in android

I'm calculating CRC32 like code below :
import java.util.zip.CRC32;
String data = "99D5503012013165411";
byte bytes[] = data.getBytes();
Checksum checksum = new CRC32();
checksum.update(bytes, 0, bytes.length);
long checksumValue = checksum.getValue();
System.out.println("Result of CRC32 : " +Long.toHexString(checksumValue) + " !");
when I compare my code with this online CRC32 calculation it only gives me the right result when the Input type ASCII, So there is a way to have the same result as Hex?
Your problem is how you create the input (byte bytes[] = ...).
The String#getBytes method returns byte representation of individual characters in the string. But I suppose the input string 99D5503012013165411 is a hex representation of byte array.
So you have to convert it to bytes like here.
One byte is represented by two characters: see Hexadecimal on Wiki.
Update: There is another catch. One hex letter is 4bits, thus it is half of byte. A proper byte array written as hex string should be of even length.
This adds another level of confusion, since your example input is 19 chars long.
Working solution is (that gives output same as the online calc):
public static void main(String[] args)
{
String data = "99D55030120131654101"; // notice the 01 at the end
byte bytes[] = hexStringToByteArray(data);
Checksum checksum = new CRC32();
checksum.update(bytes, 0, bytes.length);
long checksumValue = checksum.getValue();
System.out.println("Result of CRC32 : " +Long.toHexString(checksumValue) + " !");
// prints: Result of CRC32 : 9671cb4a !
}
// took from https://stackoverflow.com/a/140861/6749977 :
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;
}
The online tool you linked handles the missing letter by interpreting the last 1 as 01 (I had to change the input experimentally there). So I had to change the input to be of even length...
If you are going to get really input like this, and you are sure you want to handle the case this way, the hexStringToByteArray procedure should be updated. But be careful, I thing the right way would be to prepend the whole string with zeros to have even-length. Like an base-10 analogy: 132==0123
Update 2: Based on your comment here I add a solution with modified hexStringToByteArray method (even tough I feel a bit like doing your homework for you):
public static void main(String[] args)
{
String data = "99D5503012013165411";
String dataOnlyHexChars = data.replaceAll("[^0-9a-fA-F]", ""); // not very cool
byte bytes[] = hexStringToByteArray(dataOnlyHexChars);
Checksum checksum = new CRC32();
checksum.update(bytes, 0, bytes.length);
long checksumValue = checksum.getValue();
System.out.println("Result of CRC32 : " +Long.toHexString(checksumValue) + " !");
// prints: Result of CRC32 : 9671cb4a !
}
// took from https://stackoverflow.com/a/140861/6749977 and changed a bit :
public static byte[] hexStringToByteArray(String s) {
int len = s.length();
byte[] data = new byte[(len + 1) / 2]; // changed
for (int i = 0; i < len; i += 2) {
if (len==i + 1) // changed
data[i / 2] = (byte) Character.digit(s.charAt(i), 16);
else
data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
+ Character.digit(s.charAt(i+1), 16));
}
return data;
}

How to transform hexadecimal string into Byte. Java

My problem is that I've to write a code where a MAC direction must be written via keyboard and then, the code must recognize it to mount a "Magic Packet".
Let me show some code so you can understand better my problem and maybe reach some solution.
static String realMAC[] = new String [6];
static String mac; //that's the written string
private DatagramPacket buildWOLPacket(InetAddress address,String MAC) {
String splittedMAC[] = new String[12];
final int SIZE = 6 + 6 * 16; // See above for this magic number
byte data[] = new byte[SIZE];
for (int i = 0; i < 6; i++) {
data[i] = (byte) 0xff;
}
//Method where each character written
//is stored into a char array (realMAC[])
for (int i = 0 ; i<12; i++) {
String replacedMAC = MAC.replace(":", ""); //Here I delete all the : from the MAC adress introduced via keyboard.
if (i == 12)
splittedMAC[i] = replacedMAC.substring(i,(i));
else splittedMAC[i] = replacedMAC.substring(i,(i+1));}
And now the piece of code that is giving me problems
//All the (byte) 0x00 and so on are examples of a MAC direction and how to convert it if it is predefined
data[6 * i + 0] = Byte.parseByte(realMAC[0]); //(byte) 0x00;
data[6 * i + 1] = Byte.parseByte(realMAC[1]); //(byte) 0x1A;
data[6 * i + 2] = Byte.parseByte(realMAC[2]); //(byte) 0x09;
data[6 * i + 3] = Byte.parseByte(realMAC[3]); //(byte) 0x07;
data[6 * i + 4] = Byte.parseByte(realMAC[4]); //(byte) 0x8c;
data[6 * i + 5] = Byte.parseByte(realMAC[5]); //(byte) 0xe9;
My problem comes when converting the realMAC[] into bytes because of the x and letters from (0x8c, for example) because parseByte only accepts ints and ascii code. How could I tranform that string in hex form into bits?
Thank you so much.
Byte also has a .parseByte() method taking a radix as an argument. However that won't account for the initial 0x so you have to use substring(). Do:
Byte.parseByte(realMac[0].substring(2), 16)
//etc etc
More generally, all "numeric integral" classes (Integer, Short, Long) have such a method.
Byte.decode accepts a String that may begin with 0x or 0X. (It may also parse a decimal or octal number depending on what the string looks like.)

Binary strings to Hex strings java

I have this code here, which get a plain text, and turns it to a 512-bit binary string.
Then, I would like to turn each 32-bit piece of the string to 8-bit of Hex string, but that part gives me a java.lang.NumberFormatException
// ----- Turning the message to bits
byte[] binaryS = s.getBytes("UTF-8");
String mesInBinary = "";
for (byte b : binaryS) {
mesInBinary += '0' + Integer.toBinaryString(b);
}
// ----- Message padding & Pre-Processing
// Binary representation of the length of the message in bits
String mesBitLength = Integer.toBinaryString(mesInBinary.length());
// We need the size of the message in 64-bits, so we'll
// append zeros to the binary length of the message so
// we get 64-bit
String appendedZeros = "";
for (int i = 64 - mesBitLength.length() ; i > 0 ; i--)
appendedZeros += '0';
// Calculating the k zeros to append to the message after
// the appended '1'
int numberOfZeros = (448 - (mesInBinary.length() + 1)) % 512;
// Append '1' to the message
mesInBinary += '1';
// We need a positive k
while (numberOfZeros < 0)
numberOfZeros += 512;
for (int i = 1 ; i <= numberOfZeros ; i++)
mesInBinary += '0';
// append the message length in 64-bit format
mesInBinary += appendedZeros + mesBitLength;
System.out.println(mesInBinary);
// ----- Parsing the padded message
// Breaking the message to 512-bit pieces
// And each piece, to 16 32-bit word blocks
String[] chunks = new String[mesInBinary.length() / 512];
String[] words = new String[64 * chunks.length];
for (int i = 0 ; i < chunks.length ; i++) {
chunks[i] = mesInBinary.substring((512 * i), (512 * (i + 1)));
// Break each chunk to 16 32-bit blocks
for (int j = 0 ; j < 16 ; j++) {
words[j] = Long.toHexString(Long.parseLong(chunks[i].substring((32 * j), (32 * (j + 1)))));
}
}
The last code line is the problematic one and of which I get the execption. Any suggestions?
The last statement* should specify a radix of 2, I think:
words[j] = Long.toHexString(
Long.parseLong(chunks[i].substring((32 * j), (32 * (j + 1))), 2));
*Not the last line of code, MДΓΓ :-)
From the Long docs:
public static long parseLong(String s) throws NumberFormatException:
Parses the string argument as a signed decimal long. The characters in the string must all be decimal digits...
public static long parseLong(String s, int radix) throws NumberFormatException:
Parses the string argument as a signed long in the radix specified by the second argument. The characters in the string must all be digits of the specified radix...
You're calling the first version of Long.parseLong(), which expects a decimal number, not a binary one. Use the second version with a radix of 2 to indicate binary.
EDIT: The reason being that a 32-digit decimal number won't fit into a Long, but a binary one will.
for (int i = 0 ; i < chunks.length ; i++)
{
chunks[i] = mesInBinary.substring((512 * i), (512 * (i + 1)));
// Break each chunk to 16 32-bit blocks
for (int j = 0 ; j < 16 ; j++)
{
words[j] = Long.toHexString(Long.parseLong(chunks[i].substring((32 * j), (32 * (j + 1))),2));
}
}

Getting 1 byte extra in the modulus RSA Key and sometimes for exponents also

Here is my code snippet:
int eValue = 79, t;
int bitLength = 1024; // KeySize
BigInteger e = new BigInteger(Integer.toString(eValue));
KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
kpg.initialize(bitLength);
KeyPair kp = kpg.generateKeyPair();
KeyFactory kfactory = KeyFactory.getInstance("RSA");
RSAPublicKeySpec kspec = (RSAPublicKeySpec) kfactory.getKeySpec(kp.getPublic(),
RSAPublicKeySpec.class);
System.out.println("Byte Length is : " + kspec.getModulus().toByteArray().length);
String testString;
try {
testString = new String (kspec.getModulus().toByteArray() , "ISO-8859-1");
StringBuilder tt = new StringBuilder();
for(t =0 ; t< testString.length() ; t++)
{
tt.append((int) testString.charAt(t)+",");
}
String encryptedBytes = tt.toString();
System.out.println("Mod is : " + encryptedBytes);
}catch (Exception ex) {
// TODO: handle exception
}
And here is the output:
Byte Length is : 129
Mod is : 0,190,193,141,230,128,124,6,201,254,135,66,162,65,147,160,76,160,181,7,141,113,8,57,193,185,206,42,125,9,169,209,124,74,233,151,10,128,180,35,24,206,213,32,48,4,39,178,60,10,249,151,50,218,220,11,124,72,64,148,135,251,133,23,54,171,25,202,157,28,21,39,239,234,48,56,79,36,127,59,203,108,189,232,216,231,237,237,90,253,19,118,29,18,142,126,254,193,189,82,15,126,139,136,45,31,133,242,187,81,62,52,5,23,11,217,171,233,7,137,115,30,93,206,236,31,196,111,153
For 1024 bit lenght key modulus should be 128 bytes and for 2048 it should be 256, but I am getting one byte extra (Adding 0 always at the very first byte), Need Help to reslove this..
Thanks,
Pawan
The reason for the 00h valued byte at the start is because BigInteger.toByteArray() returns the signed representation. As long as the key length in bits is N*8 (or key length % 8 = 0) then the signed representation of an RSA modulus will always feature a 00h valued byte at the start.
Simply remove the initial byte if it is zero by copying it into an array of the key length in bytes. Note that if you have a private exponent, it might also be shorter than the key length in bytes, so copy it to the end of the new byte array. Normally, this kind of method is known as I2OS or I2O (integer to octet string), where the octet sting (byte array in java) has a specified length.
/**
* Encodes the given value as a unsigned Big Endian within an octet string
* of octetStringSize bytes.
*
* #param i
* the integer to encode
* #param octetStringSize
* the number of octets in the octetString returned
* #return the encoding of i
* #throws IllegalArgumentException
* if the given integer i is negative
* #throws IllegalArgumentException
* if the octetStringSize is zero or lower
* #throws IllegalArgumentException
* if the given BigInteger does not fit into octetStringSize
* bytes
*/
public static byte[] integerToOctetString(final BigInteger i,
final int octetStringSize) {
// throws NullPointerException if i = null
if (i.signum() < 0) {
throw new IllegalArgumentException(
"argument i should not be negative");
}
if (octetStringSize <= 0) {
throw new IllegalArgumentException("octetStringSize argument ("
+ octetStringSize
+ ") should be higher than 0 to store any integer");
}
if (i.bitLength() > octetStringSize * Byte.SIZE) {
throw new IllegalArgumentException("argument i (" + i
+ ") does not fit into " + octetStringSize + " octets");
}
final byte[] signedEncoding = i.toByteArray();
final int signedEncodingLength = signedEncoding.length;
if (signedEncodingLength == octetStringSize) {
return signedEncoding;
}
final byte[] unsignedEncoding = new byte[octetStringSize];
if (signedEncoding[0] == (byte) 0x00) {
// skip first padding byte to create a (possitive) unsigned encoding for this number
System.arraycopy(signedEncoding, 1, unsignedEncoding,
octetStringSize - signedEncodingLength + 1,
signedEncodingLength - 1);
} else {
System.arraycopy(signedEncoding, 0, unsignedEncoding,
octetStringSize - signedEncodingLength,
signedEncodingLength);
}
return unsignedEncoding;
}
/**
* Returns a BigInteger that is the value represented by the unsigned, Big
* Endian encoding within the given octetString.
*
* #param octetString
* the octetString containing (only) the encoding
* #return the value represented by the octetString
*/
public static BigInteger octetStringToInteger(final byte[] octetString) {
// arguments are signum, magnitude as unsigned, Big Endian encoding
return new BigInteger(1, octetString);
}
/**
* Returns the minimum number of bytes required to directly store the given
* number of bits.
*
* #param bitSize
* the bitSize
* #return the size as a number of bytes
* #throws IllegalArgumentException
* if the given bitSize argument is negative
*/
public static int bitSizeToByteSize(final int bitSize) {
if (bitSize < 0) {
throw new IllegalArgumentException("bitSize (" + bitSize
+ " should not be negative");
}
return (bitSize + Byte.SIZE - 1) / Byte.SIZE;
}
You can use Arrays.deepToString() to print a byte array directly:
String encryptedBytes = Arrays.deepToString(new Object[] { kspec.getModulus().toByteArray() })
I suspect you are having trouble with signed vs. unsigned numbers. The 128-bit modulus is unsigned, but to store it in a BigInteger might sometimes take 129 bits, hence the extra byte.
As Maarten Bodewes has answered, the extra byte is space for the BigInteger's sign.
If the expected size is known and Hex is acceptable, i would use something like this:
System.out.printf("Mod is : %0256x%n" , kspec.getModulus());
This question is best answered in the following Stackoverflow link. The solution is also very simple and applies to all cryptography applications because the length of all crypto keys are exact multiples of 8.
BigInteger to byte[]

Categories