Class: OpenSSL::PKey::EC::Group

Inherits:
Object
  • Object
show all
Defined in:
ext/openssl/ossl_pkey_ec.c

Defined Under Namespace

Classes: Error

Instance Method Summary collapse

Constructor Details

#OpenSSL::PKey::EC::Group.new(ec_group) ⇒ Object #OpenSSL::PKey::EC::Group.new(pem_or_der_encoded) ⇒ Object #OpenSSL::PKey::EC::Group.new(ec_method) ⇒ Object #OpenSSL::PKey::EC::Group.new(: GFp, bignum_p, bignum_a, bignum_b) ⇒ Object #OpenSSL::PKey::EC::Group.new(: GF2m, bignum_p, bignum_a, bignum_b) ⇒ Object

Creates a new EC::Group object.

ec_method is a symbol that represents an EC_METHOD. Currently the following are supported:

  • :GFp_simple

  • :GFp_mont

  • :GFp_nist

  • :GF2m_simple

If the first argument is :GFp or :GF2m, creates a new curve with given parameters.



726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
# File 'ext/openssl/ossl_pkey_ec.c', line 726

static VALUE ossl_ec_group_initialize(int argc, VALUE *argv, VALUE self)
{
    VALUE arg1, arg2, arg3, arg4;
    EC_GROUP *group;

    TypedData_Get_Struct(self, EC_GROUP, &ossl_ec_group_type, group);
    if (group)
        ossl_raise(rb_eRuntimeError, "EC_GROUP is already initialized");

    switch (rb_scan_args(argc, argv, "13", &arg1, &arg2, &arg3, &arg4)) {
    case 1:
        if (SYMBOL_P(arg1)) {
            const EC_METHOD *method = NULL;
            ID id = SYM2ID(arg1);

            if (id == s_GFp_simple) {
                method = EC_GFp_simple_method();
            } else if (id == s_GFp_mont) {
                method = EC_GFp_mont_method();
            } else if (id == s_GFp_nist) {
                method = EC_GFp_nist_method();
#if !defined(OPENSSL_NO_EC2M)
            } else if (id == s_GF2m_simple) {
                method = EC_GF2m_simple_method();
#endif
            }

            if (method) {
                if ((group = EC_GROUP_new(method)) == NULL)
                    ossl_raise(eEC_GROUP, "EC_GROUP_new");
            } else {
                ossl_raise(rb_eArgError, "unknown symbol, must be :GFp_simple, :GFp_mont, :GFp_nist or :GF2m_simple");
            }
        } else if (rb_obj_is_kind_of(arg1, cEC_GROUP)) {
            const EC_GROUP *arg1_group;

            GetECGroup(arg1, arg1_group);
            if ((group = EC_GROUP_dup(arg1_group)) == NULL)
                ossl_raise(eEC_GROUP, "EC_GROUP_dup");
        } else {
            BIO *in = ossl_obj2bio(&arg1);

            group = PEM_read_bio_ECPKParameters(in, NULL, NULL, NULL);
            if (!group) {
		OSSL_BIO_reset(in);
                group = d2i_ECPKParameters_bio(in, NULL);
            }

            BIO_free(in);

            if (!group) {
                const char *name = StringValueCStr(arg1);
                int nid = OBJ_sn2nid(name);

		ossl_clear_error(); /* ignore errors in d2i_ECPKParameters_bio() */
                if (nid == NID_undef)
                    ossl_raise(eEC_GROUP, "unknown curve name (%"PRIsVALUE")", arg1);

                group = EC_GROUP_new_by_curve_name(nid);
                if (group == NULL)
                    ossl_raise(eEC_GROUP, "unable to create curve (%"PRIsVALUE")", arg1);

                EC_GROUP_set_asn1_flag(group, OPENSSL_EC_NAMED_CURVE);
                EC_GROUP_set_point_conversion_form(group, POINT_CONVERSION_UNCOMPRESSED);
            }
        }

        break;
    case 4:
        if (SYMBOL_P(arg1)) {
            ID id = SYM2ID(arg1);
            EC_GROUP *(*new_curve)(const BIGNUM *, const BIGNUM *, const BIGNUM *, BN_CTX *) = NULL;
            const BIGNUM *p = GetBNPtr(arg2);
            const BIGNUM *a = GetBNPtr(arg3);
            const BIGNUM *b = GetBNPtr(arg4);

            if (id == s_GFp) {
                new_curve = EC_GROUP_new_curve_GFp;
#if !defined(OPENSSL_NO_EC2M)
            } else if (id == s_GF2m) {
                new_curve = EC_GROUP_new_curve_GF2m;
#endif
            } else {
                ossl_raise(rb_eArgError, "unknown symbol, must be :GFp or :GF2m");
            }

            if ((group = new_curve(p, a, b, ossl_bn_ctx)) == NULL)
                ossl_raise(eEC_GROUP, "EC_GROUP_new_by_GF*");
        } else {
             ossl_raise(rb_eArgError, "unknown argument, must be :GFp or :GF2m");
        }

        break;
    default:
        ossl_raise(rb_eArgError, "wrong number of arguments");
    }

    if (group == NULL)
        ossl_raise(eEC_GROUP, "");
    RTYPEDDATA_DATA(self) = group;

    return self;
}

Instance Method Details

#asn1_flagInteger

Returns the flags set on the group.

See also #asn1_flag=.

Returns:



1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
# File 'ext/openssl/ossl_pkey_ec.c', line 1035

static VALUE ossl_ec_group_get_asn1_flag(VALUE self)
{
    EC_GROUP *group = NULL;
    int flag;

    GetECGroup(self, group);
    flag = EC_GROUP_get_asn1_flag(group);

    return INT2NUM(flag);
}

#asn1_flag=(flags) ⇒ Object

Sets flags on the group. The flag value is used to determine how to encode the group: encode explicit parameters or named curve using an OID.

The flag value can be either of:

  • EC::NAMED_CURVE

  • EC::EXPLICIT_CURVE

See the OpenSSL documentation for EC_GROUP_set_asn1_flag().



1060
1061
1062
1063
1064
1065
1066
1067
1068
# File 'ext/openssl/ossl_pkey_ec.c', line 1060

static VALUE ossl_ec_group_set_asn1_flag(VALUE self, VALUE flag_v)
{
    EC_GROUP *group = NULL;

    GetECGroup(self, group);
    EC_GROUP_set_asn1_flag(group, NUM2INT(flag_v));

    return flag_v;
}

#get_cofactorObject

Returns the cofactor of the group.

See the OpenSSL documentation for EC_GROUP_get_cofactor()



950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
# File 'ext/openssl/ossl_pkey_ec.c', line 950

static VALUE ossl_ec_group_get_cofactor(VALUE self)
{
    VALUE bn_obj;
    BIGNUM *bn;
    EC_GROUP *group = NULL;

    GetECGroup(self, group);

    bn_obj = ossl_bn_new(NULL);
    bn = GetBNPtr(bn_obj);

    if (EC_GROUP_get_cofactor(group, bn, ossl_bn_ctx) != 1)
        ossl_raise(eEC_GROUP, "EC_GROUP_get_cofactor");

    return bn_obj;
}

#curve_nameString

Returns the curve name (sn).

See the OpenSSL documentation for EC_GROUP_get_curve_name()

Returns:

  • (String)


975
976
977
978
979
980
981
982
983
984
985
986
987
988
# File 'ext/openssl/ossl_pkey_ec.c', line 975

static VALUE ossl_ec_group_get_curve_name(VALUE self)
{
    EC_GROUP *group = NULL;
    int nid;

    GetECGroup(self, group);
    if (group == NULL)
        return Qnil;

    nid = EC_GROUP_get_curve_name(group);

/* BUG: an nid or asn1 object should be returned, maybe. */
    return rb_str_new2(OBJ_nid2sn(nid));
}

#degreeInteger

See the OpenSSL documentation for EC_GROUP_get_degree()

Returns:



1193
1194
1195
1196
1197
1198
1199
1200
# File 'ext/openssl/ossl_pkey_ec.c', line 1193

static VALUE ossl_ec_group_get_degree(VALUE self)
{
    EC_GROUP *group = NULL;

    GetECGroup(self, group);

    return INT2NUM(EC_GROUP_get_degree(group));
}

#eql?(group2) ⇒ Boolean #==(group2) ⇒ Boolean Also known as: ==

Returns true if the two groups use the same curve and have the same parameters, false otherwise.

Returns:

  • (Boolean)


856
857
858
859
860
861
862
863
864
865
866
867
868
# File 'ext/openssl/ossl_pkey_ec.c', line 856

static VALUE ossl_ec_group_eql(VALUE a, VALUE b)
{
    EC_GROUP *group1 = NULL, *group2 = NULL;

    GetECGroup(a, group1);
    GetECGroup(b, group2);

    switch (EC_GROUP_cmp(group1, group2, ossl_bn_ctx)) {
    case 0: return Qtrue;
    case 1: return Qfalse;
    default: ossl_raise(eEC_GROUP, "EC_GROUP_cmp");
    }
}

#generatorObject

Returns the generator of the group.

See the OpenSSL documentation for EC_GROUP_get0_generator()



878
879
880
881
882
883
884
885
886
887
888
889
# File 'ext/openssl/ossl_pkey_ec.c', line 878

static VALUE ossl_ec_group_get_generator(VALUE self)
{
    EC_GROUP *group;
    const EC_POINT *generator;

    GetECGroup(self, group);
    generator = EC_GROUP_get0_generator(group);
    if (!generator)
	return Qnil;

    return ec_point_new(generator, group);
}

#initialize_copy(other) ⇒ Object



830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
# File 'ext/openssl/ossl_pkey_ec.c', line 830

static VALUE
ossl_ec_group_initialize_copy(VALUE self, VALUE other)
{
    EC_GROUP *group, *group_new;

    TypedData_Get_Struct(self, EC_GROUP, &ossl_ec_group_type, group_new);
    if (group_new)
	ossl_raise(eEC_GROUP, "EC::Group already initialized");
    GetECGroup(other, group);

    group_new = EC_GROUP_dup(group);
    if (!group_new)
	ossl_raise(eEC_GROUP, "EC_GROUP_dup");
    RTYPEDDATA_DATA(self) = group_new;

    return self;
}

#get_orderObject

Returns the order of the group.

See the OpenSSL documentation for EC_GROUP_get_order()



925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
# File 'ext/openssl/ossl_pkey_ec.c', line 925

static VALUE ossl_ec_group_get_order(VALUE self)
{
    VALUE bn_obj;
    BIGNUM *bn;
    EC_GROUP *group = NULL;

    GetECGroup(self, group);

    bn_obj = ossl_bn_new(NULL);
    bn = GetBNPtr(bn_obj);

    if (EC_GROUP_get_order(group, bn, ossl_bn_ctx) != 1)
        ossl_raise(eEC_GROUP, "EC_GROUP_get_order");

    return bn_obj;
}

#point_conversion_formSymbol

Returns the form how EC::Point data is encoded as ASN.1.

See also #point_conversion_form=.

Returns:

  • (Symbol)


1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
# File 'ext/openssl/ossl_pkey_ec.c', line 1078

static VALUE ossl_ec_group_get_point_conversion_form(VALUE self)
{
    EC_GROUP *group = NULL;
    point_conversion_form_t form;
    VALUE ret;

    GetECGroup(self, group);
    form = EC_GROUP_get_point_conversion_form(group);

    switch (form) {
    case POINT_CONVERSION_UNCOMPRESSED:	ret = ID_uncompressed; break;
    case POINT_CONVERSION_COMPRESSED:	ret = ID_compressed; break;
    case POINT_CONVERSION_HYBRID:	ret = ID_hybrid; break;
    default:	ossl_raise(eEC_GROUP, "unsupported point conversion form: %d, this module should be updated", form);
    }

   return ID2SYM(ret);
}

#point_conversion_form=(form) ⇒ Object

Sets the form how EC::Point data is encoded as ASN.1 as defined in X9.62.

format can be one of these:

:compressed

Encoded as z||x, where z is an octet indicating which solution of the equation y is. z will be 0x02 or 0x03.

:uncompressed

Encoded as z||x||y, where z is an octet 0x04.

:hybrid

Encodes as z||x||y, where z is an octet indicating which solution of the equation y is. z will be 0x06 or 0x07.

See the OpenSSL documentation for EC_GROUP_set_point_conversion_form()



1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
# File 'ext/openssl/ossl_pkey_ec.c', line 1132

static VALUE
ossl_ec_group_set_point_conversion_form(VALUE self, VALUE form_v)
{
    EC_GROUP *group;
    point_conversion_form_t form;

    GetECGroup(self, group);
    form = parse_point_conversion_form_symbol(form_v);

    EC_GROUP_set_point_conversion_form(group, form);

    return form_v;
}

#seedString?

See the OpenSSL documentation for EC_GROUP_get0_seed()

Returns:

  • (String, nil)


1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
# File 'ext/openssl/ossl_pkey_ec.c', line 1152

static VALUE ossl_ec_group_get_seed(VALUE self)
{
    EC_GROUP *group = NULL;
    size_t seed_len;

    GetECGroup(self, group);
    seed_len = EC_GROUP_get_seed_len(group);

    if (seed_len == 0)
        return Qnil;

    return rb_str_new((const char *)EC_GROUP_get0_seed(group), seed_len);
}

#seed=(seed) ⇒ Object

See the OpenSSL documentation for EC_GROUP_set_seed()



1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
# File 'ext/openssl/ossl_pkey_ec.c', line 1172

static VALUE ossl_ec_group_set_seed(VALUE self, VALUE seed)
{
    EC_GROUP *group = NULL;

    GetECGroup(self, group);
    StringValue(seed);

    if (EC_GROUP_set_seed(group, (unsigned char *)RSTRING_PTR(seed), RSTRING_LEN(seed)) != (size_t)RSTRING_LEN(seed))
        ossl_raise(eEC_GROUP, "EC_GROUP_set_seed");

    return seed;
}

#set_generator(generator, order, cofactor) ⇒ self

Sets the curve parameters. generator must be an instance of EC::Point that is on the curve. order and cofactor are integers.

See the OpenSSL documentation for EC_GROUP_set_generator()

Returns:

  • (self)


900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
# File 'ext/openssl/ossl_pkey_ec.c', line 900

static VALUE ossl_ec_group_set_generator(VALUE self, VALUE generator, VALUE order, VALUE cofactor)
{
    EC_GROUP *group = NULL;
    const EC_POINT *point;
    const BIGNUM *o, *co;

    GetECGroup(self, group);
    GetECPoint(generator, point);
    o = GetBNPtr(order);
    co = GetBNPtr(cofactor);

    if (EC_GROUP_set_generator(group, point, o, co) != 1)
        ossl_raise(eEC_GROUP, "EC_GROUP_set_generator");

    return self;
}

#to_derString

See the OpenSSL documentation for i2d_ECPKParameters_bio()

Returns:

  • (String)


1253
1254
1255
1256
# File 'ext/openssl/ossl_pkey_ec.c', line 1253

static VALUE ossl_ec_group_to_der(VALUE self)
{
    return ossl_ec_group_to_string(self, EXPORT_DER);
}

#to_pemString

See the OpenSSL documentation for PEM_write_bio_ECPKParameters()

Returns:

  • (String)


1242
1243
1244
1245
# File 'ext/openssl/ossl_pkey_ec.c', line 1242

static VALUE ossl_ec_group_to_pem(VALUE self)
{
    return ossl_ec_group_to_string(self, EXPORT_PEM);
}

#to_textString

See the OpenSSL documentation for ECPKParameters_print()

Returns:

  • (String)


1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
# File 'ext/openssl/ossl_pkey_ec.c', line 1264

static VALUE ossl_ec_group_to_text(VALUE self)
{
    EC_GROUP *group;
    BIO *out;
    VALUE str;

    GetECGroup(self, group);
    if (!(out = BIO_new(BIO_s_mem()))) {
	ossl_raise(eEC_GROUP, "BIO_new(BIO_s_mem())");
    }
    if (!ECPKParameters_print(out, group, 0)) {
	BIO_free(out);
	ossl_raise(eEC_GROUP, NULL);
    }
    str = ossl_membio2str(out);

    return str;
}