class OpenSSL::PKey::EC::Point

Attributes

group [R]

Public Class Methods

OpenSSL::PKey::EC::Point.new(point)
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

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
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);

    switch (EC_POINT_cmp(group, point1, point2, ossl_bn_ctx)) {
    case 0: return Qtrue;
    case 1: return Qfalse;
    default: ossl_raise(eEC_POINT, "EC_POINT_cmp");
    }

    UNREACHABLE;
}
Also aliased as: ==
infinity? → true | false
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(eEC_POINT, "EC_POINT_is_at_infinity");
    }

    UNREACHABLE;
}
initialize_copy (p1)
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
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(eEC_POINT, "EC_POINT_invert");

    return self;
}
make_affine! → self

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(eEC_POINT, "EC_POINT_make_affine");
#endif

    return self;
}
mul(bn1 [, bn2]) → point
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
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(eEC_POINT, "EC_POINT_is_on_curve");
    }

    UNREACHABLE;
}
set_to_infinity! → self
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(eEC_POINT, "EC_POINT_set_to_infinity");

    return self;
}
to_bn([conversion_form]) → OpenSSL::BN

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

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;
}