Challenge:

import random
from hidden import DollarStore
p = 95773813056613526295315889615423014145567365190638271416026411091272805051097
def legendre(a, p):
    return pow(a, (p - 1) // 2, p)

def tonelli(n, p):
    q = p - 1
    s = 0
    while q % 2 == 0:
        q //= 2
        s += 1
    if s == 1:
        return pow(n, (p + 1) // 4, p)
    for z in range(2, p):
        if p - 1 == legendre(z, p):
            break
    c = pow(z, q, p)
    r = pow(n, (q + 1) // 2, p)
    t = pow(n, q, p)
    m = s
    t2 = 0
    while (t - 1) % p != 0:
        t2 = (t * t) % p
        for i in range(1, m):
            if (t2 - 1) % p == 0:
                break
            t2 = (t2 * t2) % p
        b = pow(c, 1 << (m - i - 1), p)
        r = (r * b) % p
        c = (b * b) % p
        t = (t * c) % p
        m = i
    return r
class EllipticCurve:
    def __init__ (self, a, b, p):
        self.p = p
        self.a = a
        self.b = b
    def getPoint(self, x):
        ys = (x**3 + self.a*x + self.b) % p
        if legendre(ys, self.p) != 1:
            return None
        y = tonelli( ys ,p)
        return CurvePoint(x, y, self)
    
class CurvePoint:
    def __init__(self,x,y, curve):
        self.curve = curve
        self.x = x % curve.p
        self.y = y % curve.p
    def __str__(self):
        return f"({self.x},{self.y})"
    def __eq__(self, other):
        return str(self) == str(other)
    __repr__ = __str__
    def __add__(self, other):
        x1,y1 = self.x, self.y
        x2,y2 = other.x, other.y
        if x2 == 0 and y2 == 1:
            return self
        if x1 == 0 and y1 == 1:
            return other
        if x1 == x2 and y2 == self.curve.p - y1:
            return CurvePoint(0, 1, self.curve)
        if x1 == x2 and y1 == y2:
            lam = ((3*pow(x1, 2, self.curve.p) + self.curve.a) * pow(2* y1, -1, self.curve.p))% self.curve.p
        else:
            lam = ((y2 - y1) * pow(x2 - x1, -1, self.curve.p)) % self.curve.p
        x = (lam**2 - x1 - x2) % self.curve.p
        y = (lam*(x1 -x) - y1) % self.curve.p
        return CurvePoint(x, y, self.curve)


def scalar_mult(x, n, ec) -> CurvePoint:
    Q = x
    R = CurvePoint(0,1 ,ec)
    if n == 0: return R
    if n == 1: return x
    while n > 0:
        if n % 2 == 1:
            R = R + Q
        Q = Q + Q
        n = n // 2
    return R

flag = "lactf{REDACTED}" 

flag = flag.lstrip("lactf{").rstrip("}")

flagarray = [((random.randrange(2**10) >> 8) << 8) + ord(flag[i]) for i in range(len(flag))]

ec = DollarStore()

points = []
while len(points) < len(flagarray):
    x = random.randrange(p)
    point = ec.getPoint(x)
    if point != None:
        points.append(point)

s = scalar_mult(points[0], flagarray[0], ec)
for i in range(1,len(flagarray)):
    s += (scalar_mult(points[i], flagarray[i], ec))

print(f"s= {s}")

print(f"points = {points}")

Output:

s= (4690331917760414380672348505790486524786128272326163170078478915876334878778,77902523131087061897126273610460347147805642819184490444996378236375931739511)

points = [(48868244275342945713292068450286493306842109652612873048852850861527337784625,8598765896895208028227058726713353098258128734049351946507804225327296634514), (72658254142472216221352003377742816858998248904595208415554148006123670275598,71428807550814004521976397789820845661680868197262344890701351814974388342261), (67870089007566708724312416903523370462932434169535354040601985891516954713089,8943567664814248988234978385637474582139875658136599562153182844933110782161), (33253625948635661442757699647500419774784100109285386672321733886811106048412,12192737861983844212244996021850136772489630870822316368037176061423925074233), (66860062037424526223822695383825242848539148827022939438364758097578810377221,58417846450117166884245720025471073320694519590707170823524720597081409174976), (28494672393178906436249791305135018577103930778774058381902322150406763293156,62195276890799494520787073550388771924399268413246266294642567344115775718432), (6537035443546098222408014705048663302006517570643500213251743726265246911764,63349815264954414001975570394948853390727370840181019491330859064400691177034), (9320970269062399750695489734826172234568831562993926393303183822807296243087,34696165501221265426922128243581570921860165265147807824051427532585333222152), (18573558660261827041235280489756954152038727051914639466830055088004904233178,19919769712016625050600762893366674039791157427716018448797516577097120142300), (16615614708193334022500574592689709918593068922396962286039360740901902767297,60958319794367285409532630915520850753365486357306708351189641978639088395040), (83083247653266404965046108107297707899250352411953326131401506377288013650507,88351052151438822336155560751456315613347554340471433918143267841048354530206), (13931833861234698857264824825124064884725829615801172933808997361805649306770,1863009430945401243652911885817518397081699859060155426336485589307965515267), (82335726721747347474239651051504187390571418091882782437152555488102933140061,75024532808592482514720186660630997309420973593419858494992760319543418493327), (15679700475641029146383479082391061723840711201191220489551315259170835916116,4902015468380176276259510377701509023242706106231852614815501538737950056248), (69563107209744135957874607288632923528358557330713606279779688661831937343313,47637699504526623569498379978585572196126141235987754666684744952203096777656), (12240300385069346445384926360689199410381482418493148959106963671703717348546,23386458637256108310036365005044561845597767155973474723611711176033278672500), (2686945382892345707901179849163807293774497407910463972517367748359032899306,63993175447658077329987948939524654748779134053698498595737451593308819319039)]

Solve:

First we’ll assume the given p is the curve p, then solve the curve parameters a and b.

p = 95773813056613526295315889615423014145567365190638271416026411091272805051097
points = [(48868244275342945713292068450286493306842109652612873048852850861527337784625,8598765896895208028227058726713353098258128734049351946507804225327296634514), (72658254142472216221352003377742816858998248904595208415554148006123670275598,71428807550814004521976397789820845661680868197262344890701351814974388342261), (67870089007566708724312416903523370462932434169535354040601985891516954713089,8943567664814248988234978385637474582139875658136599562153182844933110782161), (33253625948635661442757699647500419774784100109285386672321733886811106048412,12192737861983844212244996021850136772489630870822316368037176061423925074233), (66860062037424526223822695383825242848539148827022939438364758097578810377221,58417846450117166884245720025471073320694519590707170823524720597081409174976), (28494672393178906436249791305135018577103930778774058381902322150406763293156,62195276890799494520787073550388771924399268413246266294642567344115775718432), (6537035443546098222408014705048663302006517570643500213251743726265246911764,63349815264954414001975570394948853390727370840181019491330859064400691177034), (9320970269062399750695489734826172234568831562993926393303183822807296243087,34696165501221265426922128243581570921860165265147807824051427532585333222152), (18573558660261827041235280489756954152038727051914639466830055088004904233178,19919769712016625050600762893366674039791157427716018448797516577097120142300), (16615614708193334022500574592689709918593068922396962286039360740901902767297,60958319794367285409532630915520850753365486357306708351189641978639088395040), (83083247653266404965046108107297707899250352411953326131401506377288013650507,88351052151438822336155560751456315613347554340471433918143267841048354530206), (13931833861234698857264824825124064884725829615801172933808997361805649306770,1863009430945401243652911885817518397081699859060155426336485589307965515267), (82335726721747347474239651051504187390571418091882782437152555488102933140061,75024532808592482514720186660630997309420973593419858494992760319543418493327), (15679700475641029146383479082391061723840711201191220489551315259170835916116,4902015468380176276259510377701509023242706106231852614815501538737950056248), (69563107209744135957874607288632923528358557330713606279779688661831937343313,47637699504526623569498379978585572196126141235987754666684744952203096777656), (12240300385069346445384926360689199410381482418493148959106963671703717348546,23386458637256108310036365005044561845597767155973474723611711176033278672500), (2686945382892345707901179849163807293774497407910463972517367748359032899306,63993175447658077329987948939524654748779134053698498595737451593308819319039)]
p1x, p1y = points[0][0], points[0][1]
p2x, p2y = points[1][0], points[1][1]

M = Matrix(GF(p), [[p1x,1],[p2x,1]])
a, b = M.solve_right(vector([p1y^2-p1x^3,p2y^2-p2x^3]))
print(a, b)

Interesting, a=0 and b=0. So the curve equation is y^2 = x^3, and we have an elliptic cusp.

It was kinda similar to this chall but we need a way to take discrete logs with the cusp.

The second answer here is helpful: https://crypto.stackexchange.com/questions/61302/how-to-solve-this-ecdlp

So we pick a random g, take the discrete log of everything, transforming it to a regular knapsack problem.

load('https://gist.githubusercontent.com/Connor-McCartney/952583ecac836f843f50b785c7cb283d/raw/5718ebd8c9b4f9a549746094877a97e7796752eb/solvelinmod.py')

p = 95773813056613526295315889615423014145567365190638271416026411091272805051097
s = (4690331917760414380672348505790486524786128272326163170078478915876334878778,77902523131087061897126273610460347147805642819184490444996378236375931739511)
points = [(48868244275342945713292068450286493306842109652612873048852850861527337784625,8598765896895208028227058726713353098258128734049351946507804225327296634514), (72658254142472216221352003377742816858998248904595208415554148006123670275598,71428807550814004521976397789820845661680868197262344890701351814974388342261), (67870089007566708724312416903523370462932434169535354040601985891516954713089,8943567664814248988234978385637474582139875658136599562153182844933110782161), (33253625948635661442757699647500419774784100109285386672321733886811106048412,12192737861983844212244996021850136772489630870822316368037176061423925074233), (66860062037424526223822695383825242848539148827022939438364758097578810377221,58417846450117166884245720025471073320694519590707170823524720597081409174976), (28494672393178906436249791305135018577103930778774058381902322150406763293156,62195276890799494520787073550388771924399268413246266294642567344115775718432), (6537035443546098222408014705048663302006517570643500213251743726265246911764,63349815264954414001975570394948853390727370840181019491330859064400691177034), (9320970269062399750695489734826172234568831562993926393303183822807296243087,34696165501221265426922128243581570921860165265147807824051427532585333222152), (18573558660261827041235280489756954152038727051914639466830055088004904233178,19919769712016625050600762893366674039791157427716018448797516577097120142300), (16615614708193334022500574592689709918593068922396962286039360740901902767297,60958319794367285409532630915520850753365486357306708351189641978639088395040), (83083247653266404965046108107297707899250352411953326131401506377288013650507,88351052151438822336155560751456315613347554340471433918143267841048354530206), (13931833861234698857264824825124064884725829615801172933808997361805649306770,1863009430945401243652911885817518397081699859060155426336485589307965515267), (82335726721747347474239651051504187390571418091882782437152555488102933140061,75024532808592482514720186660630997309420973593419858494992760319543418493327), (15679700475641029146383479082391061723840711201191220489551315259170835916116,4902015468380176276259510377701509023242706106231852614815501538737950056248), (69563107209744135957874607288632923528358557330713606279779688661831937343313,47637699504526623569498379978585572196126141235987754666684744952203096777656), (12240300385069346445384926360689199410381482418493148959106963671703717348546,23386458637256108310036365005044561845597767155973474723611711176033278672500), (2686945382892345707901179849163807293774497407910463972517367748359032899306,63993175447658077329987948939524654748779134053698498595737451593308819319039)]

def cusp_log(P, G, p):
    gx, gy = G
    px, py = P
    d = ( pow(gx * pow(gy, -1, p), -1, p) * (px * pow(py, -1, p)) ) % p
    return d

G = points[0]
logs = [cusp_log(P, G, p) for P in points]

xs = [var(f"x_{i}") for i in range(len(points))]
eq = (sum(x*i for x, i in zip(xs, logs)) == cusp_log(s, G, p))
bounds = {x: 1024 for x in xs}
sol = solve_linear_mod([(eq, p)], bounds)
print(bytes([i%256 for i in sol.values()]))
# lactf{im_w4y_t00_br0k3!}