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