# class OpenSSL::PKey::EC::Point

### Attributes

group[R]

### Public Class Methods

OpenSSL::PKey::EC::Point.new(point) click to toggle source
OpenSSL::PKey::EC::Point.new(group [, encoded_point])

Creates a new instance of `OpenSSL::PKey::EC::Point`. If the only argument is an instance of `EC::Point`, a copy is returned. Otherwise, creates a point that belongs to group.

encoded_point is the octet string representation of the point. This must be either a `String` or an `OpenSSL::BN`.

    static VALUE ossl_ec_point_initialize(int argc, VALUE *argv, VALUE self)
    {
        EC_POINT *point;
        VALUE group_v, arg2;
        const EC_GROUP *group;

        TypedData_Get_Struct(self, EC_POINT, &ossl_ec_point_type, point);
        if (point)
            rb_raise(eEC_POINT, "EC_POINT already initialized");

        rb_scan_args(argc, argv, "11", &group_v, &arg2);
        if (rb_obj_is_kind_of(group_v, cEC_POINT)) {
            if (argc != 1)
                rb_raise(rb_eArgError, "invalid second argument");
            return ossl_ec_point_initialize_copy(self, group_v);
        }

        GetECGroup(group_v, group);
        if (argc == 1) {
            point = EC_POINT_new(group);
            if (!point)
                ossl_raise(eEC_POINT, "EC_POINT_new");
        }
        else {
            if (rb_obj_is_kind_of(arg2, cBN)) {
                point = EC_POINT_bn2point(group, GetBNPtr(arg2), NULL, ossl_bn_ctx);
                if (!point)
                    ossl_raise(eEC_POINT, "EC_POINT_bn2point");
            }
            else {
                StringValue(arg2);
                point = EC_POINT_new(group);
                if (!point)
                    ossl_raise(eEC_POINT, "EC_POINT_new");
                if (!EC_POINT_oct2point(group, point,
                                        (unsigned char *)RSTRING_PTR(arg2),
                                        RSTRING_LEN(arg2), ossl_bn_ctx)) {
                    EC_POINT_free(point);
                    ossl_raise(eEC_POINT, "EC_POINT_oct2point");
                }
            }
        }

        RTYPEDDATA_DATA(self) = point;
        rb_ivar_set(self, id_i_group, group_v);

        return self;
    }

### Public Instance Methods

point1 == point2 → true | false
Alias for: eql?
add(point) → point click to toggle source

Performs elliptic curve point addition.

    static VALUE ossl_ec_point_add(VALUE self, VALUE other)
    {
        EC_POINT *point_self, *point_other, *point_result;
        const EC_GROUP *group;
        VALUE group_v = rb_attr_get(self, id_i_group);
        VALUE result;

        GetECPoint(self, point_self);
        GetECPoint(other, point_other);
        GetECGroup(group_v, group);

        result = rb_obj_alloc(cEC_POINT);
        ossl_ec_point_initialize(1, &group_v, result);
        GetECPoint(result, point_result);

        if (EC_POINT_add(group, point_result, point_self, point_other, ossl_bn_ctx) != 1) {
            ossl_raise(eEC_POINT, "EC_POINT_add");
        }

        return result;
    }

eql?(point2) → true | false click to toggle source

    static VALUE ossl_ec_point_eql(VALUE a, VALUE b)
    {
        EC_POINT *point1, *point2;
        VALUE group_v1 = rb_attr_get(a, id_i_group);
        VALUE group_v2 = rb_attr_get(b, id_i_group);
        const EC_GROUP *group;

        if (ossl_ec_group_eql(group_v1, group_v2) == Qfalse)
            return Qfalse;

        GetECPoint(a, point1);
        GetECPoint(b, point2);
        GetECGroup(group_v1, group);

        if (EC_POINT_cmp(group, point1, point2, ossl_bn_ctx) == 1)
            return Qfalse;

        return Qtrue;
    }

Also aliased as: ==
infinity? → true | false click to toggle source

    static VALUE ossl_ec_point_is_at_infinity(VALUE self)
    {
        EC_POINT *point;
        const EC_GROUP *group;

        GetECPoint(self, point);
        GetECPointGroup(self, group);

        switch (EC_POINT_is_at_infinity(group, point)) {
        case 1: return Qtrue;
        case 0: return Qfalse;
        default: ossl_raise(cEC_POINT, "EC_POINT_is_at_infinity");
        }

        UNREACHABLE;
    }

initialize_copy(p1) click to toggle source

    static VALUE
    ossl_ec_point_initialize_copy(VALUE self, VALUE other)
    {
        EC_POINT *point, *point_new;
        EC_GROUP *group;
        VALUE group_v;

        TypedData_Get_Struct(self, EC_POINT, &ossl_ec_point_type, point_new);
        if (point_new)
            ossl_raise(eEC_POINT, "EC::Point already initialized");
        GetECPoint(other, point);

        group_v = rb_obj_dup(rb_attr_get(other, id_i_group));
        GetECGroup(group_v, group);

        point_new = EC_POINT_dup(point, group);
        if (!point_new)
            ossl_raise(eEC_POINT, "EC_POINT_dup");
        RTYPEDDATA_DATA(self) = point_new;
        rb_ivar_set(self, id_i_group, group_v);

        return self;
    }

invert! → self click to toggle source

    static VALUE ossl_ec_point_invert(VALUE self)
    {
        EC_POINT *point;
        const EC_GROUP *group;

        GetECPoint(self, point);
        GetECPointGroup(self, group);

        if (EC_POINT_invert(group, point, ossl_bn_ctx) != 1)
            ossl_raise(cEC_POINT, "EC_POINT_invert");

        return self;
    }

make_affine! → self click to toggle source

This method is deprecated and should not be used. This is a no-op.

    static VALUE ossl_ec_point_make_affine(VALUE self)
    {
        EC_POINT *point;
        const EC_GROUP *group;

        GetECPoint(self, point);
        GetECPointGroup(self, group);

        rb_warn("OpenSSL::PKey::EC::Point#make_affine! is deprecated");
    #if !OSSL_OPENSSL_PREREQ(3, 0, 0)
        if (EC_POINT_make_affine(group, point, ossl_bn_ctx) != 1)
            ossl_raise(cEC_POINT, "EC_POINT_make_affine");
    #endif

        return self;
    }

mul(bn1 [, bn2]) → point click to toggle source
mul(bns, points [, bn2]) → point

Performs elliptic curve point multiplication.

The first form calculates `bn1 * point + bn2 * G`, where `G` is the generator of the group of point. bn2 may be omitted, and in that case, the result is just `bn1 * point`.

The second form calculates `bns[0] * point + bns[1] * points[0] + ... + bns[-1] * points[-1] + bn2 * G`. bn2 may be omitted. bns must be an array of `OpenSSL::BN`. points must be an array of `OpenSSL::PKey::EC::Point`. Please note that `points[0]` is not multiplied by `bns[0]`, but `bns[1]`.

    static VALUE ossl_ec_point_mul(int argc, VALUE *argv, VALUE self)
    {
        EC_POINT *point_self, *point_result;
        const EC_GROUP *group;
        VALUE group_v = rb_attr_get(self, id_i_group);
        VALUE arg1, arg2, arg3, result;
        const BIGNUM *bn_g = NULL;

        GetECPoint(self, point_self);
        GetECGroup(group_v, group);

        result = rb_obj_alloc(cEC_POINT);
        ossl_ec_point_initialize(1, &group_v, result);
        GetECPoint(result, point_result);

        rb_scan_args(argc, argv, "12", &arg1, &arg2, &arg3);
        if (!RB_TYPE_P(arg1, T_ARRAY)) {
            BIGNUM *bn = GetBNPtr(arg1);

            if (!NIL_P(arg2))
                bn_g = GetBNPtr(arg2);
            if (EC_POINT_mul(group, point_result, bn_g, point_self, bn, ossl_bn_ctx) != 1)
                ossl_raise(eEC_POINT, NULL);
        } else {
    #if (defined(OPENSSL_VERSION_MAJOR) && OPENSSL_VERSION_MAJOR >= 3) || defined(LIBRESSL_VERSION_NUMBER)
            rb_raise(rb_eNotImpError, "calling #mul with arrays is not" \
                     "supported by this OpenSSL version");
    #else
            /*
             * bignums | arg1[0] | arg1[1] | arg1[2] | ...
             * points  | self    | arg2[0] | arg2[1] | ...
             */
            long i, num;
            VALUE bns_tmp, tmp_p, tmp_b;
            const EC_POINT **points;
            const BIGNUM **bignums;

            Check_Type(arg1, T_ARRAY);
            Check_Type(arg2, T_ARRAY);
            if (RARRAY_LEN(arg1) != RARRAY_LEN(arg2) + 1) /* arg2 must be 1 larger */
                ossl_raise(rb_eArgError, "bns must be 1 longer than points; see the documentation");

            rb_warning("OpenSSL::PKey::EC::Point#mul(ary, ary) is deprecated; " \
                       "use #mul(bn) form instead");

            num = RARRAY_LEN(arg1);
            bns_tmp = rb_ary_tmp_new(num);
            bignums = ALLOCV_N(const BIGNUM *, tmp_b, num);
            for (i = 0; i < num; i++) {
                VALUE item = RARRAY_AREF(arg1, i);
                bignums[i] = GetBNPtr(item);
                rb_ary_push(bns_tmp, item);
            }

            points = ALLOCV_N(const EC_POINT *, tmp_p, num);
            points[0] = point_self; /* self */
            for (i = 0; i < num - 1; i++)
                GetECPoint(RARRAY_AREF(arg2, i), points[i + 1]);

            if (!NIL_P(arg3))
                bn_g = GetBNPtr(arg3);

            if (EC_POINTs_mul(group, point_result, bn_g, num, points, bignums, ossl_bn_ctx) != 1) {
                ALLOCV_END(tmp_b);
                ALLOCV_END(tmp_p);
                ossl_raise(eEC_POINT, NULL);
            }

            ALLOCV_END(tmp_b);
            ALLOCV_END(tmp_p);
    #endif
        }

        return result;
    }

on_curve? → true | false click to toggle source

    static VALUE ossl_ec_point_is_on_curve(VALUE self)
    {
        EC_POINT *point;
        const EC_GROUP *group;

        GetECPoint(self, point);
        GetECPointGroup(self, group);

        switch (EC_POINT_is_on_curve(group, point, ossl_bn_ctx)) {
        case 1: return Qtrue;
        case 0: return Qfalse;
        default: ossl_raise(cEC_POINT, "EC_POINT_is_on_curve");
        }

        UNREACHABLE;
    }

set_to_infinity! → self click to toggle source

    static VALUE ossl_ec_point_set_to_infinity(VALUE self)
    {
        EC_POINT *point;
        const EC_GROUP *group;

        GetECPoint(self, point);
        GetECPointGroup(self, group);

        if (EC_POINT_set_to_infinity(group, point) != 1)
            ossl_raise(cEC_POINT, "EC_POINT_set_to_infinity");

        return self;
    }

to_bn([conversion_form]) → OpenSSL::BN click to toggle source

Returns the octet string representation of the `EC` point as an instance of `OpenSSL::BN`.

If conversion_form is not given, the point_conversion_form attribute set to the group is used.

See `to_octet_string` for more information.

    # File ext/openssl/lib/openssl/pkey.rb, line 307
    def to_bn(conversion_form = group.point_conversion_form)
      OpenSSL::BN.new(to_octet_string(conversion_form), 2)
    end

to_octet_string(conversion_form) → String click to toggle source

Returns the octet string representation of the elliptic curve point.

conversion_form specifies how the point is converted. Possible values are:

- `:compressed`

- `:uncompressed`

- `:hybrid`

    static VALUE
    ossl_ec_point_to_octet_string(VALUE self, VALUE conversion_form)
    {
        EC_POINT *point;
        const EC_GROUP *group;
        point_conversion_form_t form;
        VALUE str;
        size_t len;

        GetECPoint(self, point);
        GetECPointGroup(self, group);
        form = parse_point_conversion_form_symbol(conversion_form);

        len = EC_POINT_point2oct(group, point, form, NULL, 0, ossl_bn_ctx);
        if (!len)
            ossl_raise(eEC_POINT, "EC_POINT_point2oct");
        str = rb_str_new(NULL, (long)len);
        if (!EC_POINT_point2oct(group, point, form,
                                (unsigned char *)RSTRING_PTR(str), len,
                                ossl_bn_ctx))
            ossl_raise(eEC_POINT, "EC_POINT_point2oct");
        return str;
    }