Convert sha256 string to number - Java - java

The code below in JS converts a Hash to a number, but I tried to write a similar code in Java and both return different results.
What's the best way to get the same result shown in JS using Java?
JS
const hash = "806abe48226985c5fb0e878792232204d74643e190e25a4c20a97748d52b191c"
console.log(parseInt(hash, 16) % 11);
Result:
2
Java
String hash = "806abe48226985c5fb0e878792232204d74643e190e25a4c20a97748d52b191c";
BigInteger bigInt = new BigInteger(hash, 16);
System.out.println(bigInt.mod(BigInteger.valueOf(11)).intValue());
Result:
4

The correct value is 4. The result from the JavaScript snippet is incorrect, as the number is too large to be represented accurately. Use BigInt instead.
const hash = "806abe48226985c5fb0e878792232204d74643e190e25a4c20a97748d52b191c"
console.log(Number.isSafeInteger(parseInt(hash, 16))); // do not use this!
console.log((BigInt('0x' + hash) % 11n).toString());

Related

String hash vs Binary Hash in Java

I am writing a Java program that converts Bitcoin privateKey to WIF format.
Unfortunately, I got wrong SHA256 hashes.
My code is based on Basing on this tutorial.
When I hash a value like:
800C28FCA386C7A227600B2FE50B7CAE11EC86D3BF1FBE471BE89827E19D72AA1D
I get something like this as result:
e2e4146a36e9c455cf95a4f259f162c353cd419cc3fd0e69ae36d7d1b6cd2c09
instead of:
8147786C4D15106333BF278D71DADAF1079EF2D2440A4DDE37D747DED5403592
This is my piece of code:
public String getSHA(String value){
String hash = hash = DigestUtils.sha256Hex(value.getBytes());
System.out.println(hash);
return hash;
}
I used this library: import org.apache.commons.codec.digest.DigestUtils;
Of course I searched this problem on the web and I found this site.
On that website, there are two textboxes - String hash and Binary Hash.
Using a String hash, I got the same incorrect result as in my Java program.
But, using a Binary hash, I got a right result.
My question is:
What is the difference between Binary and String hashes?
How to implement Binary hash in my Java method?
In your case 800C28... is a text representation of byte[] using hex encoding. To convert it back to byte[] you can take a look at this answer, one way would be to do it is:
public static byte[] hexStringToByteArray(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));
}
return data;
}
String.getBytes() will return the character values, e.g. character 8 has a value of 56 as per the ASCII table.
System.out.println(Arrays.toString("8".getBytes())); // 56

Java Big number negative?

I tried to get bignumber from a string, but the value in binary is wrong.
priKeyData = HexByteKit.Hex2Byte("b8dfc598d14c0bb032c1f4eb1fcdb033289002f38cc16b2120dfa697f8982bef");
BigInteger priKeyBN2 = new BigInteger(priKeyData);
String s3 = priKeyBN2.toString(2);
it gives:
-100011100100000001110100110011100101110101100111111010001001111110011010011111000001011000101001110000000110010010011111100110011010111011011111111110100001100011100110011111010010100110111101101111100100000010110010110100000000111011001111101010000010001
But the right one should be:
1011100011011111110001011001100011010001010011000000101110110000001100101100000111110100111010110001111111001101101100000011001100101000100100000000001011110011100011001100000101101011001000010010000011011111101001101001011111111000100110000010101111101111
http://www.mobilefish.com/services/big_number/big_number.php
The right one is 256 bit, so it overflows in Java bignumber class?
Then how can I use this 256 bit number for some steps in Java encryption algorithm?
Thanks.
I don't know what HexByteKit is, but constructing BigInteger from the hex string gives the right result:
BigInteger priKeyBN2 = new BigInteger("b8dfc598d14c0bb032c1f4eb1fcdb033289002f38cc16b2120dfa697f8982bef", 16);
String s3 = priKeyBN2.toString(2);

Parse binary string as byte in JavaScript

I have a binary string like "11100011" and I want to convert it into a byte. I have a working example in Java like below:
byte b1 = (byte)Integer.parseInt("11100011", 2);
System.out.println(b1);
Here the output will be -29. But if I write some similar code in JavaScript like below:
parseInt('11100011', 2);
I get an output of 227.
What JavaScript code I should write to get the same output as Java?
Java is interpreting the byte as being a signed two's-complement number, which is negative since the highest bit is 1. Javascript is interpreting it as unsigned, so it's always positive.
Try this:
var b1 = parseInt('11100011', 2);
if(b1 > 127) b1 -= 256;

converting java method to jQuery function

I have to make compatible the java function with jQuery. The jQuery Real Person captcha validate function is written by java. I want to validate the captcha in jQuery. So, I tried to write the java function in jQuery. But the function could not return the right value.
Java:
private String rpHash(String value) {
int hash = 5381;
value = value.toUpperCase();
for(int i = 0; i < value.length(); i++) {
hash = ((hash << 5) + hash) + value.charAt(i);
}
return String.valueOf(hash);
}
jQuery:
function rpHash(value) {
hash = 5381;
value = value.toUpperCase();
for($i = 0; $i < value.length; $i++) {
hash = ((hash << 5) + hash) + value.charAt($i);
}
return hash;
}
It'd help if you'd post the expected result (from Java) and the actual result (from JavaScript). I tested it with the string "abc" and the Java function returns 193450027 while the JavaScript version returns "00177573ABC". Looking at these results, the problem is much easier to spot.
The problem is that you did not translate the loop body correctly. hash is an int, thus ((hash << 5) + hash) is also an int. However, value.charAt(i) is a char. What happens when Java needs to add an int to a char? Simple: a char is a Unicode character represented by two bytes. The char is extended to an int with the same Unicode value and is then added to the int.
However, JavaScript works very differently. hash is a number and value.charAt(i) is a string with one character. When adding a number to a string, the + is interpreted as a concatenation of two strings and thus the result is also a string. Since JavaScript is not statically typed, it is perfectly legal for the value of hash to change from number to string.
In further iterations, hash will (most likely) be a string holding both numerical and non-numerical characters. Thus, when evaluating hash << 5, the implicit conversion from a string to a number needed for the shifting operation silently fails and returns 0. The + hash as well as + value.charAt($i) become concatenations for the same reason as above.
Therefore, the correct translation would be to retrieve the character code rather than the character:
hash = ((hash << 5) + hash) + value.charCodeAt($i);
This will correctly result in the intended addition of two numbers.
On an unrelated note, you should write var $i = 0 instead of $i = 0 in your for initialization to prevent leaking $i to the global scope. The same applies to hash, which should be declared as var hash = 5381. Also, the convention is that variables prefixed with $ represent a jQuery object, which $i doesn't. You better just name it i like in Java.

C /C++ long long to Java long

I have a file on disk which I'm reading which has been written by c/c++ code. I know I have two 64-bit unsigned integers to read, but Java doesn't support unsigned integers, so the value I get when I do DataInputStream.readLong() is incorrect. (Ignore byte-order for now I'm actually using a derivative of DIS called LEDataInputStream which I downloaded from the web)
A lot of posts on here talk about using BigInteger but the javadoc for reading a bytearray only talks about loading a bytearray respresentation, and the questions seem centered on the fact that some people are going outside the positive bounds of the java long type, which I will be nowhere near with the data I'm reading.
I have a MATLab/Octave script which reads these long long values as two 32-bit integers each, then does some multiplying and adding to get the answer it wants too.
I suppose the question is - how do i read a 64-bit unsigned integer either using BigInteger, or using [LE]DataInputStream.XXX?
Thanks in advance
I would suggest using a ByteBuffer and then using code such as this to get what you want.
You can use a long as a 64-bit value to store unsigned data. Here is a module showing that most Unsigned operations can be performed using the standard long type. It really depends on what you want to do with the value as whether this is problem or not.
EDIT: A common approach to handling unsigned numbers is to widen the data type. This simpler in many cases but not a requirement (and for long using BigInteger doesn't make things any simpler IMHO)
EDIT2: What is wrong with the following code?
long max_unsigned = 0xFFFFFFFFFFFFFFFFl;
long min_unsigned = 0;
System.out.println(Unsigned.asString(max_unsigned) + " > "
+ Unsigned.asString(min_unsigned) + " is "
+ Unsigned.gt(max_unsigned, min_unsigned));
prints
18446744073709551615 > 0 is true
first you check out this question
Also see this
Now use of BigInteger class
// Get a byte array
byte[] bytes = new byte[]{(byte)0x12, (byte)0x0F, (byte)0xF0};
// Create a BigInteger using the byte array
BigInteger bi = new BigInteger(bytes);
// Format to binary
String s = bi.toString(2); // 100100000111111110000
// Format to octal
s = bi.toString(8); // 4407760
// Format to decimal
s = bi.toString(); // 1183728
// Format to hexadecimal
s = bi.toString(16); // 120ff0
if (s.length() % 2 != 0) {
// Pad with 0
s = "0"+s;
}
// Parse binary string
bi = new BigInteger("100100000111111110000", 2);
// Parse octal string
bi = new BigInteger("4407760", 8);
// Parse decimal string
bi = new BigInteger("1183728");
// Parse hexadecimal string
bi = new BigInteger("120ff0", 16);
// Get byte array
bytes = bi.toByteArray();

Categories