#Bad-Rabbit

import collections
import random

EllipticCurve = collections.namedtuple('EllipticCurve', 'name p a b g n h')

curve = EllipticCurve(
    'secp256k1',
    # РџСЂРѕСЃС‚РѕР№ РјРѕРґСѓР»СЊ.
    p=0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f,
    # РџР°СЂР°РјРµС‚СЂС‹ РїРµСЂРµРјРµРЅРЅС‹С….
    a=0,
    b=7,
    # Р‘Р°Р·РѕРІР°СЏ С‚РѕС‡РєР°.
    g=(0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798,
       0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8),
    # РџРѕСЂСЏРґРѕРє РєСЂРёРІРѕР№.
    n=0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141,
    # РџРѕРґРіСЂСѓРїРїР°.
    h=1,
)

# РњРѕРґСѓР»СЊРЅР°СЏ Р°СЂРёС„РјРµС‚РёРєР° ##########################################################

def inverse_mod(k, p):
    """Returns the inverse of k modulo p.

    This function returns the only integer x such that (x * k) % p == 1.

    k must be non-zero and p must be a prime.
    """
    if k == 0:
        raise ZeroDivisionError('division by zero')

    if k < 0:
        # k ** -1 = p - (-k) ** -1  (mod p)
        return p - inverse_mod(-k, p)

    # Р Р°СЃС€РёСЂРµРЅРЅС‹Р№ РђР»РіРѕСЂРёС‚Рј Р•РІРєР»РёРґР°.
    s, old_s = 0, 1
    t, old_t = 1, 0
    r, old_r = p, k

    while r != 0:
        quotient = old_r // r
        old_r, r = r, old_r - quotient * r
        old_s, s = s, old_s - quotient * s
        old_t, t = t, old_t - quotient * t

    gcd, x, y = old_r, old_s, old_t

    assert gcd == 1
    assert (k * x) % p == 1

    return x % p


# Р¤СѓРЅРєС†РёСЏ РґР»СЏ СЂР°Р±РѕС‚С‹ Р°СЂРёС„РјРµС‚РёРєРё С‚РѕС‡РµРє #########################################

def is_on_curve(point):
    """Returns True if the given point lies on the elliptic curve."""
    if point is None:
        # Р”Р»СЏ С‚РѕС‡РµРє СЃ РІРѕР·РјРѕР¶РЅРѕСЃС‚СЊСЋ СЂРµРєСѓСЂСЃРёРё.
        return True

    x, y = point

    return (y * y - x * x * x - curve.a * x - curve.b) % curve.p == 0


def point_neg(point):
    """Returns -point."""
    assert is_on_curve(point)

    if point is None:
        # -0 = 0
        return None

    x, y = point
    result = (x, -y % curve.p)

    assert is_on_curve(result)

    return result


def point_add(point1, point2):
    """Returns the result of point1 + point2 according to the group law."""
    assert is_on_curve(point1)
    assert is_on_curve(point2)

    if point1 is None:
        # 0 + point2 = point2
        return point2
    if point2 is None:
        # point1 + 0 = point1
        return point1

    x1, y1 = point1
    x2, y2 = point2

    if x1 == x2 and y1 != y2:
        # point1 + (-point1) = 0
        return None

    if x1 == x2:
        # РЈРґРІРѕРµРЅРёРµ С‚РѕС‡РєРё point1 == point2.
        m = (3 * x1 * x1 + curve.a) * inverse_mod(2 * y1, curve.p)
    else:
        # РЎР»РѕР¶РµРЅРёРµ С‚РѕС‡РµРє point1 != point2.
        m = (y1 - y2) * inverse_mod(x1 - x2, curve.p)

    x3 = m * m - x1 - x2
    y3 = y1 + m * (x3 - x1)
    result = (x3 % curve.p,
              -y3 % curve.p)

    assert is_on_curve(result)

    return result


def scalar_mult(k, point):
    """Returns k * point computed using the double and point_add algorithm."""
    assert is_on_curve(point)

    if k % curve.n == 0 or point is None:
        return None

    if k < 0:
        # k * point = -k * (-point)
        return scalar_mult(-k, point_neg(point))

    result = None
    addend = point

    while k:
        if k & 1:
            # РЎРѕР·РґР°Р»Рё.
            result = point_add(result, addend)

        # РџРѕРІС‚РѕСЂРёР»Рё.
        addend = point_add(addend, addend)

        k >>= 1

    assert is_on_curve(result)

    return result

# РЎРєР°Р»СЏСЂРЅРѕРµ РґРµР»РµРЅРёРµ С‚Р°РєРѕРµ Р¶Рµ РєР°Рє Рё СѓРјРЅРѕР¶РµРЅРёРµ ##########################################
def chetchek(point):
    vic = scalar_mult(0x3fffffffffffffffffffffffffffffffaeabb739abd2280eeff497a3340d9050, curve.g)
    chek1 = scalar_mult(0x7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a1, curve.g)
    chek2 = point_add(curve.g, chek1)
    brpoint = point_add(curve.g, point_neg(point))
    p1 = point_add(point, point_neg(vic))
    p2 = point_add(brpoint, point_neg(vic))
    br1p = point_add(curve.g, point_neg(p1))
    br2p = point_add(curve.g, point_neg(p2))
    chekpoint1 = point_add(p1, p2)
    chekpoint2 = point_add(br1p, br2p)
    if chekpoint1 == chek1:
        return "первая половина"
    else:
        return "вторая половина"
    
# Р’ Р±СѓРґСѓСЋС‰РµРј РёР· СЌС‚РѕРіРѕ РіРµРЅРµСЂРёСЂСѓСЋС‚ ECDSA ################################################

def make_keypair():
    """Generates a random private-public key pair."""
    private_key = random.randrange(1, curve.n)
    public_key = scalar_mult(private_key, curve.g)

#С‚РµР»Рѕ РїСЂРѕРіСЂР°РјРјС‹, СЃР°РјР°СЏ СЃР»РѕР¶РЅР°СЏ С…СѓРµС‚Р°###################################################
P  = (0xf98c0f45dd33ed5fc6c942755089f0c7937cc864475d5fb2159c68cb102167f6, 0xcf2f4444e97a33a3d92eefcb600d0a4952dea14868528d5c92c91f5085256a3c)
t = 0
r = scalar_mult(2, curve.g)
t = 0x7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a1
e = point_neg(P)
i = scalar_mult(t, P)
print(e, i)