Skip to content

Commit

Permalink
Make BigInteger.toByteArray compatible with java.math.BigInteger for …
Browse files Browse the repository at this point in the history
…negative numbers
  • Loading branch information
lorenzHeinrich committed Sep 8, 2024
1 parent b06c2a8 commit 7266f24
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package electionguard.core

import electionguard.core.Base16.toHex
import kotlin.test.Test
import kotlin.test.assertEquals

class BigIntegerCompatibilityTest {

/** Since java.math.BigInteger uses two's complement with sign extension,
* and javascript bigint not, we have to test proper conversion*/
@Test
fun testBigIntToByteArray() {
// Positive numbers
var bi = BigInteger("1")
assertEquals(byteArrayOf(1).toHex(), bi.toByteArray().toHex())

bi = BigInteger("127")
assertEquals(byteArrayOf(0x7F).toHex(), bi.toByteArray().toHex())

bi = BigInteger("128")
assertEquals(byteArrayOf(0x00, 0x80.toByte()).toHex(), bi.toByteArray().toHex())

bi = BigInteger("256")
assertEquals(byteArrayOf(0x01, 0x00).toHex(), bi.toByteArray().toHex())

// Negative numbers
bi = BigInteger("-1")
assertEquals(byteArrayOf(0xFF.toByte()).toHex(), bi.toByteArray().toHex())

bi = BigInteger("-128")
assertEquals(byteArrayOf(0x80.toByte()).toHex(), bi.toByteArray().toHex())

bi = BigInteger("-129")
assertEquals(byteArrayOf(0xFF.toByte(), 0x7F).toHex(), bi.toByteArray().toHex())

bi = BigInteger("-256")
assertEquals(byteArrayOf(0xFF.toByte(), 0x00).toHex(), bi.toByteArray().toHex())

// Zero
bi = BigInteger("0")
assertEquals(byteArrayOf(0x00).toHex(), bi.toByteArray().toHex())
}
}
30 changes: 29 additions & 1 deletion egklib-core/src/jsMain/kotlin/electionguard/core/Group.js.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package electionguard.core

import electionguard.core.Base16.toHex
import kotlin.experimental.inv

@JsModule(import = "big-integer")
@JsNonModule
Expand Down Expand Up @@ -99,7 +100,34 @@ actual class BigInteger: Comparable<BigInteger> {
}

actual fun toByteArray(): ByteArray {
return this.value.toArray(256).value.map { it.toByte() }.toByteArray()
val array = this.value.toArray(256)
val isNegative = array.isNegative
val bytes = array.value.map { it.toByte() }.toMutableList()

if (isNegative) {
// Two's complement for negative numbers
var carry = true
for (i in bytes.indices.reversed()) {
bytes[i] = bytes[i].inv()
if (carry) {
if (bytes[i] == 0xFF.toByte()) {
bytes[i] = 0
} else {
bytes[i] = (bytes[i] + 1).toByte()
carry = false
}
}
}
// Ensure sign extension for negative numbers
if (bytes[0] >= 0) {
bytes.add(0, 0xFF.toByte()) // Add an extra byte if MSB doesn't correctly represent the sign
}
}

if (bytes[0] < 0 && !isNegative) {
bytes.add(0, 0) // positive sign extension
}
return bytes.toByteArray()
}

actual override fun toString(): String {
Expand Down

0 comments on commit 7266f24

Please sign in to comment.