Issue
I am working with BigInteger, and using my function I write a BigInteger of 256 bits to a file (there are 64 such numbers)
public static byte[] toHH2(BigInteger n) {
byte[] b = new byte[256];
for(int i = 0; i < 256; i+=8) {
b[i] = (byte) (n.longValue() >> (248 - i) & 0xff);
}
return b;
}
Then I need to read this 256 bit number and write it to a variable. But for some reason, I end up with a maximum of 64 bit numbers, and I need 256, how to fix the error?
var dataSignatureInt = bytesToIntArray(Files.readAllBytes(Path.of("C:\\Users\\User\\IdeaProjects\\CryptoLab1\\src\\crypto\\DigitalSignatureGOST.png")));
for(int i = 0; i < file.length; i+=256) { //file lenght = 16384
BigInteger value = BigInteger.valueOf(dataSignatureInt[i]);
for(int j = 0; j < 256; j++) {
System.out.println("i = " + i + " j = " + j);
value = BigInteger.valueOf((value.longValue() << 8) | dataSignatureInt[i + j]);
}
Solution
256 bits are 32 bytes, but somehow you do a bit per byte or such.
public static byte[] toHH2(BigInteger n) {
byte[] b = n.toByteArray(); /// <= 32 bytes in big endian order!
return Arrays.copyOf(b, 32 - b.length);
if (b.length < 32) {
byte[] b2 = new byte[256];
System.arraycopy(b, 0, b2, 32 - b.length, b.length);
if (b[0] < 0) { // Do sign extension, if most significant byte negative.
for (int j = 0; j < 32 - b.length; ++j) {
b2[j] = -1;
}
}
b = b2;
}
return b;
}
For ease I have padded it. Not needed, but it shows that the most significant byte is at index 0 of the bytes.
// Now several such 32 byte arrays are stored in the file.
var dataSignatureInt = Files.readAllBytes(Path.of(
"C:\\Users\\User\\IdeaProjects\\CryptoLab1\\src\\crypto\\DigitalSignatureGOST.png"));
int numberCount = dataSignatureInt.length / 32;
BigInteger[] numbers = new BigInteger[numberCount];
To split a large byte array into 32 byte subarrays, the class ByteBuffer
is ideal.
ByteBuffer buf = ByteBuffer.wrap(dataSignatureInt);
byte[] bytes = new byte[32];
for (int i = 0; i < numberCount; ++i) {
buf.get(bytes);
numbers[i] = new BigInteger(bytes);
}
Last but not least, you could consider using BitSet
instead of BigInteger
if you are interested in single bits.
BitSet bitSet = new BitSet(256);
byte[] shortenedBytes = bitSet.toByteArray();
bitSet = BitSet.valueOf(shortenedBytes);
Answered By - Joop Eggen
Answer Checked By - Marilyn (JavaFixing Volunteer)