class OpenSSL::PKey::EC

Constants

NAMED_CURVE

Public Class Methods

builtin_curves → [[name, comment], ...] click to toggle source

See the OpenSSL documentation for EC_builtin_curves()

static VALUE ossl_s_builtin_curves(VALUE self)
{
    EC_builtin_curve *curves = NULL;
    int n;
    int crv_len = rb_long2int(EC_get_builtin_curves(NULL, 0));
    VALUE ary, ret;

    curves = ALLOCA_N(EC_builtin_curve, crv_len);
    if (curves == NULL)
        return Qnil;
    if (!EC_get_builtin_curves(curves, crv_len))
        ossl_raise(rb_eRuntimeError, "EC_get_builtin_curves");

    ret = rb_ary_new2(crv_len);

    for (n = 0; n < crv_len; n++) {
        const char *sname = OBJ_nid2sn(curves[n].nid);
        const char *comment = curves[n].comment;

        ary = rb_ary_new2(2);
        rb_ary_push(ary, rb_str_new2(sname));
        rb_ary_push(ary, comment ? rb_str_new2(comment) : Qnil);
        rb_ary_push(ret, ary);
    }

    return ret;
}
OpenSSL::PKey::EC.new() click to toggle source
OpenSSL::PKey::EC.new(ec_key)
OpenSSL::PKey::EC.new(ec_group)
OpenSSL::PKey::EC.new("secp112r1")
OpenSSL::PKey::EC.new(pem_string)
OpenSSL::PKey::EC.new(pem_string [, pwd])
OpenSSL::PKey::EC.new(der_string)

See the OpenSSL documentation for:

EC_KEY_*
static VALUE ossl_ec_key_initialize(int argc, VALUE *argv, VALUE self)
{
    EVP_PKEY *pkey;
    EC_KEY *ec = NULL;
    VALUE arg, pass;
    VALUE group = Qnil;
    char *passwd = NULL;

    GetPKey(self, pkey);
    if (pkey->pkey.ec)
        ossl_raise(eECError, "EC_KEY already initialized");

    rb_scan_args(argc, argv, "02", &arg, &pass);

    if (NIL_P(arg)) {
        ec = EC_KEY_new();
    } else {
        if (rb_obj_is_kind_of(arg, cEC)) {
            EC_KEY *other_ec = NULL;

            SafeRequire_EC_KEY(arg, other_ec);
            ec = EC_KEY_dup(other_ec);
        } else if (rb_obj_is_kind_of(arg, cEC_GROUP)) {
                ec = EC_KEY_new();
                group = arg;
        } else {
            BIO *in = ossl_obj2bio(arg);

            if (!NIL_P(pass)) {
                passwd = StringValuePtr(pass);
            }
            ec = PEM_read_bio_ECPrivateKey(in, NULL, ossl_pem_passwd_cb, passwd);
            if (!ec) {
                OSSL_BIO_reset(in);
                ec = PEM_read_bio_EC_PUBKEY(in, NULL, ossl_pem_passwd_cb, passwd);
            }
            if (!ec) {
                OSSL_BIO_reset(in);
                ec = d2i_ECPrivateKey_bio(in, NULL);
            }
            if (!ec) {
                OSSL_BIO_reset(in);
                ec = d2i_EC_PUBKEY_bio(in, NULL);
            }

            BIO_free(in);

            if (ec == NULL) {
                const char *name = StringValueCStr(arg);
                int nid = OBJ_sn2nid(name);

                (void)ERR_get_error();
                if (nid == NID_undef)
                    ossl_raise(eECError, "unknown curve name (%s)\n", name);

                if ((ec = EC_KEY_new_by_curve_name(nid)) == NULL)
                    ossl_raise(eECError, "unable to create curve (%s)\n", name);

                EC_KEY_set_asn1_flag(ec, OPENSSL_EC_NAMED_CURVE);
                EC_KEY_set_conv_form(ec, POINT_CONVERSION_UNCOMPRESSED);
            }
        }
    }

    if (ec == NULL)
        ossl_raise(eECError, NULL);

    if (!EVP_PKEY_assign_EC_KEY(pkey, ec)) {
        EC_KEY_free(ec);
        ossl_raise(eECError, "EVP_PKEY_assign_EC_KEY");
    }

    rb_iv_set(self, "@group", Qnil);

    if (!NIL_P(group))
        rb_funcall(self, rb_intern("group="), 1, arg);

    return self;
}

Public Instance Methods

check_key → true click to toggle source

Raises an exception if the key is invalid.

See the OpenSSL documentation for EC_KEY_check_key()

static VALUE ossl_ec_key_check_key(VALUE self)
{
    EC_KEY *ec;

    Require_EC_KEY(self, ec);

    if (EC_KEY_check_key(ec) != 1)
        ossl_raise(eECError, "EC_KEY_check_key");

    return Qtrue;
}
dh_compute_key(pubkey) → String click to toggle source

See the OpenSSL documentation for ECDH_compute_key()

static VALUE ossl_ec_key_dh_compute_key(VALUE self, VALUE pubkey)
{
    EC_KEY *ec;
    EC_POINT *point;
    int buf_len;
    VALUE str;

    Require_EC_KEY(self, ec);
    SafeRequire_EC_POINT(pubkey, point);

/* BUG: need a way to figure out the maximum string size */
    buf_len = 1024;
    str = rb_str_new(0, buf_len);
/* BUG: take KDF as a block */
    buf_len = ECDH_compute_key(RSTRING_PTR(str), buf_len, point, ec, NULL);
    if (buf_len < 0)
         ossl_raise(eECError, "ECDH_compute_key");

    rb_str_resize(str, buf_len);

    return str;
}
dsa_sign_asn1(data) → String click to toggle source

See the OpenSSL documentation for ECDSA_sign()

static VALUE ossl_ec_key_dsa_sign_asn1(VALUE self, VALUE data)
{
    EC_KEY *ec;
    unsigned int buf_len;
    VALUE str;

    Require_EC_KEY(self, ec);
    StringValue(data);

    if (EC_KEY_get0_private_key(ec) == NULL)
        ossl_raise(eECError, "Private EC key needed!");

    str = rb_str_new(0, ECDSA_size(ec) + 16);
    if (ECDSA_sign(0, (unsigned char *) RSTRING_PTR(data), RSTRING_LENINT(data), (unsigned char *) RSTRING_PTR(str), &buf_len, ec) != 1)
         ossl_raise(eECError, "ECDSA_sign");

    rb_str_resize(str, buf_len);

    return str;
}
dsa_verify_asn1(data, sig) → true or false click to toggle source

See the OpenSSL documentation for ECDSA_verify()

static VALUE ossl_ec_key_dsa_verify_asn1(VALUE self, VALUE data, VALUE sig)
{
    EC_KEY *ec;

    Require_EC_KEY(self, ec);
    StringValue(data);
    StringValue(sig);

    switch (ECDSA_verify(0, (unsigned char *) RSTRING_PTR(data), RSTRING_LENINT(data), (unsigned char *) RSTRING_PTR(sig), (int)RSTRING_LEN(sig), ec)) {
    case 1:     return Qtrue;
    case 0:     return Qfalse;
    default:    break;
    }

    ossl_raise(eECError, "ECDSA_verify");

    UNREACHABLE;
}
export → String click to toggle source
export(cipher, pass_phrase) → String

Outputs the EC key in PEM encoding. If cipher and pass_phrase are given they will be used to encrypt the key. cipher must be an OpenSSL::Cipher::Cipher instance. Note that encryption will only be effective for a private key, public keys will always be encoded in plain text.

static VALUE ossl_ec_key_export(int argc, VALUE *argv, VALUE self)
{
    VALUE cipher, passwd;
    rb_scan_args(argc, argv, "02", &cipher, &passwd);
    return ossl_ec_key_to_string(self, cipher, passwd, EXPORT_PEM);
}
Also aliased as: to_pem
generate_key → self click to toggle source

See the OpenSSL documentation for EC_KEY_generate_key()

static VALUE ossl_ec_key_generate_key(VALUE self)
{
    EC_KEY *ec;

    Require_EC_KEY(self, ec);

    if (EC_KEY_generate_key(ec) != 1)
        ossl_raise(eECError, "EC_KEY_generate_key");

    return self;
}
group → group click to toggle source

Returns a constant OpenSSL::EC::Group that is tied to the key. Modifying the returned group can make the key invalid.

static VALUE ossl_ec_key_get_group(VALUE self)
{
    VALUE group_v;
    EC_KEY *ec;
    ossl_ec_group *ec_group;
    EC_GROUP *group;

    Require_EC_KEY(self, ec);

    group_v = rb_iv_get(self, "@group");
    if (!NIL_P(group_v))
        return group_v;

    if ((group = (EC_GROUP *)EC_KEY_get0_group(ec)) != NULL) {
        group_v = rb_obj_alloc(cEC_GROUP);
        SafeGet_ec_group(group_v, ec_group);
        ec_group->group = group;
        ec_group->dont_free = 1;
        rb_iv_set(group_v, "@key", self);
        rb_iv_set(self, "@group", group_v);
        return group_v;
    }

    return Qnil;
}
group = group → group click to toggle source

Returns the same object passed, not the group object associated with the key. If you wish to access the group object tied to the key call key.group after setting the group.

Setting the group will immediately destroy any previously assigned group object. The group is internally copied by OpenSSL. Modifying the original group after assignment will not effect the internal key structure. (your changes may be lost). BE CAREFUL.

EC_KEY_set_group calls EC_GROUP_free(key->group) then EC_GROUP_dup(), not EC_GROUP_copy. This documentation is accurate for OpenSSL 0.9.8b.

static VALUE ossl_ec_key_set_group(VALUE self, VALUE group_v)
{
    VALUE old_group_v;
    EC_KEY *ec;
    EC_GROUP *group;

    Require_EC_KEY(self, ec);
    SafeRequire_EC_GROUP(group_v, group);

    old_group_v = rb_iv_get(self, "@group");
    if (!NIL_P(old_group_v)) {
        ossl_ec_group *old_ec_group;
        SafeGet_ec_group(old_group_v, old_ec_group);

        old_ec_group->group = NULL;
        old_ec_group->dont_free = 0;
        rb_iv_set(old_group_v, "@key", Qnil);
    }

    rb_iv_set(self, "@group", Qnil);

    if (EC_KEY_set_group(ec, group) != 1)
        ossl_raise(eECError, "EC_KEY_set_group");

    return group_v;
}
private_key → OpenSSL::BN click to toggle source

See the OpenSSL documentation for EC_KEY_get0_private_key()

static VALUE ossl_ec_key_get_private_key(VALUE self)
{
    EC_KEY *ec;
    const BIGNUM *bn;

    Require_EC_KEY(self, ec);

    if ((bn = EC_KEY_get0_private_key(ec)) == NULL)
        return Qnil;

    return ossl_bn_new(bn);
}
private_key = openssl_bn click to toggle source

See the OpenSSL documentation for EC_KEY_set_private_key()

static VALUE ossl_ec_key_set_private_key(VALUE self, VALUE private_key)
{
    EC_KEY *ec;
    BIGNUM *bn = NULL;

    Require_EC_KEY(self, ec);
    if (!NIL_P(private_key))
        bn = GetBNPtr(private_key);

    switch (EC_KEY_set_private_key(ec, bn)) {
    case 1:
        break;
    case 0:
        if (bn == NULL)
            break;
    default:
        ossl_raise(eECError, "EC_KEY_set_private_key");
    }

    return private_key;
}
private_key? → true or false click to toggle source

Both #public_key? and #private_key? may return false at the same time unlike other PKey classes.

static VALUE ossl_ec_key_is_private_key(VALUE self)
{
    EC_KEY *ec;

    Require_EC_KEY(self, ec);

    return (EC_KEY_get0_private_key(ec) ? Qtrue : Qfalse);
}
public_key → OpenSSL::PKey::EC::Point click to toggle source

See the OpenSSL documentation for EC_KEY_get0_public_key()

static VALUE ossl_ec_key_get_public_key(VALUE self)
{
    EC_KEY *ec;
    const EC_POINT *point;
    VALUE group;

    Require_EC_KEY(self, ec);

    if ((point = EC_KEY_get0_public_key(ec)) == NULL)
        return Qnil;

    group = rb_funcall(self, rb_intern("group"), 0);
    if (NIL_P(group))
        ossl_raise(eECError, "EC_KEY_get0_get0_group (has public_key but no group???");

    return ossl_ec_point_dup(point, group);
}
public_key = ec_point click to toggle source

See the OpenSSL documentation for EC_KEY_set_public_key()

static VALUE ossl_ec_key_set_public_key(VALUE self, VALUE public_key)
{
    EC_KEY *ec;
    EC_POINT *point = NULL;

    Require_EC_KEY(self, ec);
    if (!NIL_P(public_key))
        SafeRequire_EC_POINT(public_key, point);

    switch (EC_KEY_set_public_key(ec, point)) {
    case 1:
        break;
    case 0:
        if (point == NULL)
            break;
    default:
        ossl_raise(eECError, "EC_KEY_set_public_key");
    }

    return public_key;
}
public_key? → true or false click to toggle source

Both #public_key? and #private_key? may return false at the same time unlike other PKey classes.

static VALUE ossl_ec_key_is_public_key(VALUE self)
{
    EC_KEY *ec;

    Require_EC_KEY(self, ec);

    return (EC_KEY_get0_public_key(ec) ? Qtrue : Qfalse);
}
to_der → String click to toggle source

See the OpenSSL documentation for i2d_ECPrivateKey_bio()

static VALUE ossl_ec_key_to_der(VALUE self)
{
    return ossl_ec_key_to_string(self, Qnil, Qnil, EXPORT_DER);
}
to_pem(p1 = v1, p2 = v2)
Alias for: export
to_text → String click to toggle source

See the OpenSSL documentation for EC_KEY_print()

static VALUE ossl_ec_key_to_text(VALUE self)
{
    EC_KEY *ec;
    BIO *out;
    VALUE str;

    Require_EC_KEY(self, ec);
    if (!(out = BIO_new(BIO_s_mem()))) {
        ossl_raise(eECError, "BIO_new(BIO_s_mem())");
    }
    if (!EC_KEY_print(out, ec, 0)) {
        BIO_free(out);
        ossl_raise(eECError, "EC_KEY_print");
    }
    str = ossl_membio2str(out);

    return str;
}