def __add__(self, b): assert self.curve == b.curve a_pt = ossl.point_new_from_ints(self.curve.os_group, self.x, self.y, self.infinity) b_pt = ossl.point_new_from_ints(b.curve.os_group, b.x, b.y, b.infinity) ossl.lc.EC_POINT_add(self.curve.os_group, a_pt, a_pt, b_pt, None) x, y, inf = ossl.point_get_xy_ints(self.curve.os_group, a_pt) ossl.lc.EC_POINT_free(a_pt) ossl.lc.EC_POINT_free(b_pt) return ECPointAffine(self.curve, x, y, inf)
def is_on_curve(self, p): """ Checks whether a point is on the curve. Args: p (ECPointAffine): Point to be checked Returns: bool: True if p is on the curve, False otherwise. """ ec_pt = ossl.point_new_from_ints(self.os_group, p.x, p.y) on_curve = ossl.lc.EC_POINT_is_on_curve(self.os_group, ec_pt, None) ossl.lc.EC_POINT_free(ec_pt) return bool(on_curve)
def recover_public_key(self, message, signature, recovery_id=None): """ Recovers possibilities for the public key associated with the private key used to sign message and generate signature. Since there are multiple possibilities (two for curves with co-factor = 1), each possibility that successfully verifies the signature is returned. Args: message (bytes): The message that was signed. signature (ECPointAffine): The point representing the signature. recovery_id (int) (Optional): If provided, limits the valid x and y point to only that described by the recovery_id. Returns: list(ECPointAffine): List of points representing valid public keys that verify signature. """ r = signature.x s = signature.y ctx = c_void_p(ossl.lc.BN_CTX_new()) ossl.lc.BN_CTX_start(ctx) order_bn = c_void_p(ossl.lc.BN_CTX_get(ctx)) x_bn = c_void_p(ossl.lc.BN_CTX_get(ctx)) i_bn = c_void_p(ossl.lc.BN_CTX_get(ctx)) in_bn = c_void_p(ossl.lc.BN_CTX_get(ctx)) p_bn = c_void_p(ossl.lc.BN_CTX_get(ctx)) r_bn = c_void_p(ossl.lc.BN_CTX_get(ctx)) s_bn = c_void_p(ossl.lc.BN_CTX_get(ctx)) rinv_bn = c_void_p(ossl.lc.BN_CTX_get(ctx)) z_bn = c_void_p(ossl.lc.BN_CTX_get(ctx)) ossl.lc.EC_GROUP_get_order(self.os_group, order_bn, ctx) ossl.int_to_bn(self.p, p_bn) ossl.int_to_bn(r, r_bn) ossl.int_to_bn(s, s_bn) ossl.lc.BN_mod_inverse(rinv_bn, r_bn, order_bn, ctx) if recovery_id is not None: i_list = [recovery_id >> 1] k_list = [recovery_id & 0x1] else: i_list = range(2) k_list = range(2) rv = [] num_bytes = math.ceil(self.nlen / 8) z = int.from_bytes(self.hash_function(message).digest()[:num_bytes], 'big') ossl.int_to_bn(z, z_bn) zG = c_void_p(ossl.lc.EC_POINT_new(self.os_group)) sR = c_void_p(ossl.lc.EC_POINT_new(self.os_group)) temp = c_void_p(ossl.lc.EC_POINT_new(self.os_group)) pub_key = c_void_p(ossl.lc.EC_POINT_new(self.os_group)) Rn = c_void_p(ossl.lc.EC_POINT_new(self.os_group)) for i in i_list: ossl.int_to_bn(i, i_bn) ossl.lc.BN_mod_mul(in_bn, i_bn, order_bn, p_bn, ctx) ossl.lc.BN_mod_add(x_bn, r_bn, in_bn, p_bn, ctx) x = ossl.bn_to_int(x_bn) ys = self.y_from_x(x) for k in k_list: y = ys[k] if y & 0x1 != k: y = ys[k ^ 1] R = ossl.point_new_from_ints(self.os_group, r, y) ossl.lc.EC_POINT_mul(self.os_group, Rn, None, R, order_bn, ctx) if not ossl.lc.EC_POINT_is_at_infinity(self.os_group, Rn): continue ossl.lc.EC_POINT_mul(self.os_group, zG, z_bn, None, None, ctx) ossl.lc.EC_POINT_invert(self.os_group, zG, ctx) ossl.lc.EC_POINT_mul(self.os_group, sR, None, R, s_bn, ctx) ossl.lc.EC_POINT_add(self.os_group, temp, sR, zG, ctx) ossl.lc.EC_POINT_mul(self.os_group, pub_key, None, temp, rinv_bn, ctx) ossl.lc.EC_POINT_free(R) # Convert to ECPointAffine pub_x, pub_y, inf = ossl.point_get_xy_ints(self.os_group, pub_key) rv.append((ECPointAffine(self, pub_x, pub_y, inf), 2 * i + k)) ossl.lc.EC_POINT_free(zG) ossl.lc.EC_POINT_free(sR) ossl.lc.EC_POINT_free(temp) ossl.lc.EC_POINT_free(pub_key) ossl.lc.EC_POINT_free(Rn) ossl.lc.BN_CTX_end(ctx) ossl.lc.BN_CTX_free(ctx) return rv
def recover_public_key(self, message, signature, recovery_id=None): """ Recovers possibilities for the public key associated with the private key used to sign message and generate signature. Since there are multiple possibilities (two for curves with co-factor = 1), each possibility that successfully verifies the signature is returned. Args: message (bytes): The message that was signed. signature (ECPointAffine): The point representing the signature. recovery_id (int) (Optional): If provided, limits the valid x and y point to only that described by the recovery_id. Returns: list(ECPointAffine): List of points representing valid public keys that verify signature. """ r = signature.x s = signature.y ctx = c_void_p(ossl.lc.BN_CTX_new()) ossl.lc.BN_CTX_start(ctx) order_bn = c_void_p(ossl.lc.BN_CTX_get(ctx)) x_bn = c_void_p(ossl.lc.BN_CTX_get(ctx)) i_bn = c_void_p(ossl.lc.BN_CTX_get(ctx)) in_bn = c_void_p(ossl.lc.BN_CTX_get(ctx)) p_bn = c_void_p(ossl.lc.BN_CTX_get(ctx)) r_bn = c_void_p(ossl.lc.BN_CTX_get(ctx)) s_bn = c_void_p(ossl.lc.BN_CTX_get(ctx)) rinv_bn = c_void_p(ossl.lc.BN_CTX_get(ctx)) z_bn = c_void_p(ossl.lc.BN_CTX_get(ctx)) ossl.lc.EC_GROUP_get_order(self.os_group, order_bn, ctx) ossl.int_to_bn(self.p, p_bn) ossl.int_to_bn(r, r_bn) ossl.int_to_bn(s, s_bn) ossl.lc.BN_mod_inverse(rinv_bn, r_bn, order_bn, ctx) if recovery_id is not None: i_list = [recovery_id >> 1] k_list = [recovery_id & 0x1] else: i_list = range(2) k_list = range(2) rv = [] num_bytes = math.ceil(self.nlen / 8) z = int.from_bytes( self.hash_function(message).digest()[:num_bytes], 'big') ossl.int_to_bn(z, z_bn) zG = c_void_p(ossl.lc.EC_POINT_new(self.os_group)) sR = c_void_p(ossl.lc.EC_POINT_new(self.os_group)) temp = c_void_p(ossl.lc.EC_POINT_new(self.os_group)) pub_key = c_void_p(ossl.lc.EC_POINT_new(self.os_group)) Rn = c_void_p(ossl.lc.EC_POINT_new(self.os_group)) for i in i_list: ossl.int_to_bn(i, i_bn) ossl.lc.BN_mod_mul(in_bn, i_bn, order_bn, p_bn, ctx) ossl.lc.BN_mod_add(x_bn, r_bn, in_bn, p_bn, ctx) x = ossl.bn_to_int(x_bn) ys = self.y_from_x(x) for k in k_list: y = ys[k] if y & 0x1 != k: y = ys[k ^ 1] R = ossl.point_new_from_ints(self.os_group, r, y) ossl.lc.EC_POINT_mul(self.os_group, Rn, None, R, order_bn, ctx) if not ossl.lc.EC_POINT_is_at_infinity(self.os_group, Rn): continue ossl.lc.EC_POINT_mul(self.os_group, zG, z_bn, None, None, ctx) ossl.lc.EC_POINT_invert(self.os_group, zG, ctx) ossl.lc.EC_POINT_mul(self.os_group, sR, None, R, s_bn, ctx) ossl.lc.EC_POINT_add(self.os_group, temp, sR, zG, ctx) ossl.lc.EC_POINT_mul(self.os_group, pub_key, None, temp, rinv_bn, ctx) ossl.lc.EC_POINT_free(R) # Convert to ECPointAffine pub_x, pub_y, inf = ossl.point_get_xy_ints( self.os_group, pub_key) rv.append((ECPointAffine(self, pub_x, pub_y, inf), 2 * i + k)) ossl.lc.EC_POINT_free(zG) ossl.lc.EC_POINT_free(sR) ossl.lc.EC_POINT_free(temp) ossl.lc.EC_POINT_free(pub_key) ossl.lc.EC_POINT_free(Rn) ossl.lc.BN_CTX_end(ctx) ossl.lc.BN_CTX_free(ctx) return rv