Fix overflow for DataWord calculations and add unit test for multiply

This commit is contained in:
nicksavers 2014-10-08 20:32:20 +02:00
parent 729e2822ce
commit 33b59c6583
3 changed files with 77 additions and 44 deletions

View File

@ -287,4 +287,36 @@ public class ByteUtil {
}
return address;
}
/**
* Utility function to copy a byte array into a new byte array with given size.
* If the src length is smaller than the given size, the result will be left-padded
* with zeros.
*
* @param src
* @param size
* @return Byte array of given size with a copy of the </code>src</code>
*/
public static byte[] copyToArray(byte[] src, int size) {
byte[] dest = ByteBuffer.allocate(size).array();
return copyToArray(src, dest);
}
/**
* Utility function to copy a byte array into a given byte array.
* If the src length is smaller than the given size, the result will be left-padded
* with the original bytes.
*
* @param src
* @param dest
* @param size
* @return Destination byte array filled with a copy of the </code>src</code>
*/
public static byte[] copyToArray(byte[] src, byte[] dest) {
if (src.length > dest.length)
System.arraycopy(src, src.length-dest.length, dest, 0, dest.length-1);
else
System.arraycopy(src, 0, dest, dest.length - src.length, src.length);
return dest;
}
}

View File

@ -163,26 +163,16 @@ public class DataWord implements Comparable<DataWord> {
// old add-method with BigInteger quick hack
public void add2(DataWord word) {
BigInteger result = value().add(word.value());
byte[] bytes = result.toByteArray();
ByteBuffer data = ByteBuffer.allocate(32);
System.arraycopy(bytes, 0, data.array(), 32 - bytes.length, bytes.length);
this.data = data.array();
this.data = ByteUtil.copyToArray(result.toByteArray(), 32);
}
// TODO: mul can be done in more efficient way
// TODO: with shift left shift right trick
// TODO without BigInteger quick hack
public void mul(DataWord word) {
BigInteger result = value().multiply(word.value());
byte[] bytes = result.toByteArray();
ByteBuffer data = ByteBuffer.allocate(32);
System.arraycopy(bytes, 0, data.array(), 32 - bytes.length, bytes.length);
this.data = data.array();
this.data = ByteUtil.copyToArray(result.toByteArray(), 32);
}
// TODO: improve with no BigInteger
@ -194,11 +184,7 @@ public class DataWord implements Comparable<DataWord> {
}
BigInteger result = value().divide(word.value());
byte[] bytes = result.toByteArray();
ByteBuffer data = ByteBuffer.allocate(32);
System.arraycopy(bytes, 0, data.array(), 32 - bytes.length, bytes.length);
this.data = data.array();
this.data = ByteUtil.copyToArray(result.toByteArray(), 32);
}
// TODO: improve with no BigInteger
@ -210,37 +196,25 @@ public class DataWord implements Comparable<DataWord> {
}
BigInteger result = sValue().divide(word.sValue());
byte[] bytes = result.toByteArray();
ByteBuffer data = ByteBuffer.allocate(32);
if (result.compareTo(BigInteger.ZERO) == -1)
if (result.signum() == -1)
Arrays.fill(data.array(), (byte) 0xFF);
System.arraycopy(bytes, 0, data.array(), 32 - bytes.length, bytes.length);
this.data = data.array();
this.data = ByteUtil.copyToArray(result.toByteArray(), data.array());
}
// TODO: improve with no BigInteger
public void sub(DataWord word) {
BigInteger result = value().subtract(word.value());
byte[] bytes = result.toByteArray();
ByteBuffer data = ByteBuffer.allocate(32);
System.arraycopy(bytes, 0, data.array(), 32 - bytes.length, bytes.length);
this.data = data.array();
this.data = ByteUtil.copyToArray(result.toByteArray(), 32);
}
// TODO: improve with no BigInteger
public void exp(DataWord word) {
BigInteger result = value().pow(word.intValue());
byte[] bytes = result.toByteArray();
ByteBuffer data = ByteBuffer.allocate(32);
System.arraycopy(bytes, 0, data.array(), 32 - bytes.length, bytes.length);
this.data = data.array();
this.data = ByteUtil.copyToArray(result.toByteArray(), 32);
}
// TODO: improve with no BigInteger
@ -252,11 +226,7 @@ public class DataWord implements Comparable<DataWord> {
}
BigInteger result = value().mod(word.value());
byte[] bytes = result.toByteArray();
ByteBuffer data = ByteBuffer.allocate(32);
System.arraycopy(bytes, 0, data.array(), 32 - bytes.length, bytes.length);
this.data = data.array();
this.data = ByteUtil.copyToArray(result.toByteArray(), 32);
}
// TODO: improve with no BigInteger
@ -268,14 +238,12 @@ public class DataWord implements Comparable<DataWord> {
}
BigInteger result = sValue().mod( word.sValue());
byte[] bytes = result.toByteArray();
ByteBuffer data = ByteBuffer.allocate(32);
if (result.compareTo(BigInteger.ZERO) == -1)
if (result.signum() == -1)
Arrays.fill(data.array(), (byte) 0xFF);
System.arraycopy(bytes, 0, data.array(), 32 - bytes.length, bytes.length);
this.data = data.array();
this.data = ByteUtil.copyToArray(result.toByteArray(), data.array());
}
public String toString() {

View File

@ -88,4 +88,37 @@ public class DataWordTest {
assertEquals(32, y.getData().length);
assertEquals(expected, Hex.toHexString(y.getData()));
}
@Test
public void testMul() {
byte[] one = new byte[32];
one[31] = 0x1; // 0x0000000000000000000000000000000000000000000000000000000000000001
byte[] two = new byte[32];
two[11] = 0x1; // 0x0000000000000000000000010000000000000000000000000000000000000000
DataWord x = new DataWord(one);// System.out.println(x.value());
DataWord y = new DataWord(two);// System.out.println(y.value());
x.mul(y);
assertEquals(32, y.getData().length);
assertEquals("0000000000000000000000010000000000000000000000000000000000000000", Hex.toHexString(y.getData()));
}
@Test
public void testMulOverflow() {
byte[] one = new byte[32];
one[30] = 0x1; // 0x0000000000000000000000000000000000000000000000000000000000000100
byte[] two = new byte[32];
two[0] = 0x1; // 0x1000000000000000000000000000000000000000000000000000000000000000
DataWord x = new DataWord(one);// System.out.println(x.value());
DataWord y = new DataWord(two);// System.out.println(y.value());
x.mul(y);
assertEquals(32, y.getData().length);
assertEquals("0100000000000000000000000000000000000000000000000000000000000000", Hex.toHexString(y.getData()));
}
}