Ejemplo n.º 1
0
    def from_bytes(cls, data: bytes, curve: ec.EllipticCurve = None):
        """
        Instantiate CorrectnessProof from serialized data.
        """
        curve = curve if curve is not None else default_curve()
        key_size = get_curve_keysize_bytes(curve)
        data = BytesIO(data)

        # CurveBNs are the keysize in bytes, Points are compressed and the
        # keysize + 1 bytes long.
        e2 = Point.from_bytes(data.read(key_size + 1), curve)
        v2 = Point.from_bytes(data.read(key_size + 1), curve)
        kfrag_commitment = Point.from_bytes(data.read(key_size + 1), curve)
        kfrag_pok = Point.from_bytes(data.read(key_size + 1), curve)
        kfrag_sig1 = CurveBN.from_bytes(data.read(key_size), curve)
        kfrag_sig2 = CurveBN.from_bytes(data.read(key_size), curve)
        sig = CurveBN.from_bytes(data.read(key_size), curve)

        metadata = data.read() or None

        return cls(e2,
                   v2,
                   kfrag_commitment,
                   kfrag_pok,
                   kfrag_sig1,
                   kfrag_sig2,
                   sig,
                   metadata=metadata)
Ejemplo n.º 2
0
def test_bytes_serializers(point_bytes, nid, curve):

    point_with_nid = Point.from_bytes(point_bytes, curve=nid)  # from nid
    assert isinstance(point_with_nid, Point)

    point_with_curve = Point.from_bytes(point_bytes, curve=curve)  # from curve
    assert isinstance(point_with_curve, Point)

    assert point_with_nid == point_with_curve

    the_same_point_bytes = point_with_curve.to_bytes()
    assert point_bytes == the_same_point_bytes

    representations = (
        point_bytes,  # Compressed representation
        point_with_curve.to_bytes(is_compressed=False))  # Uncompressed

    for point_representation in representations:

        malformed_point_bytes = point_bytes + b'0x'
        with pytest.raises(ValueError):
            _ = Point.from_bytes(malformed_point_bytes)

        malformed_point_bytes = point_bytes[1:]
        with pytest.raises(ValueError):
            _ = Point.from_bytes(malformed_point_bytes)

        malformed_point_bytes = point_bytes[:-1]
        with pytest.raises(ValueError):
            _ = Point.from_bytes(malformed_point_bytes)
Ejemplo n.º 3
0
def test_bytes_serializers(point_bytes, nid, curve):

    point_with_nid = Point.from_bytes(point_bytes, curve=nid)  # from nid
    assert isinstance(point_with_nid, Point)

    point_with_curve = Point.from_bytes(point_bytes, curve=curve)  # from curve
    assert isinstance(point_with_curve, Point)

    assert point_with_nid == point_with_curve

    the_same_point_bytes = point_with_curve.to_bytes(is_compressed=False)
    assert point_bytes == the_same_point_bytes

    malformed_point_bytes = point_bytes + b'0x'
    with pytest.raises(ValueError):
        _ = Point.from_bytes(malformed_point_bytes)
Ejemplo n.º 4
0
def test_generator_point():
    """http://www.secg.org/SEC2-Ver-1.0.pdf Section 2.7.1"""
    g1 = Point.get_generator_from_curve()

    g_compressed = 0x0279BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798
    g_uncompressed = 0x0479BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8

    g_compressed = g_compressed.to_bytes(32 + 1, byteorder='big')
    g_uncompressed = g_uncompressed.to_bytes(64 + 1, byteorder='big')

    g2 = Point.from_bytes(g_compressed)
    assert g1 == g2

    g3 = Point.from_bytes(g_uncompressed)
    assert g1 == g3
    assert g2 == g3
Ejemplo n.º 5
0
def test_point_not_on_curve():
    """
    We want to be unable to create a Point that's not on the curve.

    When we try, we get cryptography.exceptions.InternalError - is that specifically because it isn't
    on the curve?  It seems to be reliably raised in the event of the Point being off the curve.

    The OpenSSL docs don't explicitly say that they raise an error for this reason:
    https://www.openssl.org/docs/man1.1.0/crypto/EC_GFp_simple_method.html
    """
    point_on_koblitz256_but_not_P256 = Point.from_bytes(b'\x03%\x98Dk\x88\xe2\x97\xab?\xabZ\xef\xd4' \
    b'\x9e\xaa\xc6\xb3\xa4\xa3\x89\xb2\xd7b.\x8f\x16Ci_&\xe0\x7f', curve=SECP256K1)

    from cryptography.exceptions import InternalError
    with pytest.raises(InternalError):
        Point.from_bytes(point_on_koblitz256_but_not_P256.to_bytes(), curve=SECP256R1)
Ejemplo n.º 6
0
    def from_bytes(data: bytes, curve: ec.EllipticCurve = None):
        """
        Instantiates a CapsuleFrag object from the serialized data.
        """
        curve = curve if curve is not None else default_curve()
        key_size = get_curve_keysize_bytes(curve)
        data = BytesIO(data)

        # BigNums are the keysize in bytes, Points are compressed and the
        # keysize + 1 bytes long.
        e1 = Point.from_bytes(data.read(key_size + 1), curve)
        v1 = Point.from_bytes(data.read(key_size + 1), curve)
        kfrag_id = BigNum.from_bytes(data.read(key_size), curve)
        eph_ni = Point.from_bytes(data.read(key_size + 1), curve)

        return CapsuleFrag(e1, v1, kfrag_id, eph_ni)
Ejemplo n.º 7
0
    def from_bytes(cls, capsule_bytes: bytes, curve: ec.EllipticCurve = None):
        """
        Instantiates a Capsule object from the serialized data.
        """
        curve = curve if curve is not None else default_curve()
        key_size = get_curve_keysize_bytes(curve)
        capsule_buff = BytesIO(capsule_bytes)

        # CurveBNs are the keysize in bytes, Points are compressed and the
        # keysize + 1 bytes long.
        if len(capsule_bytes) == 197:
            e = Point.from_bytes(capsule_buff.read(key_size + 1), curve)
            v = Point.from_bytes(capsule_buff.read(key_size + 1), curve)
            sig = CurveBN.from_bytes(capsule_buff.read(key_size), curve)
            e_prime = Point.from_bytes(capsule_buff.read(key_size + 1), curve)
            v_prime = Point.from_bytes(capsule_buff.read(key_size + 1), curve)
            ni = Point.from_bytes(capsule_buff.read(key_size + 1), curve)
        else:
            e = Point.from_bytes(capsule_buff.read(key_size + 1), curve)
            v = Point.from_bytes(capsule_buff.read(key_size + 1), curve)
            sig = CurveBN.from_bytes(capsule_buff.read(key_size), curve)
            e_prime = v_prime = ni = None

        return cls(point_e=e, point_v=v, bn_sig=sig,
                   point_e_prime=e_prime, point_v_prime=v_prime, 
                   point_noninteractive=ni)
Ejemplo n.º 8
0
    def from_bytes(data: bytes, curve: ec.EllipticCurve = None):
        """
        Instantiate a KFrag object from the serialized data.
        """
        curve = curve if curve is not None else default_curve()
        key_size = get_curve_keysize_bytes(curve)
        data = BytesIO(data)

        # BigNums are the keysize in bytes, Points are compressed and the
        # keysize + 1 bytes long.
        id = BigNum.from_bytes(data.read(key_size), curve)
        key = BigNum.from_bytes(data.read(key_size), curve)
        eph_ni = Point.from_bytes(data.read(key_size + 1), curve)
        commitment = Point.from_bytes(data.read(key_size + 1), curve)
        sig1 = BigNum.from_bytes(data.read(key_size), curve)
        sig2 = BigNum.from_bytes(data.read(key_size), curve)

        return KFrag(id, key, eph_ni, commitment, sig1, sig2)
Ejemplo n.º 9
0
    def from_bytes(cls, data: bytes, curve: ec.EllipticCurve = None):
        """
        Instantiates a CapsuleFrag object from the serialized data.
        """
        curve = curve if curve is not None else default_curve()
        key_size = get_curve_keysize_bytes(curve)
        data = BytesIO(data)

        # CurveBNs are the keysize in bytes, Points are compressed and the
        # keysize + 1 bytes long.
        e1 = Point.from_bytes(data.read(key_size + 1), curve)
        v1 = Point.from_bytes(data.read(key_size + 1), curve)
        kfrag_id = CurveBN.from_bytes(data.read(key_size), curve)
        ni = Point.from_bytes(data.read(key_size + 1), curve)

        proof = data.read() or None
        proof = CorrectnessProof.from_bytes(proof, curve) if proof else None

        return cls(e1, v1, kfrag_id, ni, proof)
Ejemplo n.º 10
0
    def from_bytes(cls, data: bytes, curve: ec.EllipticCurve = None):
        """
        Instantiate ChallengeResponse from serialized data.
        """
        curve = curve if curve is not None else default_curve()
        key_size = get_curve_keysize_bytes(curve)
        data = BytesIO(data)

        # BigNums are the keysize in bytes, Points are compressed and the
        # keysize + 1 bytes long.
        e2 = Point.from_bytes(data.read(key_size + 1), curve)
        v2 = Point.from_bytes(data.read(key_size + 1), curve)
        kfrag_commitment = Point.from_bytes(data.read(key_size + 1), curve)
        kfrag_pok = Point.from_bytes(data.read(key_size + 1), curve)
        kfrag_sig1 = BigNum.from_bytes(data.read(key_size), curve)
        kfrag_sig2 = BigNum.from_bytes(data.read(key_size), curve)
        sig = BigNum.from_bytes(data.read(key_size), curve)

        return cls(e2, v2, kfrag_commitment, kfrag_pok, kfrag_sig1, kfrag_sig2,
                   sig)
Ejemplo n.º 11
0
    def from_bytes(cls, data: bytes, curve: ec.EllipticCurve = None):
        """
        Instantiate a KFrag object from the serialized data.
        """
        curve = curve if curve is not None else default_curve()
        bn_size = CurveBN.get_size(curve)
        point_size = Point.get_size(curve)
        data = BytesIO(data)

        # CurveBNs are the keysize in bytes, Points are compressed and the
        # keysize + 1 bytes long.
        id = data.read(bn_size)
        key = CurveBN.from_bytes(data.read(bn_size), curve)
        ni = Point.from_bytes(data.read(point_size), curve)
        commitment = Point.from_bytes(data.read(point_size), curve)
        xcoord = Point.from_bytes(data.read(point_size), curve)
        sig1 = CurveBN.from_bytes(data.read(bn_size), curve)
        sig2 = CurveBN.from_bytes(data.read(bn_size), curve)

        return cls(id, key, ni, commitment, xcoord, sig1, sig2)
Ejemplo n.º 12
0
def test_point_operations():

    vector_file = os.path.join('vectors', 'vectors_point_operations.json')
    try:
        with open(vector_file) as f:
            vector_suite = json.load(f)
    except OSError:
        raise

    point1 = Point.from_bytes(
        bytes.fromhex(vector_suite['first Point operand']))
    point2 = Point.from_bytes(
        bytes.fromhex(vector_suite['second Point operand']))
    bn1 = CurveBN.from_bytes(bytes.fromhex(vector_suite['CurveBN operand']))

    expected = dict()
    for op_result in vector_suite['vectors']:
        expected[op_result['operation']] = bytes.fromhex(op_result['result'])

    test = [
        ('Addition', point1 + point2),
        ('Subtraction', point1 - point2),
        ('Multiplication', bn1 * point1),
        ('Inversion', -point1),
    ]

    for (operation, result) in test:
        assert result == Point.from_bytes(
            expected[operation]), 'Error in {}'.format(operation)

    test = [
        ('To_affine.X', point1.to_affine()[0]),
        ('To_affine.Y', point1.to_affine()[1]),
    ]

    for (operation, result) in test:
        assert result == int.from_bytes(expected[operation],
                                        'big'), 'Error in {}'.format(operation)

    assert kdf(point1, pre.DEM_KEYSIZE) == expected['kdf']
Ejemplo n.º 13
0
def unsafe_hash_to_point(
    data: bytes = b'',
    params: UmbralParameters = None,
    label: bytes = b'',
    hash_class=Blake2b,
) -> 'Point':
    """
    Hashes arbitrary data into a valid EC point of the specified curve,
    using the try-and-increment method.
    It admits an optional label as an additional input to the hash function.
    It uses BLAKE2b (with a digest size of 64 bytes) as the internal hash function.

    WARNING: Do not use when the input data is secret, as this implementation is not
    in constant time, and hence, it is not safe with respect to timing attacks.
    """

    params = params if params is not None else default_params()

    len_data = len(data).to_bytes(4, byteorder='big')
    len_label = len(label).to_bytes(4, byteorder='big')

    label_data = len_label + label + len_data + data

    # We use an internal 32-bit counter as additional input
    i = 0
    while i < 2**32:
        ibytes = i.to_bytes(4, byteorder='big')
        hash_function = hash_class()
        hash_function.update(label_data + ibytes)
        hash_digest = hash_function.finalize()[:1 +
                                               params.CURVE_KEY_SIZE_BYTES]

        sign = b'\x02' if hash_digest[0] & 1 == 0 else b'\x03'
        compressed_point = sign + hash_digest[1:]

        try:
            return Point.from_bytes(compressed_point, params.curve)
        except InternalError as e:
            # We want to catch specific InternalExceptions:
            # - Point not in the curve (code 107)
            # - Invalid compressed point (code 110)
            # https://github.com/openssl/openssl/blob/master/include/openssl/ecerr.h#L228
            if e.err_code[0].reason in (107, 110):
                pass
            else:
                # Any other exception, we raise it
                raise e
        i += 1

    # Only happens with probability 2^(-32)
    raise ValueError('Could not hash input into the curve')
Ejemplo n.º 14
0
    def from_bytes(cls, key_data: bytes, params: UmbralParameters=None, as_b64=True):
        """
        Loads an Umbral public key from a urlsafe base64 encoded string or bytes.
        """
        if params is None:
            params = default_params()

        if as_b64:
            key_bytes = base64.urlsafe_b64decode(key_data)
        else:
            key_bytes = key_data

        point_key = Point.from_bytes(key_bytes, params.curve)
        return cls(point_key, params)
def test_invalid_points(random_ec_point2):

    point_bytes = bytearray(random_ec_point2.to_bytes(is_compressed=False))
    point_bytes[-1] = point_bytes[-1] ^ 0x01  # Flips last bit
    point_bytes = bytes(point_bytes)

    with pytest.raises(InternalError) as e:
        _point = Point.from_bytes(point_bytes)

    # We want to catch specific InternalExceptions:
    # - Point not in the curve (code 107)
    # - Invalid compressed point (code 110)
    # https://github.com/openssl/openssl/blob/master/include/openssl/ecerr.h#L228
    assert e.value.err_code[0].reason in (107, 110)
def test_point_curve_multiplication_regression():
    k256_point_bytes = b'\x03\xe0{\x1bQ\xbf@\x1f\x95\x8d\xe1\x17\xa7\xbe\x9e-G`T\xbf\xd7\x9e\xa7\x10\xc8uA\xc0z$\xc0\x92\x8a'
    k256_bn_bytes = b'4u\xd70-\xa0h\xdeG\xf0\x143\x06!\x91\x05{\xe4jC\n\xf1h\xed7a\xf8\x9d\xec^\x19\x8c'

    k256_point = Point.from_bytes(k256_point_bytes)
    k256_bn = CurveBN.from_bytes(k256_bn_bytes)

    product_with_star_operator = k256_point * k256_bn

    # Make sure we have instantiated a new, unequal point in the same curve and group
    assert isinstance(product_with_star_operator,
                      Point), "Point.__mul__ did not return a point instance"
    assert k256_point != product_with_star_operator
    assert k256_point.curve == product_with_star_operator.curve

    product_bytes = b'\x03\xc9\xda\xa2\x88\xe2\xa0+\xb1N\xb6\xe6\x1c\xa5(\xe6\xe0p\xf6\xf4\xa9\xfc\xb1\xfaUV\xd3\xb3\x0e4\x94\xbe\x12'
    product_point = Point.from_bytes(product_bytes)
    assert product_with_star_operator.to_bytes() == product_bytes
    assert product_point == product_with_star_operator

    # Repeating the operation, should return the same result.
    product_with_star_operator_again = k256_point * k256_bn
    assert product_with_star_operator == product_with_star_operator_again
Ejemplo n.º 17
0
    def from_bytes(cls, key_bytes: bytes, params: UmbralParameters=None,
                   decoder: Callable=None):
        """
        Loads an Umbral public key from bytes.
        Optionally, if an decoder function is provided it will be used to decode
        the data before returning it as an Umbral key.
        """
        if params is None:
            params = default_params()

        if decoder:
            key_bytes = decoder(key_bytes)

        point_key = Point.from_bytes(key_bytes, params.curve)
        return cls(point_key, params)
Ejemplo n.º 18
0
def test_unsafe_hash_to_point():

    vector_file = os.path.join('vectors', 'vectors_unsafe_hash_to_point.json')
    try:
        with open(vector_file) as f:
            vector_suite = json.load(f)
    except OSError:
        raise

    params = default_params()

    for item in vector_suite['vectors']:
        data = bytes.fromhex(item['data'])
        label = bytes.fromhex(item['label'])
        expected = Point.from_bytes(bytes.fromhex(item['point']))
        assert expected == unsafe_hash_to_point(label=label,
                                                data=data,
                                                params=params)
def test_coords_with_special_characteristics():

    # Testing that a point with x coordinate greater than the curve order is still valid.
    # In particular, we will test the last valid point from the default curve (secp256k1)
    # whose x coordinate is `field_order - 3` and is greater than the order of the curve

    field_order = 2**256 - 0x1000003D1
    compressed = b'\x02' + (field_order - 3).to_bytes(32, 'big')

    last_point = Point.from_bytes(compressed)

    # The same point, but obtained through the from_affine method
    coords = (
        115792089237316195423570985008687907853269984665640564039457584007908834671660,
        109188863561374057667848968960504138135859662956057034999983532397866404169138
    )

    assert last_point == Point.from_affine(coords)
Ejemplo n.º 20
0
def test_point_roundtrip(p, c):
    assert(p == Point.from_bytes(p.to_bytes(is_compressed=c)))