feat: mechanical IntArray→LongArray replacement (WIP — broken, needs manual fixes)
Bulk sed replacement of IntArray(8)→LongArray(4), IntArray(16)→LongArray(8), intArrayOf→longArrayOf across all remaining files. This creates many compile errors that need manual fixing: - Type declarations still say IntArray where LongArray is needed - Constants still have 8 values (32-bit) instead of 4 (64-bit) - Loop bounds still reference 8 instead of 4 - toInt() casts on longArrayOf elements - mulShift384 internals broken for new layout https://claude.ai/code/session_01BhU63WUe9AhikZxRdw3Lpg
This commit is contained in:
@@ -50,7 +50,7 @@ package com.vitorpamplona.quartz.utils.secp256k1
|
||||
internal object Glv {
|
||||
/** β: cube root of unity mod p. The endomorphism is φ(x,y) = (β·x, y). */
|
||||
val BETA =
|
||||
intArrayOf(
|
||||
longArrayOf(
|
||||
0x719501EE.toInt(),
|
||||
0xC1396C28.toInt(),
|
||||
0x12F58995.toInt(),
|
||||
@@ -134,9 +134,9 @@ internal object Glv {
|
||||
k: IntArray,
|
||||
g: IntArray,
|
||||
): IntArray {
|
||||
val wide = IntArray(16)
|
||||
val wide = LongArray(8)
|
||||
U256.mulWide(wide, k, g)
|
||||
val result = IntArray(8)
|
||||
val result = LongArray(4)
|
||||
for (i in 0 until 4) result[i] = wide[i + 12]
|
||||
if (wide[11] < 0) { // Round based on bit 383
|
||||
var c = 1L
|
||||
@@ -182,7 +182,7 @@ internal object Glv {
|
||||
|
||||
/** -λ mod n */
|
||||
private val MINUS_LAMBDA =
|
||||
intArrayOf(
|
||||
longArrayOf(
|
||||
0xB51283CF.toInt(),
|
||||
0xE0CFC810.toInt(),
|
||||
0x8EC739C2.toInt(),
|
||||
@@ -195,7 +195,7 @@ internal object Glv {
|
||||
|
||||
/** Babai rounding constant g1 = round(2^384 · |b2| / n) */
|
||||
private val G1 =
|
||||
intArrayOf(
|
||||
longArrayOf(
|
||||
0x45DBB031.toInt(),
|
||||
0xE893209A.toInt(),
|
||||
0x71E8CA7F.toInt(),
|
||||
@@ -208,7 +208,7 @@ internal object Glv {
|
||||
|
||||
/** Babai rounding constant g2 = round(2^384 · |b1| / n) */
|
||||
private val G2 =
|
||||
intArrayOf(
|
||||
longArrayOf(
|
||||
0x8AC47F71.toInt(),
|
||||
0x1571B4AE.toInt(),
|
||||
0x9DF506C6.toInt(),
|
||||
@@ -221,7 +221,7 @@ internal object Glv {
|
||||
|
||||
/** -b1 mod n (lattice basis vector) */
|
||||
private val MINUS_B1 =
|
||||
intArrayOf(
|
||||
longArrayOf(
|
||||
0x0ABFE4C3.toInt(),
|
||||
0x6F547FA9.toInt(),
|
||||
0x010E8828.toInt(),
|
||||
@@ -234,7 +234,7 @@ internal object Glv {
|
||||
|
||||
/** -b2 mod n (lattice basis vector) */
|
||||
private val MINUS_B2 =
|
||||
intArrayOf(
|
||||
longArrayOf(
|
||||
0x3DB1562C.toInt(),
|
||||
0xD765CDA8.toInt(),
|
||||
0x0774346D.toInt(),
|
||||
@@ -247,7 +247,7 @@ internal object Glv {
|
||||
|
||||
/** n / 2, used to determine if a half-scalar needs negation */
|
||||
private val N_HALF =
|
||||
intArrayOf(
|
||||
longArrayOf(
|
||||
0x681B20A0.toInt(),
|
||||
0xDFE92F46.toInt(),
|
||||
0x57A4501D.toInt(),
|
||||
|
||||
@@ -39,7 +39,7 @@ package com.vitorpamplona.quartz.utils.secp256k1
|
||||
*/
|
||||
internal object KeyCodec {
|
||||
/** Curve constant b = 7 in y² = x³ + 7. */
|
||||
private val B = intArrayOf(7, 0, 0, 0, 0, 0, 0, 0)
|
||||
private val B = longArrayOf(7, 0, 0, 0, 0, 0, 0, 0)
|
||||
|
||||
/**
|
||||
* Lift an x-coordinate to a curve point with even y (BIP-340 convention).
|
||||
@@ -51,7 +51,7 @@ internal object KeyCodec {
|
||||
x: IntArray,
|
||||
): Boolean {
|
||||
if (U256.cmp(x, FieldP.P) >= 0) return false
|
||||
val t = IntArray(8)
|
||||
val t = LongArray(4)
|
||||
FieldP.sqr(t, x)
|
||||
FieldP.mul(t, t, x)
|
||||
FieldP.add(t, t, B) // t = x³ + 7
|
||||
@@ -78,7 +78,7 @@ internal object KeyCodec {
|
||||
pubkey.size == 33 && (pubkey[0] == 0x02.toByte() || pubkey[0] == 0x03.toByte()) -> {
|
||||
val x = U256.fromBytes(pubkey.copyOfRange(1, 33))
|
||||
if (U256.cmp(x, FieldP.P) >= 0) return false
|
||||
val t = IntArray(8)
|
||||
val t = LongArray(4)
|
||||
FieldP.sqr(t, x)
|
||||
FieldP.mul(t, t, x)
|
||||
FieldP.add(t, t, B) // y² = x³ + 7
|
||||
@@ -92,9 +92,9 @@ internal object KeyCodec {
|
||||
pubkey.size == 65 && pubkey[0] == 0x04.toByte() -> {
|
||||
val x = U256.fromBytes(pubkey.copyOfRange(1, 33))
|
||||
val y = U256.fromBytes(pubkey.copyOfRange(33, 65))
|
||||
val y2 = IntArray(8)
|
||||
val x3p7 = IntArray(8)
|
||||
val t = IntArray(8)
|
||||
val y2 = LongArray(4)
|
||||
val x3p7 = LongArray(4)
|
||||
val t = LongArray(4)
|
||||
FieldP.sqr(y2, y)
|
||||
FieldP.sqr(t, x)
|
||||
FieldP.mul(x3p7, t, x)
|
||||
|
||||
@@ -71,9 +71,9 @@ package com.vitorpamplona.quartz.utils.secp256k1
|
||||
* multiplication, which performs thousands of doublings and additions per operation.
|
||||
*/
|
||||
internal class MutablePoint(
|
||||
val x: IntArray = IntArray(8),
|
||||
val y: IntArray = IntArray(8),
|
||||
val z: IntArray = IntArray(8),
|
||||
val x: IntArray = LongArray(4),
|
||||
val y: IntArray = LongArray(4),
|
||||
val z: IntArray = LongArray(4),
|
||||
) {
|
||||
fun isInfinity(): Boolean = U256.isZero(z)
|
||||
|
||||
@@ -108,15 +108,15 @@ internal class MutablePoint(
|
||||
* Used for precomputed tables where we want compact storage and mixed addition.
|
||||
*/
|
||||
internal class AffinePoint(
|
||||
val x: IntArray = IntArray(8),
|
||||
val y: IntArray = IntArray(8),
|
||||
val x: IntArray = LongArray(4),
|
||||
val y: IntArray = LongArray(4),
|
||||
)
|
||||
|
||||
internal object ECPoint {
|
||||
// ==================== Generator point G ====================
|
||||
|
||||
val GX =
|
||||
intArrayOf(
|
||||
longArrayOf(
|
||||
0x16F81798.toInt(),
|
||||
0x59F2815B.toInt(),
|
||||
0x2DCE28D9.toInt(),
|
||||
@@ -127,7 +127,7 @@ internal object ECPoint {
|
||||
0x79BE667E.toInt(),
|
||||
)
|
||||
val GY =
|
||||
intArrayOf(
|
||||
longArrayOf(
|
||||
0xFB10D4B8.toInt(),
|
||||
0x9C47D08F.toInt(),
|
||||
0xA6855419.toInt(),
|
||||
@@ -139,7 +139,7 @@ internal object ECPoint {
|
||||
)
|
||||
|
||||
/** Curve constant b = 7 in y² = x³ + 7. */
|
||||
private val B = intArrayOf(7, 0, 0, 0, 0, 0, 0, 0)
|
||||
private val B = longArrayOf(7, 0, 0, 0, 0, 0, 0, 0)
|
||||
|
||||
/**
|
||||
* wNAF window width for the G-side of scalar multiplication.
|
||||
@@ -174,8 +174,8 @@ internal object ECPoint {
|
||||
for (i in 1 until G_TABLE_SIZE) addPoints(jac[i], jac[i - 1], g2)
|
||||
|
||||
return Array(G_TABLE_SIZE) { i ->
|
||||
val x = IntArray(8)
|
||||
val y = IntArray(8)
|
||||
val x = LongArray(4)
|
||||
val y = LongArray(4)
|
||||
toAffine(jac[i], x, y)
|
||||
AffinePoint(x, y)
|
||||
}
|
||||
@@ -236,10 +236,10 @@ internal object ECPoint {
|
||||
|
||||
return Array(tableSize) { i ->
|
||||
if (jac[i].isInfinity()) {
|
||||
AffinePoint(IntArray(8), IntArray(8))
|
||||
AffinePoint(LongArray(4), LongArray(4))
|
||||
} else {
|
||||
val x = IntArray(8)
|
||||
val y = IntArray(8)
|
||||
val x = LongArray(4)
|
||||
val y = LongArray(4)
|
||||
toAffine(jac[i], x, y)
|
||||
AffinePoint(x, y)
|
||||
}
|
||||
@@ -256,7 +256,7 @@ internal object ECPoint {
|
||||
* returns immediately after the recursive call without using the temps further.
|
||||
*/
|
||||
private class PointScratch {
|
||||
val t = Array(12) { IntArray(8) }
|
||||
val t = Array(12) { LongArray(4) }
|
||||
val dblCopy = MutablePoint() // Copy buffer for in-place doubling (out === input)
|
||||
}
|
||||
|
||||
@@ -347,7 +347,7 @@ internal object ECPoint {
|
||||
|
||||
if (U256.isZero(t[4])) {
|
||||
// Same x-coordinate: either same point (double) or inverse (infinity)
|
||||
val tmp = IntArray(8)
|
||||
val tmp = LongArray(4)
|
||||
FieldP.sub(tmp, t[3], p.y)
|
||||
if (U256.isZero(tmp)) doublePoint(out, p) else out.setInfinity()
|
||||
return
|
||||
@@ -607,7 +607,7 @@ internal object ECPoint {
|
||||
|
||||
out.setInfinity()
|
||||
val tmp = MutablePoint()
|
||||
val negY = IntArray(8)
|
||||
val negY = LongArray(4)
|
||||
val negJac = MutablePoint() // Reused scratch for Jacobian negation
|
||||
|
||||
for (i in bits - 1 downTo 0) {
|
||||
@@ -689,9 +689,9 @@ internal object ECPoint {
|
||||
outY: IntArray,
|
||||
): Boolean {
|
||||
if (p.isInfinity()) return false
|
||||
val zInv = IntArray(8)
|
||||
val zInv2 = IntArray(8)
|
||||
val zInv3 = IntArray(8)
|
||||
val zInv = LongArray(4)
|
||||
val zInv2 = LongArray(4)
|
||||
val zInv3 = LongArray(4)
|
||||
FieldP.inv(zInv, p.z)
|
||||
FieldP.sqr(zInv2, zInv)
|
||||
FieldP.mul(zInv3, zInv2, zInv)
|
||||
|
||||
@@ -34,7 +34,7 @@ package com.vitorpamplona.quartz.utils.secp256k1
|
||||
*/
|
||||
internal object ScalarN {
|
||||
val N =
|
||||
intArrayOf(
|
||||
longArrayOf(
|
||||
0xD0364141.toInt(),
|
||||
0xBFD25E8C.toInt(),
|
||||
0xAF48A03B.toInt(),
|
||||
@@ -47,7 +47,7 @@ internal object ScalarN {
|
||||
|
||||
/** 2^256 - n: the small constant used for reduction (≈129 bits) */
|
||||
private val N_COMPLEMENT =
|
||||
intArrayOf(
|
||||
longArrayOf(
|
||||
0x2FC9BEBF.toInt(),
|
||||
0x402DA173.toInt(),
|
||||
0x50B75FC4.toInt(),
|
||||
@@ -60,7 +60,7 @@ internal object ScalarN {
|
||||
|
||||
/** n - 2: exponent for Fermat inversion */
|
||||
private val N_MINUS_2 =
|
||||
intArrayOf(
|
||||
longArrayOf(
|
||||
0xD036413F.toInt(),
|
||||
0xBFD25E8C.toInt(),
|
||||
0xAF48A03B.toInt(),
|
||||
@@ -77,7 +77,7 @@ internal object ScalarN {
|
||||
/** If a >= n, return a - n. Otherwise return a unchanged. */
|
||||
fun reduce(a: IntArray): IntArray =
|
||||
if (U256.cmp(a, N) >= 0) {
|
||||
val r = IntArray(8)
|
||||
val r = LongArray(4)
|
||||
U256.subTo(r, a, N)
|
||||
r
|
||||
} else {
|
||||
@@ -88,7 +88,7 @@ internal object ScalarN {
|
||||
a: IntArray,
|
||||
b: IntArray,
|
||||
): IntArray {
|
||||
val r = IntArray(8)
|
||||
val r = LongArray(4)
|
||||
val carry = U256.addTo(r, a, b)
|
||||
if (carry != 0) U256.addTo(r, r, N_COMPLEMENT)
|
||||
reduceSelf(r)
|
||||
@@ -99,7 +99,7 @@ internal object ScalarN {
|
||||
a: IntArray,
|
||||
b: IntArray,
|
||||
): IntArray {
|
||||
val r = IntArray(8)
|
||||
val r = LongArray(4)
|
||||
val borrow = U256.subTo(r, a, b)
|
||||
if (borrow != 0) U256.addTo(r, r, N)
|
||||
return r
|
||||
@@ -109,14 +109,14 @@ internal object ScalarN {
|
||||
a: IntArray,
|
||||
b: IntArray,
|
||||
): IntArray {
|
||||
val w = IntArray(16)
|
||||
val w = LongArray(8)
|
||||
U256.mulWide(w, a, b)
|
||||
return reduceWide(w)
|
||||
}
|
||||
|
||||
fun neg(a: IntArray): IntArray {
|
||||
if (U256.isZero(a)) return IntArray(8)
|
||||
val r = IntArray(8)
|
||||
if (U256.isZero(a)) return LongArray(4)
|
||||
val r = LongArray(4)
|
||||
U256.subTo(r, N, a)
|
||||
return r
|
||||
}
|
||||
@@ -139,8 +139,8 @@ internal object ScalarN {
|
||||
* reduction until the result fits in 256 bits, then do a final conditional subtraction.
|
||||
*/
|
||||
private fun reduceWide(w: IntArray): IntArray {
|
||||
val lo = IntArray(8)
|
||||
val hi = IntArray(8)
|
||||
val lo = LongArray(4)
|
||||
val hi = LongArray(4)
|
||||
for (i in 0 until 8) {
|
||||
lo[i] = w[i]
|
||||
hi[i] = w[i + 8]
|
||||
@@ -151,9 +151,9 @@ internal object ScalarN {
|
||||
}
|
||||
|
||||
// Round 1: lo + hi × N_COMPLEMENT
|
||||
val hiTimesNC = IntArray(16)
|
||||
val hiTimesNC = LongArray(8)
|
||||
U256.mulWide(hiTimesNC, hi, N_COMPLEMENT)
|
||||
val sum = IntArray(16)
|
||||
val sum = LongArray(8)
|
||||
var carry = 0L
|
||||
for (i in 0 until 16) {
|
||||
carry += (hiTimesNC[i].toLong() and 0xFFFFFFFFL) +
|
||||
@@ -163,8 +163,8 @@ internal object ScalarN {
|
||||
}
|
||||
|
||||
// Round 2 if still > 256 bits
|
||||
val lo2 = IntArray(8)
|
||||
val hi2 = IntArray(8)
|
||||
val lo2 = LongArray(4)
|
||||
val hi2 = LongArray(4)
|
||||
for (i in 0 until 8) {
|
||||
lo2[i] = sum[i]
|
||||
hi2[i] = sum[i + 8]
|
||||
@@ -174,10 +174,10 @@ internal object ScalarN {
|
||||
return lo2
|
||||
}
|
||||
|
||||
val hi2NC = IntArray(16)
|
||||
val hi2NC = LongArray(8)
|
||||
U256.mulWide(hi2NC, hi2, N_COMPLEMENT)
|
||||
var c2 = 0L
|
||||
val result = IntArray(8)
|
||||
val result = LongArray(4)
|
||||
for (i in 0 until 8) {
|
||||
c2 += (lo2[i].toLong() and 0xFFFFFFFFL) + (hi2NC[i].toLong() and 0xFFFFFFFFL)
|
||||
result[i] = c2.toInt()
|
||||
@@ -208,7 +208,7 @@ internal object ScalarN {
|
||||
base: IntArray,
|
||||
exp: IntArray,
|
||||
): IntArray {
|
||||
val result = IntArray(8)
|
||||
val result = LongArray(4)
|
||||
val b = base.copyOf()
|
||||
var highBit = 255
|
||||
while (highBit >= 0 && !U256.testBit(exp, highBit)) highBit--
|
||||
|
||||
+19
-19
@@ -73,8 +73,8 @@ object Secp256k1 {
|
||||
require(ScalarN.isValid(scalar))
|
||||
val p = MutablePoint()
|
||||
ECPoint.mulG(p, scalar)
|
||||
val x = IntArray(8)
|
||||
val y = IntArray(8)
|
||||
val x = LongArray(4)
|
||||
val y = LongArray(4)
|
||||
check(ECPoint.toAffine(p, x, y))
|
||||
return ECPoint.serializeUncompressed(x, y)
|
||||
}
|
||||
@@ -183,8 +183,8 @@ object Secp256k1 {
|
||||
// Derive public key (one G multiplication + one inversion)
|
||||
val pubPoint = MutablePoint()
|
||||
ECPoint.mulG(pubPoint, d0)
|
||||
val px = IntArray(8)
|
||||
val py = IntArray(8)
|
||||
val px = LongArray(4)
|
||||
val py = LongArray(4)
|
||||
check(ECPoint.toAffine(pubPoint, px, py))
|
||||
|
||||
val xOnlyPub = U256.toBytes(px)
|
||||
@@ -239,7 +239,7 @@ object Secp256k1 {
|
||||
if (auxrand != null) {
|
||||
require(auxrand.size == 32)
|
||||
val auxHash = sha256(AUX_PREFIX + auxrand)
|
||||
val tArr = IntArray(8)
|
||||
val tArr = LongArray(4)
|
||||
U256.xorTo(tArr, U256.fromBytes(dBytes), U256.fromBytes(auxHash))
|
||||
U256.toBytes(tArr)
|
||||
} else {
|
||||
@@ -258,8 +258,8 @@ object Secp256k1 {
|
||||
// R = k0·G
|
||||
val rPoint = MutablePoint()
|
||||
ECPoint.mulG(rPoint, k0)
|
||||
val rx = IntArray(8)
|
||||
val ry = IntArray(8)
|
||||
val rx = LongArray(4)
|
||||
val ry = LongArray(4)
|
||||
check(ECPoint.toAffine(rPoint, rx, ry))
|
||||
|
||||
val k = if (ECPoint.hasEvenY(ry)) k0 else ScalarN.neg(k0)
|
||||
@@ -303,8 +303,8 @@ object Secp256k1 {
|
||||
): Boolean {
|
||||
if (signature.size != 64 || pub.size != 32) return false
|
||||
|
||||
val px = IntArray(8)
|
||||
val py = IntArray(8)
|
||||
val px = LongArray(4)
|
||||
val py = LongArray(4)
|
||||
if (!ECPoint.liftX(px, py, U256.fromBytes(pub))) return false
|
||||
|
||||
val r = U256.fromBytes(signature, 0)
|
||||
@@ -329,8 +329,8 @@ object Secp256k1 {
|
||||
ECPoint.mulDoubleG(result, s, pPoint, negE)
|
||||
|
||||
if (result.isInfinity()) return false
|
||||
val rx = IntArray(8)
|
||||
val ry = IntArray(8)
|
||||
val rx = LongArray(4)
|
||||
val ry = LongArray(4)
|
||||
if (!ECPoint.toAffine(result, rx, ry)) return false
|
||||
if (!ECPoint.hasEvenY(ry)) return false
|
||||
return U256.cmp(rx, r) == 0
|
||||
@@ -355,8 +355,8 @@ object Secp256k1 {
|
||||
tweak: ByteArray,
|
||||
): ByteArray {
|
||||
require(tweak.size == 32)
|
||||
val x = IntArray(8)
|
||||
val y = IntArray(8)
|
||||
val x = LongArray(4)
|
||||
val y = LongArray(4)
|
||||
check(ECPoint.parsePublicKey(pubkey, x, y))
|
||||
val scalar = U256.fromBytes(tweak)
|
||||
require(ScalarN.isValid(scalar))
|
||||
@@ -365,8 +365,8 @@ object Secp256k1 {
|
||||
p.setAffine(x, y)
|
||||
val result = MutablePoint()
|
||||
ECPoint.mul(result, p, scalar)
|
||||
val rx = IntArray(8)
|
||||
val ry = IntArray(8)
|
||||
val rx = LongArray(4)
|
||||
val ry = LongArray(4)
|
||||
check(ECPoint.toAffine(result, rx, ry))
|
||||
|
||||
return if (pubkey.size == 33) {
|
||||
@@ -402,16 +402,16 @@ object Secp256k1 {
|
||||
// Compute y = sqrt(x³ + 7). We need SOME valid y for EC point operations,
|
||||
// but the result's x-coordinate is the same regardless of y sign.
|
||||
// Use liftX which returns the even-y variant.
|
||||
val px = IntArray(8)
|
||||
val py = IntArray(8)
|
||||
val px = LongArray(4)
|
||||
val py = LongArray(4)
|
||||
check(ECPoint.liftX(px, py, x)) { "Not a valid x-coordinate on secp256k1" }
|
||||
|
||||
val p = MutablePoint()
|
||||
p.setAffine(px, py)
|
||||
val result = MutablePoint()
|
||||
ECPoint.mul(result, p, k)
|
||||
val rx = IntArray(8)
|
||||
val ry = IntArray(8)
|
||||
val rx = LongArray(4)
|
||||
val ry = LongArray(4)
|
||||
check(ECPoint.toAffine(result, rx, ry))
|
||||
return U256.toBytes(rx)
|
||||
}
|
||||
|
||||
+23
-23
@@ -39,7 +39,7 @@ class FieldPTest {
|
||||
@Test
|
||||
fun addZeroIdentity() {
|
||||
val a = hex("67e56582298859ddae725f972992a07c6c4fb9f62a8fff58ce3ca926a1063530")
|
||||
val zero = IntArray(8)
|
||||
val zero = LongArray(4)
|
||||
assertEquals(toHex(a), toHex(FieldP.add(a, zero)))
|
||||
}
|
||||
|
||||
@@ -62,7 +62,7 @@ class FieldPTest {
|
||||
@Test
|
||||
fun mulOneIdentity() {
|
||||
val a = hex("67e56582298859ddae725f972992a07c6c4fb9f62a8fff58ce3ca926a1063530")
|
||||
val one = intArrayOf(1, 0, 0, 0, 0, 0, 0, 0)
|
||||
val one = longArrayOf(1, 0, 0, 0, 0, 0, 0, 0)
|
||||
assertEquals(toHex(a), toHex(FieldP.mul(a, one)))
|
||||
}
|
||||
|
||||
@@ -72,7 +72,7 @@ class FieldPTest {
|
||||
fun addNearP() {
|
||||
// (p - 1) + 1 = p ≡ 0 (mod p)
|
||||
val pMinus1 = hex("fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2e")
|
||||
val one = intArrayOf(1, 0, 0, 0, 0, 0, 0, 0)
|
||||
val one = longArrayOf(1, 0, 0, 0, 0, 0, 0, 0)
|
||||
val result = FieldP.add(pMinus1, one)
|
||||
assertTrue(U256.isZero(result))
|
||||
}
|
||||
@@ -89,8 +89,8 @@ class FieldPTest {
|
||||
@Test
|
||||
fun subUnderflow() {
|
||||
// 0 - 1 ≡ p - 1 (mod p)
|
||||
val zero = IntArray(8)
|
||||
val one = intArrayOf(1, 0, 0, 0, 0, 0, 0, 0)
|
||||
val zero = LongArray(4)
|
||||
val one = longArrayOf(1, 0, 0, 0, 0, 0, 0, 0)
|
||||
val result = FieldP.sub(zero, one)
|
||||
val expected = hex("fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2e") // p-1
|
||||
assertEquals(toHex(expected), toHex(result))
|
||||
@@ -106,7 +106,7 @@ class FieldPTest {
|
||||
|
||||
@Test
|
||||
fun negZeroIsZero() {
|
||||
assertTrue(U256.isZero(FieldP.neg(IntArray(8))))
|
||||
assertTrue(U256.isZero(FieldP.neg(LongArray(4))))
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -149,13 +149,13 @@ class FieldPTest {
|
||||
val a = hex("67e56582298859ddae725f972992a07c6c4fb9f62a8fff58ce3ca926a1063530")
|
||||
val aInv = FieldP.inv(a)
|
||||
val product = FieldP.mul(a, aInv)
|
||||
val one = intArrayOf(1, 0, 0, 0, 0, 0, 0, 0)
|
||||
val one = longArrayOf(1, 0, 0, 0, 0, 0, 0, 0)
|
||||
assertEquals(toHex(one), toHex(product))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun invOfOne() {
|
||||
val one = intArrayOf(1, 0, 0, 0, 0, 0, 0, 0)
|
||||
val one = longArrayOf(1, 0, 0, 0, 0, 0, 0, 0)
|
||||
assertEquals(toHex(one), toHex(FieldP.inv(one)))
|
||||
}
|
||||
|
||||
@@ -170,8 +170,8 @@ class FieldPTest {
|
||||
|
||||
@Test
|
||||
fun halfOfEven() {
|
||||
val out = IntArray(8)
|
||||
val four = intArrayOf(4, 0, 0, 0, 0, 0, 0, 0)
|
||||
val out = LongArray(4)
|
||||
val four = longArrayOf(4, 0, 0, 0, 0, 0, 0, 0)
|
||||
FieldP.half(out, four)
|
||||
assertEquals(2, out[0])
|
||||
for (i in 1 until 8) assertEquals(0, out[i])
|
||||
@@ -180,8 +180,8 @@ class FieldPTest {
|
||||
@Test
|
||||
fun halfOfOdd() {
|
||||
// half(1) = (1 + p) / 2 = (p + 1) / 2
|
||||
val out = IntArray(8)
|
||||
val one = intArrayOf(1, 0, 0, 0, 0, 0, 0, 0)
|
||||
val out = LongArray(4)
|
||||
val one = longArrayOf(1, 0, 0, 0, 0, 0, 0, 0)
|
||||
FieldP.half(out, one)
|
||||
// Verify: 2 * half(1) = 1 mod p
|
||||
val doubled = FieldP.add(out, out)
|
||||
@@ -192,7 +192,7 @@ class FieldPTest {
|
||||
@Test
|
||||
fun halfThenDoubleRoundTrips() {
|
||||
val a = hex("67e56582298859ddae725f972992a07c6c4fb9f62a8fff58ce3ca926a1063530")
|
||||
val out = IntArray(8)
|
||||
val out = LongArray(4)
|
||||
FieldP.half(out, a)
|
||||
val doubled = FieldP.add(out, out)
|
||||
assertEquals(toHex(a), toHex(doubled))
|
||||
@@ -213,7 +213,7 @@ class FieldPTest {
|
||||
@Test
|
||||
fun sqrtOfNonResidue() {
|
||||
// 3 is not a quadratic residue mod p (for secp256k1's p)
|
||||
val three = intArrayOf(3, 0, 0, 0, 0, 0, 0, 0)
|
||||
val three = longArrayOf(3, 0, 0, 0, 0, 0, 0, 0)
|
||||
assertNull(FieldP.sqrt(three))
|
||||
}
|
||||
|
||||
@@ -223,7 +223,7 @@ class FieldPTest {
|
||||
val gx = ECPoint.GX
|
||||
val gy = ECPoint.GY
|
||||
val x3 = FieldP.mul(FieldP.sqr(gx), gx)
|
||||
val y2 = FieldP.add(x3, intArrayOf(7, 0, 0, 0, 0, 0, 0, 0))
|
||||
val y2 = FieldP.add(x3, longArrayOf(7, 0, 0, 0, 0, 0, 0, 0))
|
||||
val root = FieldP.sqrt(y2)!!
|
||||
// root should be gy or -gy
|
||||
val isGy = U256.cmp(root, gy) == 0
|
||||
@@ -240,7 +240,7 @@ class FieldPTest {
|
||||
val result = FieldP.mul(pMinus1, pMinus1)
|
||||
assertTrue(U256.cmp(result, FieldP.P) < 0, "Result should be < p")
|
||||
// (p-1)² ≡ 1 (mod p)
|
||||
val one = intArrayOf(1, 0, 0, 0, 0, 0, 0, 0)
|
||||
val one = longArrayOf(1, 0, 0, 0, 0, 0, 0, 0)
|
||||
assertEquals(toHex(one), toHex(result))
|
||||
}
|
||||
|
||||
@@ -250,7 +250,7 @@ class FieldPTest {
|
||||
fun inPlaceAdd() {
|
||||
val a = hex("0000000000000000000000000000000000000000000000000000000000000005")
|
||||
val b = hex("0000000000000000000000000000000000000000000000000000000000000003")
|
||||
val out = IntArray(8)
|
||||
val out = LongArray(4)
|
||||
FieldP.add(out, a, b)
|
||||
assertEquals(8, out[0])
|
||||
}
|
||||
@@ -258,7 +258,7 @@ class FieldPTest {
|
||||
@Test
|
||||
fun inPlaceSqr() {
|
||||
val a = hex("0000000000000000000000000000000000000000000000000000000000000005")
|
||||
val out = IntArray(8)
|
||||
val out = LongArray(4)
|
||||
FieldP.sqr(out, a)
|
||||
assertEquals(25, out[0]) // 5² = 25
|
||||
}
|
||||
@@ -267,7 +267,7 @@ class FieldPTest {
|
||||
fun halfOfPMinus1() {
|
||||
// half(p-1) should equal (p-1)/2
|
||||
val pMinus1 = hex("fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2e")
|
||||
val out = IntArray(8)
|
||||
val out = LongArray(4)
|
||||
FieldP.half(out, pMinus1)
|
||||
// Verify: 2 * half(p-1) = p-1
|
||||
val doubled = FieldP.add(out, out)
|
||||
@@ -276,23 +276,23 @@ class FieldPTest {
|
||||
|
||||
@Test
|
||||
fun invOfTwo() {
|
||||
val two = intArrayOf(2, 0, 0, 0, 0, 0, 0, 0)
|
||||
val two = longArrayOf(2, 0, 0, 0, 0, 0, 0, 0)
|
||||
val inv2 = FieldP.inv(two)
|
||||
val product = FieldP.mul(two, inv2)
|
||||
val one = intArrayOf(1, 0, 0, 0, 0, 0, 0, 0)
|
||||
val one = longArrayOf(1, 0, 0, 0, 0, 0, 0, 0)
|
||||
assertEquals(toHex(one), toHex(product))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun sqrtOfZero() {
|
||||
val zero = IntArray(8)
|
||||
val zero = LongArray(4)
|
||||
val root = FieldP.sqrt(zero)
|
||||
assertTrue(root != null && U256.isZero(root))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun sqrtOfOne() {
|
||||
val one = intArrayOf(1, 0, 0, 0, 0, 0, 0, 0)
|
||||
val one = longArrayOf(1, 0, 0, 0, 0, 0, 0, 0)
|
||||
val root = FieldP.sqrt(one)!!
|
||||
assertEquals(toHex(one), toHex(root))
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ class GlvTest {
|
||||
|
||||
@Test
|
||||
fun splitScalarZero() {
|
||||
val split = Glv.splitScalar(IntArray(8))
|
||||
val split = Glv.splitScalar(LongArray(4))
|
||||
assertTrue(U256.isZero(split.k1) && U256.isZero(split.k2))
|
||||
}
|
||||
|
||||
@@ -106,7 +106,7 @@ class GlvTest {
|
||||
// β³ ≡ 1 (mod p) — the defining property of the cube root of unity
|
||||
val b2 = FieldP.sqr(Glv.BETA)
|
||||
val b3 = FieldP.mul(b2, Glv.BETA)
|
||||
val one = intArrayOf(1, 0, 0, 0, 0, 0, 0, 0)
|
||||
val one = longArrayOf(1, 0, 0, 0, 0, 0, 0, 0)
|
||||
assertEquals(toHex(one), toHex(b3))
|
||||
}
|
||||
|
||||
@@ -115,8 +115,8 @@ class GlvTest {
|
||||
// λ·G should equal (β·Gx, Gy)
|
||||
val result = MutablePoint()
|
||||
ECPoint.mulG(result, LAMBDA)
|
||||
val rx = IntArray(8)
|
||||
val ry = IntArray(8)
|
||||
val rx = LongArray(4)
|
||||
val ry = LongArray(4)
|
||||
ECPoint.toAffine(result, rx, ry)
|
||||
assertEquals(toHex(FieldP.mul(ECPoint.GX, Glv.BETA)), toHex(rx))
|
||||
assertEquals(toHex(ECPoint.GY), toHex(ry))
|
||||
@@ -127,7 +127,7 @@ class GlvTest {
|
||||
@Test
|
||||
fun wnafReconstructionSmall() {
|
||||
// wNAF digits should reconstruct to the original scalar
|
||||
val k = intArrayOf(17, 0, 0, 0, 0, 0, 0, 0) // 17 = 10001 in binary
|
||||
val k = longArrayOf(17, 0, 0, 0, 0, 0, 0, 0) // 17 = 10001 in binary
|
||||
val digits = Glv.wnaf(k, 5, 256)
|
||||
assertEquals(k[0], reconstructWnaf(digits)[0])
|
||||
}
|
||||
@@ -180,7 +180,7 @@ class GlvTest {
|
||||
@Test
|
||||
fun wnafSmallMaxBits() {
|
||||
// wNAF with maxBits=129 (used for GLV half-scalars)
|
||||
val k = intArrayOf(0x12345678.toInt(), 0x9ABCDEF0.toInt(), 0x11111111, 0x22222222, 0, 0, 0, 0)
|
||||
val k = longArrayOf(0x12345678.toInt(), 0x9ABCDEF0.toInt(), 0x11111111, 0x22222222, 0, 0, 0, 0)
|
||||
val digits = Glv.wnaf(k, 5, 129)
|
||||
val reconstructed = reconstructWnaf(digits)
|
||||
for (i in 0 until 4) assertEquals(k[i], reconstructed[i], "Limb $i mismatch for 129-bit wNAF")
|
||||
@@ -193,16 +193,16 @@ class GlvTest {
|
||||
// s·G + 0·P = s·G
|
||||
val s = hex("67e56582298859ddae725f972992a07c6c4fb9f62a8fff58ce3ca926a1063530")
|
||||
val p = MutablePoint()
|
||||
ECPoint.mulG(p, intArrayOf(2, 0, 0, 0, 0, 0, 0, 0))
|
||||
ECPoint.mulG(p, longArrayOf(2, 0, 0, 0, 0, 0, 0, 0))
|
||||
val combined = MutablePoint()
|
||||
ECPoint.mulDoubleG(combined, s, p, IntArray(8))
|
||||
val cx = IntArray(8)
|
||||
val cy = IntArray(8)
|
||||
ECPoint.mulDoubleG(combined, s, p, LongArray(4))
|
||||
val cx = LongArray(4)
|
||||
val cy = LongArray(4)
|
||||
ECPoint.toAffine(combined, cx, cy)
|
||||
val direct = MutablePoint()
|
||||
ECPoint.mulG(direct, s)
|
||||
val dx = IntArray(8)
|
||||
val dy = IntArray(8)
|
||||
val dx = LongArray(4)
|
||||
val dy = LongArray(4)
|
||||
ECPoint.toAffine(direct, dx, dy)
|
||||
assertEquals(toHex(dx), toHex(cx))
|
||||
}
|
||||
@@ -211,9 +211,9 @@ class GlvTest {
|
||||
|
||||
/** Reconstruct a scalar from wNAF digits using Horner's method. */
|
||||
private fun reconstructWnaf(digits: IntArray): IntArray {
|
||||
var acc = IntArray(8)
|
||||
var acc = LongArray(4)
|
||||
for (bit in digits.size - 1 downTo 0) {
|
||||
val doubled = IntArray(8)
|
||||
val doubled = LongArray(4)
|
||||
var carry = 0L
|
||||
for (j in 0 until 8) {
|
||||
carry += (acc[j].toLong() and 0xFFFFFFFFL) * 2L
|
||||
|
||||
+29
-29
@@ -33,8 +33,8 @@ class KeyCodecTest {
|
||||
|
||||
@Test
|
||||
fun liftXGenerator() {
|
||||
val x = IntArray(8)
|
||||
val y = IntArray(8)
|
||||
val x = LongArray(4)
|
||||
val y = LongArray(4)
|
||||
assertTrue(KeyCodec.liftX(x, y, ECPoint.GX))
|
||||
assertEquals(toHex(ECPoint.GX), toHex(x))
|
||||
assertTrue(KeyCodec.hasEvenY(y))
|
||||
@@ -43,25 +43,25 @@ class KeyCodecTest {
|
||||
@Test
|
||||
fun liftXInvalidFieldElement() {
|
||||
// p itself is not a valid x
|
||||
val x = IntArray(8)
|
||||
val y = IntArray(8)
|
||||
val x = LongArray(4)
|
||||
val y = LongArray(4)
|
||||
assertFalse(KeyCodec.liftX(x, y, FieldP.P))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun liftXNotOnCurve() {
|
||||
// x=2: y² = 8+7 = 15. 15 is not a quadratic residue mod p.
|
||||
val x = IntArray(8)
|
||||
val y = IntArray(8)
|
||||
val two = intArrayOf(2, 0, 0, 0, 0, 0, 0, 0)
|
||||
val x = LongArray(4)
|
||||
val y = LongArray(4)
|
||||
val two = longArrayOf(2, 0, 0, 0, 0, 0, 0, 0)
|
||||
// This may or may not be on the curve — just check it doesn't crash
|
||||
KeyCodec.liftX(x, y, two) // result doesn't matter, just no exception
|
||||
}
|
||||
|
||||
@Test
|
||||
fun liftXAlwaysReturnsEvenY() {
|
||||
val x = IntArray(8)
|
||||
val y = IntArray(8)
|
||||
val x = LongArray(4)
|
||||
val y = LongArray(4)
|
||||
assertTrue(KeyCodec.liftX(x, y, ECPoint.GX))
|
||||
assertTrue(KeyCodec.hasEvenY(y), "liftX should always return even y")
|
||||
}
|
||||
@@ -70,14 +70,14 @@ class KeyCodecTest {
|
||||
|
||||
@Test
|
||||
fun hasEvenYForEvenValue() {
|
||||
assertTrue(KeyCodec.hasEvenY(intArrayOf(2, 0, 0, 0, 0, 0, 0, 0)))
|
||||
assertTrue(KeyCodec.hasEvenY(intArrayOf(0, 0, 0, 0, 0, 0, 0, 0)))
|
||||
assertTrue(KeyCodec.hasEvenY(longArrayOf(2, 0, 0, 0, 0, 0, 0, 0)))
|
||||
assertTrue(KeyCodec.hasEvenY(longArrayOf(0, 0, 0, 0, 0, 0, 0, 0)))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun hasEvenYForOddValue() {
|
||||
assertFalse(KeyCodec.hasEvenY(intArrayOf(1, 0, 0, 0, 0, 0, 0, 0)))
|
||||
assertFalse(KeyCodec.hasEvenY(intArrayOf(3, 0, 0, 0, 0, 0, 0, 0)))
|
||||
assertFalse(KeyCodec.hasEvenY(longArrayOf(1, 0, 0, 0, 0, 0, 0, 0)))
|
||||
assertFalse(KeyCodec.hasEvenY(longArrayOf(3, 0, 0, 0, 0, 0, 0, 0)))
|
||||
}
|
||||
|
||||
// ==================== parsePublicKey ====================
|
||||
@@ -86,8 +86,8 @@ class KeyCodecTest {
|
||||
fun parseCompressedEvenY() {
|
||||
val compressed = KeyCodec.serializeCompressed(ECPoint.GX, ECPoint.GY)
|
||||
assertEquals(0x02.toByte(), compressed[0])
|
||||
val x = IntArray(8)
|
||||
val y = IntArray(8)
|
||||
val x = LongArray(4)
|
||||
val y = LongArray(4)
|
||||
assertTrue(KeyCodec.parsePublicKey(compressed, x, y))
|
||||
assertEquals(toHex(ECPoint.GX), toHex(x))
|
||||
assertEquals(toHex(ECPoint.GY), toHex(y))
|
||||
@@ -98,8 +98,8 @@ class KeyCodecTest {
|
||||
val negGy = FieldP.neg(ECPoint.GY)
|
||||
val compressed = KeyCodec.serializeCompressed(ECPoint.GX, negGy)
|
||||
assertEquals(0x03.toByte(), compressed[0])
|
||||
val x = IntArray(8)
|
||||
val y = IntArray(8)
|
||||
val x = LongArray(4)
|
||||
val y = LongArray(4)
|
||||
assertTrue(KeyCodec.parsePublicKey(compressed, x, y))
|
||||
assertEquals(toHex(ECPoint.GX), toHex(x))
|
||||
assertEquals(toHex(negGy), toHex(y))
|
||||
@@ -109,8 +109,8 @@ class KeyCodecTest {
|
||||
fun parseUncompressed() {
|
||||
val uncompressed = KeyCodec.serializeUncompressed(ECPoint.GX, ECPoint.GY)
|
||||
assertEquals(0x04.toByte(), uncompressed[0])
|
||||
val x = IntArray(8)
|
||||
val y = IntArray(8)
|
||||
val x = LongArray(4)
|
||||
val y = LongArray(4)
|
||||
assertTrue(KeyCodec.parsePublicKey(uncompressed, x, y))
|
||||
assertEquals(toHex(ECPoint.GX), toHex(x))
|
||||
assertEquals(toHex(ECPoint.GY), toHex(y))
|
||||
@@ -118,8 +118,8 @@ class KeyCodecTest {
|
||||
|
||||
@Test
|
||||
fun parseInvalidSizes() {
|
||||
val x = IntArray(8)
|
||||
val y = IntArray(8)
|
||||
val x = LongArray(4)
|
||||
val y = LongArray(4)
|
||||
assertFalse(KeyCodec.parsePublicKey(ByteArray(0), x, y))
|
||||
assertFalse(KeyCodec.parsePublicKey(ByteArray(10), x, y))
|
||||
assertFalse(KeyCodec.parsePublicKey(ByteArray(32), x, y))
|
||||
@@ -130,8 +130,8 @@ class KeyCodecTest {
|
||||
|
||||
@Test
|
||||
fun parseInvalidPrefix() {
|
||||
val x = IntArray(8)
|
||||
val y = IntArray(8)
|
||||
val x = LongArray(4)
|
||||
val y = LongArray(4)
|
||||
assertFalse(KeyCodec.parsePublicKey(ByteArray(33), x, y)) // prefix 0x00
|
||||
assertFalse(KeyCodec.parsePublicKey(ByteArray(65), x, y)) // prefix 0x00
|
||||
}
|
||||
@@ -143,8 +143,8 @@ class KeyCodecTest {
|
||||
fake[0] = 0x04
|
||||
fake[1] = 0x01 // x = 1 (padded)
|
||||
fake[33] = 0x01 // y = 1 (padded) — 1² ≠ 1³ + 7
|
||||
val x = IntArray(8)
|
||||
val y = IntArray(8)
|
||||
val x = LongArray(4)
|
||||
val y = LongArray(4)
|
||||
assertFalse(KeyCodec.parsePublicKey(fake, x, y))
|
||||
}
|
||||
|
||||
@@ -153,8 +153,8 @@ class KeyCodecTest {
|
||||
@Test
|
||||
fun compressDecompressRoundTrip() {
|
||||
val compressed = KeyCodec.serializeCompressed(ECPoint.GX, ECPoint.GY)
|
||||
val x = IntArray(8)
|
||||
val y = IntArray(8)
|
||||
val x = LongArray(4)
|
||||
val y = LongArray(4)
|
||||
assertTrue(KeyCodec.parsePublicKey(compressed, x, y))
|
||||
val recompressed = KeyCodec.serializeCompressed(x, y)
|
||||
assertEquals(compressed.toList(), recompressed.toList())
|
||||
@@ -163,8 +163,8 @@ class KeyCodecTest {
|
||||
@Test
|
||||
fun uncompressedRoundTrip() {
|
||||
val uncompressed = KeyCodec.serializeUncompressed(ECPoint.GX, ECPoint.GY)
|
||||
val x = IntArray(8)
|
||||
val y = IntArray(8)
|
||||
val x = LongArray(4)
|
||||
val y = LongArray(4)
|
||||
assertTrue(KeyCodec.parsePublicKey(uncompressed, x, y))
|
||||
val reser = KeyCodec.serializeUncompressed(x, y)
|
||||
assertEquals(uncompressed.toList(), reser.toList())
|
||||
|
||||
+55
-55
@@ -40,7 +40,7 @@ class PointTest {
|
||||
fun generatorIsOnCurve() {
|
||||
// y² = x³ + 7
|
||||
val x3 = FieldP.mul(FieldP.sqr(ECPoint.GX), ECPoint.GX)
|
||||
val y2expected = FieldP.add(x3, intArrayOf(7, 0, 0, 0, 0, 0, 0, 0))
|
||||
val y2expected = FieldP.add(x3, longArrayOf(7, 0, 0, 0, 0, 0, 0, 0))
|
||||
val y2actual = FieldP.sqr(ECPoint.GY)
|
||||
assertEquals(toHex(y2expected), toHex(y2actual))
|
||||
}
|
||||
@@ -54,16 +54,16 @@ class PointTest {
|
||||
p.setAffine(ECPoint.GX, ECPoint.GY)
|
||||
val doubled = MutablePoint()
|
||||
ECPoint.doublePoint(doubled, p)
|
||||
val dx = IntArray(8)
|
||||
val dy = IntArray(8)
|
||||
val dx = LongArray(4)
|
||||
val dy = LongArray(4)
|
||||
ECPoint.toAffine(doubled, dx, dy)
|
||||
|
||||
// 2·G via scalar multiplication
|
||||
val two = intArrayOf(2, 0, 0, 0, 0, 0, 0, 0)
|
||||
val two = longArrayOf(2, 0, 0, 0, 0, 0, 0, 0)
|
||||
val mulResult = MutablePoint()
|
||||
ECPoint.mulG(mulResult, two)
|
||||
val mx = IntArray(8)
|
||||
val my = IntArray(8)
|
||||
val mx = LongArray(4)
|
||||
val my = LongArray(4)
|
||||
ECPoint.toAffine(mulResult, mx, my)
|
||||
|
||||
assertEquals(toHex(mx), toHex(dx))
|
||||
@@ -76,15 +76,15 @@ class PointTest {
|
||||
val p = MutablePoint()
|
||||
p.setAffine(ECPoint.GX, ECPoint.GY)
|
||||
ECPoint.doublePoint(p, p)
|
||||
val x = IntArray(8)
|
||||
val y = IntArray(8)
|
||||
val x = LongArray(4)
|
||||
val y = LongArray(4)
|
||||
ECPoint.toAffine(p, x, y)
|
||||
|
||||
val two = intArrayOf(2, 0, 0, 0, 0, 0, 0, 0)
|
||||
val two = longArrayOf(2, 0, 0, 0, 0, 0, 0, 0)
|
||||
val expected = MutablePoint()
|
||||
ECPoint.mulG(expected, two)
|
||||
val ex = IntArray(8)
|
||||
val ey = IntArray(8)
|
||||
val ex = LongArray(4)
|
||||
val ey = LongArray(4)
|
||||
ECPoint.toAffine(expected, ex, ey)
|
||||
|
||||
assertEquals(toHex(ex), toHex(x))
|
||||
@@ -107,14 +107,14 @@ class PointTest {
|
||||
g.setAffine(ECPoint.GX, ECPoint.GY)
|
||||
val sum = MutablePoint()
|
||||
ECPoint.addPoints(sum, g, g)
|
||||
val sx = IntArray(8)
|
||||
val sy = IntArray(8)
|
||||
val sx = LongArray(4)
|
||||
val sy = LongArray(4)
|
||||
ECPoint.toAffine(sum, sx, sy)
|
||||
|
||||
val doubled = MutablePoint()
|
||||
ECPoint.doublePoint(doubled, g)
|
||||
val dx = IntArray(8)
|
||||
val dy = IntArray(8)
|
||||
val dx = LongArray(4)
|
||||
val dy = LongArray(4)
|
||||
ECPoint.toAffine(doubled, dx, dy)
|
||||
|
||||
assertEquals(toHex(dx), toHex(sx))
|
||||
@@ -130,15 +130,15 @@ class PointTest {
|
||||
|
||||
val result = MutablePoint()
|
||||
ECPoint.addPoints(result, g, inf)
|
||||
val rx = IntArray(8)
|
||||
val ry = IntArray(8)
|
||||
val rx = LongArray(4)
|
||||
val ry = LongArray(4)
|
||||
ECPoint.toAffine(result, rx, ry)
|
||||
assertEquals(toHex(ECPoint.GX), toHex(rx))
|
||||
|
||||
val result2 = MutablePoint()
|
||||
ECPoint.addPoints(result2, inf, g)
|
||||
val r2x = IntArray(8)
|
||||
val r2y = IntArray(8)
|
||||
val r2x = LongArray(4)
|
||||
val r2y = LongArray(4)
|
||||
ECPoint.toAffine(result2, r2x, r2y)
|
||||
assertEquals(toHex(ECPoint.GX), toHex(r2x))
|
||||
}
|
||||
@@ -161,15 +161,15 @@ class PointTest {
|
||||
@Test
|
||||
fun addMixedMatchesFull() {
|
||||
// addMixed should produce the same result as addPoints when q is affine
|
||||
val three = intArrayOf(3, 0, 0, 0, 0, 0, 0, 0)
|
||||
val three = longArrayOf(3, 0, 0, 0, 0, 0, 0, 0)
|
||||
val p = MutablePoint()
|
||||
ECPoint.mulG(p, three) // 3G in Jacobian (z ≠ 1)
|
||||
|
||||
// Add G as affine
|
||||
val mixed = MutablePoint()
|
||||
ECPoint.addMixed(mixed, p, ECPoint.GX, ECPoint.GY)
|
||||
val mx = IntArray(8)
|
||||
val my = IntArray(8)
|
||||
val mx = LongArray(4)
|
||||
val my = LongArray(4)
|
||||
ECPoint.toAffine(mixed, mx, my)
|
||||
|
||||
// Add G as Jacobian
|
||||
@@ -177,8 +177,8 @@ class PointTest {
|
||||
gJac.setAffine(ECPoint.GX, ECPoint.GY)
|
||||
val full = MutablePoint()
|
||||
ECPoint.addPoints(full, p, gJac)
|
||||
val fx = IntArray(8)
|
||||
val fy = IntArray(8)
|
||||
val fx = LongArray(4)
|
||||
val fy = LongArray(4)
|
||||
ECPoint.toAffine(full, fx, fy)
|
||||
|
||||
assertEquals(toHex(fx), toHex(mx))
|
||||
@@ -191,8 +191,8 @@ class PointTest {
|
||||
inf.setInfinity()
|
||||
val result = MutablePoint()
|
||||
ECPoint.addMixed(result, inf, ECPoint.GX, ECPoint.GY)
|
||||
val rx = IntArray(8)
|
||||
val ry = IntArray(8)
|
||||
val rx = LongArray(4)
|
||||
val ry = LongArray(4)
|
||||
ECPoint.toAffine(result, rx, ry)
|
||||
assertEquals(toHex(ECPoint.GX), toHex(rx))
|
||||
}
|
||||
@@ -201,11 +201,11 @@ class PointTest {
|
||||
|
||||
@Test
|
||||
fun mulGByOne() {
|
||||
val one = intArrayOf(1, 0, 0, 0, 0, 0, 0, 0)
|
||||
val one = longArrayOf(1, 0, 0, 0, 0, 0, 0, 0)
|
||||
val result = MutablePoint()
|
||||
ECPoint.mulG(result, one)
|
||||
val rx = IntArray(8)
|
||||
val ry = IntArray(8)
|
||||
val rx = LongArray(4)
|
||||
val ry = LongArray(4)
|
||||
ECPoint.toAffine(result, rx, ry)
|
||||
assertEquals(toHex(ECPoint.GX), toHex(rx))
|
||||
assertEquals(toHex(ECPoint.GY), toHex(ry))
|
||||
@@ -213,7 +213,7 @@ class PointTest {
|
||||
|
||||
@Test
|
||||
fun mulGByZeroIsInfinity() {
|
||||
val zero = IntArray(8)
|
||||
val zero = LongArray(4)
|
||||
val result = MutablePoint()
|
||||
ECPoint.mulG(result, zero)
|
||||
assertTrue(result.isInfinity())
|
||||
@@ -233,16 +233,16 @@ class PointTest {
|
||||
val k = hex("67e56582298859ddae725f972992a07c6c4fb9f62a8fff58ce3ca926a1063530")
|
||||
val gResult = MutablePoint()
|
||||
ECPoint.mulG(gResult, k)
|
||||
val gx = IntArray(8)
|
||||
val gy = IntArray(8)
|
||||
val gx = LongArray(4)
|
||||
val gy = LongArray(4)
|
||||
ECPoint.toAffine(gResult, gx, gy)
|
||||
|
||||
val g = MutablePoint()
|
||||
g.setAffine(ECPoint.GX, ECPoint.GY)
|
||||
val mResult = MutablePoint()
|
||||
ECPoint.mul(mResult, g, k)
|
||||
val mx = IntArray(8)
|
||||
val my = IntArray(8)
|
||||
val mx = LongArray(4)
|
||||
val my = LongArray(4)
|
||||
ECPoint.toAffine(mResult, mx, my)
|
||||
|
||||
assertEquals(toHex(mx), toHex(gx))
|
||||
@@ -256,14 +256,14 @@ class PointTest {
|
||||
val e = hex("3982f19bef1615bccfbb05e321c10e1d4cba3df0e841c2e41eeb6016347653c3")
|
||||
|
||||
val p = MutablePoint()
|
||||
val two = intArrayOf(2, 0, 0, 0, 0, 0, 0, 0)
|
||||
val two = longArrayOf(2, 0, 0, 0, 0, 0, 0, 0)
|
||||
ECPoint.mulG(p, two) // P = 2·G
|
||||
|
||||
// Combined
|
||||
val combined = MutablePoint()
|
||||
ECPoint.mulDoubleG(combined, s, p, e)
|
||||
val cx = IntArray(8)
|
||||
val cy = IntArray(8)
|
||||
val cx = LongArray(4)
|
||||
val cy = LongArray(4)
|
||||
ECPoint.toAffine(combined, cx, cy)
|
||||
|
||||
// Separate
|
||||
@@ -273,8 +273,8 @@ class PointTest {
|
||||
ECPoint.mul(eP, p, e)
|
||||
val sep = MutablePoint()
|
||||
ECPoint.addPoints(sep, sG, eP)
|
||||
val sx = IntArray(8)
|
||||
val sy = IntArray(8)
|
||||
val sx = LongArray(4)
|
||||
val sy = LongArray(4)
|
||||
ECPoint.toAffine(sep, sx, sy)
|
||||
|
||||
assertEquals(toHex(sx), toHex(cx))
|
||||
@@ -285,8 +285,8 @@ class PointTest {
|
||||
|
||||
@Test
|
||||
fun liftXGenerator() {
|
||||
val x = IntArray(8)
|
||||
val y = IntArray(8)
|
||||
val x = LongArray(4)
|
||||
val y = LongArray(4)
|
||||
assertTrue(ECPoint.liftX(x, y, ECPoint.GX))
|
||||
assertEquals(toHex(ECPoint.GX), toHex(x))
|
||||
// liftX returns even y
|
||||
@@ -296,8 +296,8 @@ class PointTest {
|
||||
@Test
|
||||
fun liftXInvalidX() {
|
||||
// p itself is not a valid x coordinate
|
||||
val x = IntArray(8)
|
||||
val y = IntArray(8)
|
||||
val x = LongArray(4)
|
||||
val y = LongArray(4)
|
||||
assertFalse(ECPoint.liftX(x, y, FieldP.P))
|
||||
}
|
||||
|
||||
@@ -306,8 +306,8 @@ class PointTest {
|
||||
@Test
|
||||
fun compressDecompressRoundTrip() {
|
||||
val compressed = ECPoint.serializeCompressed(ECPoint.GX, ECPoint.GY)
|
||||
val x = IntArray(8)
|
||||
val y = IntArray(8)
|
||||
val x = LongArray(4)
|
||||
val y = LongArray(4)
|
||||
assertTrue(ECPoint.parsePublicKey(compressed, x, y))
|
||||
assertEquals(toHex(ECPoint.GX), toHex(x))
|
||||
assertEquals(toHex(ECPoint.GY), toHex(y))
|
||||
@@ -316,8 +316,8 @@ class PointTest {
|
||||
@Test
|
||||
fun uncompressedRoundTrip() {
|
||||
val uncompressed = ECPoint.serializeUncompressed(ECPoint.GX, ECPoint.GY)
|
||||
val x = IntArray(8)
|
||||
val y = IntArray(8)
|
||||
val x = LongArray(4)
|
||||
val y = LongArray(4)
|
||||
assertTrue(ECPoint.parsePublicKey(uncompressed, x, y))
|
||||
assertEquals(toHex(ECPoint.GX), toHex(x))
|
||||
assertEquals(toHex(ECPoint.GY), toHex(y))
|
||||
@@ -325,8 +325,8 @@ class PointTest {
|
||||
|
||||
@Test
|
||||
fun parseInvalidKey() {
|
||||
val x = IntArray(8)
|
||||
val y = IntArray(8)
|
||||
val x = LongArray(4)
|
||||
val y = LongArray(4)
|
||||
assertFalse(ECPoint.parsePublicKey(ByteArray(10), x, y))
|
||||
assertFalse(ECPoint.parsePublicKey(ByteArray(33), x, y)) // wrong prefix (0x00)
|
||||
}
|
||||
@@ -338,13 +338,13 @@ class PointTest {
|
||||
p.setAffine(ECPoint.GX, ECPoint.GY)
|
||||
val result = MutablePoint()
|
||||
ECPoint.addMixed(result, p, ECPoint.GX, ECPoint.GY)
|
||||
val rx = IntArray(8)
|
||||
val ry = IntArray(8)
|
||||
val rx = LongArray(4)
|
||||
val ry = LongArray(4)
|
||||
ECPoint.toAffine(result, rx, ry)
|
||||
val doubled = MutablePoint()
|
||||
ECPoint.doublePoint(doubled, p)
|
||||
val dx = IntArray(8)
|
||||
val dy = IntArray(8)
|
||||
val dx = LongArray(4)
|
||||
val dy = LongArray(4)
|
||||
ECPoint.toAffine(doubled, dx, dy)
|
||||
assertEquals(toHex(dx), toHex(rx))
|
||||
}
|
||||
@@ -369,8 +369,8 @@ class PointTest {
|
||||
val pubkey = Secp256k1.pubkeyCreate(privKeyBytes)
|
||||
val compressed = Secp256k1.pubKeyCompress(pubkey)
|
||||
assertEquals(0x03.toByte(), compressed[0]) // Odd y → 03 prefix
|
||||
val x = IntArray(8)
|
||||
val y = IntArray(8)
|
||||
val x = LongArray(4)
|
||||
val y = LongArray(4)
|
||||
assertTrue(ECPoint.parsePublicKey(compressed, x, y))
|
||||
// Round-trip: compress again should give same result
|
||||
val recompressed = ECPoint.serializeCompressed(x, y)
|
||||
|
||||
+9
-9
@@ -43,7 +43,7 @@ class ScalarNTest {
|
||||
|
||||
@Test
|
||||
fun isValidZero() {
|
||||
assertFalse(ScalarN.isValid(IntArray(8)))
|
||||
assertFalse(ScalarN.isValid(LongArray(4)))
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -63,7 +63,7 @@ class ScalarNTest {
|
||||
@Test
|
||||
fun addZeroIdentity() {
|
||||
val a = hex("67e56582298859ddae725f972992a07c6c4fb9f62a8fff58ce3ca926a1063530")
|
||||
assertEquals(toHex(a), toHex(ScalarN.add(a, IntArray(8))))
|
||||
assertEquals(toHex(a), toHex(ScalarN.add(a, LongArray(4))))
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -96,7 +96,7 @@ class ScalarNTest {
|
||||
@Test
|
||||
fun mulOneIdentity() {
|
||||
val a = hex("67e56582298859ddae725f972992a07c6c4fb9f62a8fff58ce3ca926a1063530")
|
||||
val one = intArrayOf(1, 0, 0, 0, 0, 0, 0, 0)
|
||||
val one = longArrayOf(1, 0, 0, 0, 0, 0, 0, 0)
|
||||
assertEquals(toHex(a), toHex(ScalarN.mul(a, one)))
|
||||
}
|
||||
|
||||
@@ -124,7 +124,7 @@ class ScalarNTest {
|
||||
val a = hex("67e56582298859ddae725f972992a07c6c4fb9f62a8fff58ce3ca926a1063530")
|
||||
val aInv = ScalarN.inv(a)
|
||||
val product = ScalarN.mul(a, aInv)
|
||||
val one = intArrayOf(1, 0, 0, 0, 0, 0, 0, 0)
|
||||
val one = longArrayOf(1, 0, 0, 0, 0, 0, 0, 0)
|
||||
assertEquals(toHex(one), toHex(product))
|
||||
}
|
||||
|
||||
@@ -134,7 +134,7 @@ class ScalarNTest {
|
||||
fun addNearN() {
|
||||
// (n-1) + 1 should wrap to 0
|
||||
val nMinus1 = hex("fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140")
|
||||
val one = intArrayOf(1, 0, 0, 0, 0, 0, 0, 0)
|
||||
val one = longArrayOf(1, 0, 0, 0, 0, 0, 0, 0)
|
||||
assertTrue(U256.isZero(ScalarN.add(nMinus1, one)))
|
||||
}
|
||||
|
||||
@@ -142,9 +142,9 @@ class ScalarNTest {
|
||||
fun addNearNWrap() {
|
||||
// (n-1) + 2 should give 1
|
||||
val nMinus1 = hex("fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140")
|
||||
val two = intArrayOf(2, 0, 0, 0, 0, 0, 0, 0)
|
||||
val two = longArrayOf(2, 0, 0, 0, 0, 0, 0, 0)
|
||||
val result = ScalarN.add(nMinus1, two)
|
||||
val one = intArrayOf(1, 0, 0, 0, 0, 0, 0, 0)
|
||||
val one = longArrayOf(1, 0, 0, 0, 0, 0, 0, 0)
|
||||
assertEquals(toHex(one), toHex(result))
|
||||
}
|
||||
|
||||
@@ -153,13 +153,13 @@ class ScalarNTest {
|
||||
// (n-1) * (n-1) ≡ 1 mod n (since (n-1) ≡ -1 and (-1)² = 1)
|
||||
val nMinus1 = hex("fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140")
|
||||
val result = ScalarN.mul(nMinus1, nMinus1)
|
||||
val one = intArrayOf(1, 0, 0, 0, 0, 0, 0, 0)
|
||||
val one = longArrayOf(1, 0, 0, 0, 0, 0, 0, 0)
|
||||
assertEquals(toHex(one), toHex(result))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun negOfZeroIsZero() {
|
||||
assertTrue(U256.isZero(ScalarN.neg(IntArray(8))))
|
||||
assertTrue(U256.isZero(ScalarN.neg(LongArray(4))))
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -37,13 +37,13 @@ class U256Test {
|
||||
// ==================== isZero / cmp ====================
|
||||
|
||||
@Test
|
||||
fun isZeroTrue() = assertTrue(U256.isZero(IntArray(8)))
|
||||
fun isZeroTrue() = assertTrue(U256.isZero(LongArray(4)))
|
||||
|
||||
@Test
|
||||
fun isZeroFalse() = assertFalse(U256.isZero(intArrayOf(1, 0, 0, 0, 0, 0, 0, 0)))
|
||||
fun isZeroFalse() = assertFalse(U256.isZero(longArrayOf(1, 0, 0, 0, 0, 0, 0, 0)))
|
||||
|
||||
@Test
|
||||
fun isZeroHighBit() = assertFalse(U256.isZero(intArrayOf(0, 0, 0, 0, 0, 0, 0, 1)))
|
||||
fun isZeroHighBit() = assertFalse(U256.isZero(longArrayOf(0, 0, 0, 0, 0, 0, 0, 1)))
|
||||
|
||||
@Test
|
||||
fun cmpEqual() = assertEquals(0, U256.cmp(hex("0000000000000000000000000000000000000000000000000000000000000001"), hex("0000000000000000000000000000000000000000000000000000000000000001")))
|
||||
@@ -58,7 +58,7 @@ class U256Test {
|
||||
|
||||
@Test
|
||||
fun addSimple() {
|
||||
val out = IntArray(8)
|
||||
val out = LongArray(4)
|
||||
val carry = U256.addTo(out, hex("0000000000000000000000000000000000000000000000000000000000000001"), hex("0000000000000000000000000000000000000000000000000000000000000002"))
|
||||
assertEquals("0000000000000000000000000000000000000000000000000000000000000003", toHex(out))
|
||||
assertEquals(0, carry)
|
||||
@@ -66,7 +66,7 @@ class U256Test {
|
||||
|
||||
@Test
|
||||
fun addOverflow() {
|
||||
val out = IntArray(8)
|
||||
val out = LongArray(4)
|
||||
val carry = U256.addTo(out, hex("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), hex("0000000000000000000000000000000000000000000000000000000000000001"))
|
||||
assertEquals("0000000000000000000000000000000000000000000000000000000000000000", toHex(out))
|
||||
assertEquals(1, carry)
|
||||
@@ -74,14 +74,14 @@ class U256Test {
|
||||
|
||||
@Test
|
||||
fun addLimbCarry() {
|
||||
val out = IntArray(8)
|
||||
val out = LongArray(4)
|
||||
U256.addTo(out, hex("00000000000000000000000000000000000000000000000000000000ffffffff"), hex("0000000000000000000000000000000000000000000000000000000000000001"))
|
||||
assertEquals("0000000000000000000000000000000000000000000000000000000100000000", toHex(out))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun subSimple() {
|
||||
val out = IntArray(8)
|
||||
val out = LongArray(4)
|
||||
val borrow = U256.subTo(out, hex("0000000000000000000000000000000000000000000000000000000000000003"), hex("0000000000000000000000000000000000000000000000000000000000000001"))
|
||||
assertEquals("0000000000000000000000000000000000000000000000000000000000000002", toHex(out))
|
||||
assertEquals(0, borrow)
|
||||
@@ -89,7 +89,7 @@ class U256Test {
|
||||
|
||||
@Test
|
||||
fun subUnderflow() {
|
||||
val out = IntArray(8)
|
||||
val out = LongArray(4)
|
||||
val borrow = U256.subTo(out, hex("0000000000000000000000000000000000000000000000000000000000000000"), hex("0000000000000000000000000000000000000000000000000000000000000001"))
|
||||
assertEquals("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", toHex(out))
|
||||
assertEquals(1, borrow)
|
||||
@@ -99,7 +99,7 @@ class U256Test {
|
||||
|
||||
@Test
|
||||
fun mulWideSmall() {
|
||||
val out = IntArray(16)
|
||||
val out = LongArray(8)
|
||||
U256.mulWide(out, hex("0000000000000000000000000000000000000000000000000000000000000003"), hex("0000000000000000000000000000000000000000000000000000000000000007"))
|
||||
// 3 * 7 = 21 = 0x15
|
||||
assertEquals(0x15, out[0])
|
||||
@@ -109,8 +109,8 @@ class U256Test {
|
||||
@Test
|
||||
fun mulWideLarge() {
|
||||
// (2^128 - 1)² consistency: mulWide and sqrWide should match
|
||||
val out1 = IntArray(16)
|
||||
val out2 = IntArray(16)
|
||||
val out1 = LongArray(8)
|
||||
val out2 = LongArray(8)
|
||||
val maxHalf = hex("00000000000000000000000000000000ffffffffffffffffffffffffffffffff")
|
||||
U256.mulWide(out1, maxHalf, maxHalf)
|
||||
U256.sqrWide(out2, maxHalf)
|
||||
@@ -123,9 +123,9 @@ class U256Test {
|
||||
fun sqrWideMatchesMulWide() {
|
||||
// sqrWide(a) should produce the same result as mulWide(a, a)
|
||||
val a = hex("67E56582298859DDAE725F972992A07C6C4FB9F62A8FFF58CE3CA926A1063530")
|
||||
val mulResult = IntArray(16)
|
||||
val mulResult = LongArray(8)
|
||||
U256.mulWide(mulResult, a, a)
|
||||
val sqrResult = IntArray(16)
|
||||
val sqrResult = LongArray(8)
|
||||
U256.sqrWide(sqrResult, a)
|
||||
for (i in 0 until 16) {
|
||||
assertEquals(mulResult[i], sqrResult[i], "Limb $i mismatch")
|
||||
@@ -136,9 +136,9 @@ class U256Test {
|
||||
fun sqrWideMaxValue() {
|
||||
// (2^256 - 1)^2 should match mulWide
|
||||
val maxVal = hex("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")
|
||||
val mulResult = IntArray(16)
|
||||
val mulResult = LongArray(8)
|
||||
U256.mulWide(mulResult, maxVal, maxVal)
|
||||
val sqrResult = IntArray(16)
|
||||
val sqrResult = LongArray(8)
|
||||
U256.sqrWide(sqrResult, maxVal)
|
||||
for (i in 0 until 16) {
|
||||
assertEquals(mulResult[i], sqrResult[i], "Limb $i mismatch for max value sqr")
|
||||
@@ -201,7 +201,7 @@ class U256Test {
|
||||
|
||||
@Test
|
||||
fun xorBasic() {
|
||||
val out = IntArray(8)
|
||||
val out = LongArray(4)
|
||||
U256.xorTo(out, hex("ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00"), hex("0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f"))
|
||||
assertEquals("f00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00f", toHex(out))
|
||||
}
|
||||
@@ -221,7 +221,7 @@ class U256Test {
|
||||
@Test
|
||||
fun copyIntoTest() {
|
||||
val src = hex("67e56582298859ddae725f972992a07c6c4fb9f62a8fff58ce3ca926a1063530")
|
||||
val dst = IntArray(8)
|
||||
val dst = LongArray(4)
|
||||
U256.copyInto(dst, src)
|
||||
for (i in 0 until 8) assertEquals(src[i], dst[i])
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user