Search code examples
javabouncycastleelliptic-curve

Bouncycastle migration from python fastecdsa library for Custom Fp Curve


Due to some security requirements, we need to implement a sign/verify for a custom EC Curve defined as: https://docs.starkware.co/starkex/crypto/stark-curve.html, the issue I am encountering is that the result of Point multiplication does not equal the existing python implementation - which as can be imagined, breaks all other functionality.

import org.bouncycastle.math.ec.ECCurve
import org.junit.jupiter.api.Test
import java.math.BigInteger

internal class StarkEcTest {
    @Test
    fun testIt() {
        val curve: ECCurve = ECCurve.Fp(
            BigInteger("3618502788666131213697322783095070105623107215331596699973092056135872020481"),
            BigInteger.ONE,
            BigInteger("3141592653589793238462643383279502884197169399375105820974944592307816406665"),
            BigInteger("3618502788666131213697322783095070105526743751716087489154079457884512865583"),
            BigInteger.ONE
        )
        val p = curve.createPoint(
            BigInteger("2251563274489750535117886426533222435294046428347329203627021249169616184184"),
            BigInteger("1798716007562728905295480679789526322175868328062420237419143593021674992973")
        )
        val m = p.multiply(BigInteger("3"))
        println(m.xCoord.toBigInteger())
        println(m.yCoord.toBigInteger())
    }
}

python

from fastecdsa.curve import Curve
from fastecdsa.point import Point


curve = Curve(
    'Curve0',
    3618502788666131213697322783095070105623107215331596699973092056135872020481,
    1,
    3141592653589793238462643383279502884197169399375105820974944592307816406665,
    3618502788666131213697322783095070105526743751716087489154079457884512865583,
    None, None)

P_1 = Point(2251563274489750535117886426533222435294046428347329203627021249169616184184,
            1798716007562728905295480679789526322175868328062420237419143593021674992973, curve=curve)
M = P_1 * 3
print(M.x)
print(M.y)

bouncycastle output:

2795384649576597138876330049383140213054452425478601942220916936105483260349
2237299821780817033836570741512068317061212432514505879654119963526983263668

python output:

2692261938318494776777664756074555416313431118463720872468237610494977391696
3211431005308242515933993754747870488911784503098259550627317667807118007131

Can anyone spot somewhere I've gone wrong?


Solution

  • It will work if you normalize point in java:

    val m = p.multiply(BigInteger("3")).normalize()