def from_bytes(cls, data, curve: ec.EllipticCurve = None): """ Returns a Point object from the given byte data on the curve provided. """ curve = curve if curve is not None else default_curve() try: curve_nid = backend._elliptic_curve_to_nid(curve) except AttributeError: # Presume that the user passed in the curve_nid curve_nid = curve compressed_size = cls.expected_bytes_length(curve) # Check if compressed if data[0] in [2, 3]: if len(data) != compressed_size: raise ValueError("X coordinate too large for curve.") affine_x = CurveBN.from_bytes(data[1:], curve) type_y = data[0] - 2 ec_point = openssl._get_new_EC_POINT(ec_group=affine_x.group) with backend._tmp_bn_ctx() as bn_ctx: res = backend._lib.EC_POINT_set_compressed_coordinates_GFp( affine_x.group, ec_point, affine_x.bignum, type_y, bn_ctx) backend.openssl_assert(res == 1) return cls(ec_point, curve_nid, affine_x.group) # Handle uncompressed point elif data[0] == 4: coord_size = compressed_size - 1 uncompressed_size = 1 + 2 * coord_size if len(data) != uncompressed_size: raise ValueError( "uncompressed point does not have right size.") affine_x = int.from_bytes(data[1:coord_size + 1], 'big') affine_y = int.from_bytes(data[1 + coord_size:], 'big') return cls.from_affine((affine_x, affine_y), curve) else: raise ValueError("Invalid point serialization.")
def from_bytes(cls, key_bytes: bytes, params: UmbralParameters = None, password: bytes = None, _scrypt_cost: int = 20, decoder: Callable = None): """ Loads an Umbral private key from bytes. Optionally, allows a decoder function to be passed as a param to decode the data provided before converting to an Umbral key. Optionally, if a password is provided it will decrypt the key using nacl's Salsa20-Poly1305 and Scrypt key derivation. WARNING: RFC7914 recommends that you use a 2^20 cost value for sensitive files. Unless you changed this when you called `to_bytes`, you should not change it here. It is NOT recommended to change the `_scrypt_cost` value unless you know what you're doing. """ if params is None: params = default_params() if decoder: key_bytes = decoder(key_bytes) if password: salt = key_bytes[-16:] key_bytes = key_bytes[:-16] key = Scrypt(salt=salt, length=SecretBox.KEY_SIZE, n=2**_scrypt_cost, r=8, p=1, backend=default_backend()).derive(password) key_bytes = SecretBox(key).decrypt(key_bytes) bn_key = CurveBN.from_bytes(key_bytes, params.curve) return cls(bn_key, params)
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)
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
def from_bytes(cls, data: bytes, curve: Optional[Curve] = None) -> 'Point': """ Returns a Point object from the given byte data on the curve provided. """ curve = curve if curve is not None else default_curve() compressed_size = cls.expected_bytes_length(curve) # Check if compressed if data[0] in [2, 3]: if len(data) != compressed_size: raise ValueError("X coordinate too large for curve.") affine_x = CurveBN.from_bytes(data[1:], curve) type_y = data[0] - 2 ec_point = openssl._get_new_EC_POINT(curve) with backend._tmp_bn_ctx() as bn_ctx: res = backend._lib.EC_POINT_set_compressed_coordinates_GFp( curve.ec_group, ec_point, affine_x.bignum, type_y, bn_ctx) backend.openssl_assert(res == 1) return cls(ec_point, curve) # Handle uncompressed point # TODO: Give better error messages elif data[0] == 4: coord_size = compressed_size - 1 uncompressed_size = 1 + (2 * coord_size) if len(data) != uncompressed_size: raise ValueError( "Uncompressed point does not have right size.") affine_x = int.from_bytes(data[1:coord_size + 1], 'big') affine_y = int.from_bytes(data[1 + coord_size:], 'big') return cls.from_affine((affine_x, affine_y), curve) else: raise ValueError("Invalid point serialization.")
def test_bn_roundtrip(bn): assert(bn == CurveBN.from_bytes(bn.to_bytes()))