示例#1
0
def FQP_point_to_FQ2_point(pt: Tuple[FQP, FQP, FQP]) -> Tuple[FQ2, FQ2, FQ2]:
    """
    Transform FQP to FQ2 for type hinting.
    """
    return (
        FQ2(pt[0].coeffs),
        FQ2(pt[1].coeffs),
        FQ2(pt[2].coeffs),
    )
示例#2
0
def hash_to_G2(message: bytes, domain: int) -> Tuple[FQ2, FQ2, FQ2]:
    x_coordinate = _get_x_coordinate(message, domain)

    # Test candidate y coordinates until a one is found
    while 1:
        y_coordinate_squared = x_coordinate**3 + FQ2(
            [4, 4])  # The curve is y^2 = x^3 + 4(i + 1)
        y_coordinate = modular_squareroot(y_coordinate_squared)
        if y_coordinate is not None:  # Check if quadratic residue found
            break
        x_coordinate += FQ2([1, 0])  # Add 1 and try again

    return multiply((x_coordinate, y_coordinate, FQ2([1, 0])), G2_cofactor)
示例#3
0
def test_get_x_coordinate(message, domain):
    x_coordinate = _get_x_coordinate(message, domain)
    domain_in_bytes = domain.to_bytes(8, 'big')
    assert x_coordinate == FQ2([
        big_endian_to_int(hash_eth2(message + domain_in_bytes + b'\x01')),
        big_endian_to_int(hash_eth2(message + domain_in_bytes + b'\x02')),
    ])
示例#4
0
def hash_to_G2(message: bytes, domain: int) -> Tuple[FQ2, FQ2, FQ2]:
    domain_in_bytes = domain.to_bytes(8, 'big')

    # Initial candidate x coordinate
    x_re = big_endian_to_int(hash_eth2(domain_in_bytes + b'\x01' + message))
    x_im = big_endian_to_int(hash_eth2(domain_in_bytes + b'\x02' + message))
    x_coordinate = FQ2([x_re, x_im])  # x_re + x_im * i

    # Test candidate y coordinates until a one is found
    while 1:
        y_coordinate_squared = x_coordinate**3 + FQ2(
            [4, 4])  # The curve is y^2 = x^3 + 4(i + 1)
        y_coordinate = modular_squareroot(y_coordinate_squared)
        if y_coordinate is not None:  # Check if quadratic residue found
            break
        x_coordinate += FQ2([1, 0])  # Add 1 and try again

    return multiply((x_coordinate, y_coordinate, FQ2([1, 0])), G2_cofactor)
示例#5
0
def _get_x_coordinate(message: bytes, domain: int) -> FQ2:
    domain_in_bytes = domain.to_bytes(8, 'big')

    # Initial candidate x coordinate
    x_re = big_endian_to_int(hash_eth2(message + domain_in_bytes + b'\x01'))
    x_im = big_endian_to_int(hash_eth2(message + domain_in_bytes + b'\x02'))
    x_coordinate = FQ2([x_re, x_im])  # x_re + x_im * i

    return x_coordinate
示例#6
0
def decompress_G2(p: Tuple[int, int]) -> Tuple[FQP, FQP, FQP]:
    x1 = p[0] % 2**383
    y1_mod_2 = p[0] // 2**383
    x2 = p[1]
    x = FQ2([x1, x2])
    if x == FQ2([0, 0]):
        return FQ2([1, 0]), FQ2([1, 0]), FQ2([0, 0])
    y = modular_squareroot(x**3 + b2)
    if y.coeffs[0] % 2 != y1_mod_2:
        y = FQ2((y * -1).coeffs)
    if not is_on_curve((x, y, FQ2([1, 0])), b2):
        raise ValueError(
            "The given point is not on the twisted curve over FQ**2")
    return x, y, FQ2([1, 0])
示例#7
0
def modular_squareroot(value: int) -> FQP:
    """
    ``modular_squareroot(x)`` returns the value ``y`` such that ``y**2 % q == x``,
    and None if this is not possible. In cases where there are two solutions,
    the value with higher imaginary component is favored;
    if both solutions have equal imaginary component the value with higher real
    component is favored.
    """
    candidate_squareroot = value**((FQ2_order + 8) // 16)
    check = candidate_squareroot**2 / value
    if check in eighth_roots_of_unity[::2]:
        x1 = candidate_squareroot / eighth_roots_of_unity[
            eighth_roots_of_unity.index(check) // 2]
        x2 = FQ2([-x1.coeffs[0], -x1.coeffs[1]])  # x2 = -x1
        return x1 if (x1.coeffs[1], x1.coeffs[0]) > (x2.coeffs[1],
                                                     x2.coeffs[0]) else x2
    return None
示例#8
0
def modular_squareroot(value: FQ2) -> FQP:
    """
    ``modular_squareroot(x)`` returns the value ``y`` such that ``y**2 % q == x``,
    and None if this is not possible. In cases where there are two solutions,
    the value with higher imaginary component is favored;
    if both solutions have equal imaginary component the value with higher real
    component is favored.
    """
    candidate_squareroot = value**((FQ2_order + 8) // 16)
    check = candidate_squareroot**2 / value
    if check in eighth_roots_of_unity[::2]:
        x1 = candidate_squareroot / eighth_roots_of_unity[
            eighth_roots_of_unity.index(check) // 2]
        # TODO: fix pending upstream fix https://github.com/ethereum/py_ecc/issues/47
        #       % q shouldn't be needed
        x2 = FQ2([-x1.coeffs[0] % q, -x1.coeffs[1] % q])  # x2 = -x1
        return x1 if (x1.coeffs[1], x1.coeffs[0]) > (x2.coeffs[1],
                                                     x2.coeffs[0]) else x2
    return None
def _convert_fp2_to_int(fp2_repr):
    a, b = fp2_repr
    return FQ2((_convert_fp_to_int(a), _convert_fp_to_int(b)))
示例#10
0
    ValidationError,
)

from py_ecc.optimized_bls12_381 import (  # NOQA
    G1, G2, Z1, Z2, neg, add, multiply, FQ, FQ2, FQ12, FQP, pairing, normalize,
    field_modulus as q, b, b2, is_on_curve, curve_order, final_exponentiate)
from eth2.beacon._utils.hash import hash_eth2

from eth2.beacon.typing import (
    BLSPubkey,
    BLSSignature,
)

G2_cofactor = 305502333931268344200999753193121504214466019254188142667664032982267604182971884026507427359259977847832272839041616661285803823378372096355777062779109  # noqa: E501
FQ2_order = q**2 - 1
eighth_roots_of_unity = [FQ2([1, 1])**((FQ2_order * k) // 8) for k in range(8)]


#
# Helpers
#
def FQP_point_to_FQ2_point(pt: Tuple[FQP, FQP, FQP]) -> Tuple[FQ2, FQ2, FQ2]:
    """
    Transform FQP to FQ2 for type hinting.
    """
    return (
        FQ2(pt[0].coeffs),
        FQ2(pt[1].coeffs),
        FQ2(pt[2].coeffs),
    )