123456789_123456789_123456789_123456789_123456789_

Class: OpenSSL::PKey::EC

Relationships & Source Files
Namespace Children
Classes:
Super Chains via Extension / Inclusion / Inheritance
Class Chain:
self, PKey
Instance Chain:
self, PKey
Inherits: OpenSSL::PKey::PKey
Defined in: ext/openssl/ossl_pkey_ec.c

Overview

EC provides access to Elliptic Curve Digital Signature Algorithm (ECDSA) and Elliptic Curve Diffie-Hellman (ECDH).

Key exchange

ec1 = OpenSSL::PKey::EC.generate("prime256v1")
ec2 = OpenSSL::PKey::EC.generate("prime256v1")
# ec1 and ec2 have own private key respectively
shared_key1 = ec1.dh_compute_key(ec2.public_key)
shared_key2 = ec2.dh_compute_key(ec1.public_key)

p shared_key1 == shared_key2 #=> true

Constant Summary

Class Method Summary

PKey - Inherited

.new

Because PKey is an abstract class, actually calling this method explicitly will raise a NotImplementedError.

Instance Attribute Summary

Instance Method Summary

PKey - Inherited

#sign

To sign the String data, digest, an instance of ::OpenSSL::Digest, must be provided.

#verify

To verify the String signature, digest, an instance of ::OpenSSL::Digest, must be provided to re-compute the message digest of the original data, also a String.

Constructor Details

.new .new(ec_key) .new(ec_group) .new("secp112r1") .new(pem_string [, pwd]) .new(der_string)

Creates a new EC object from given arguments.

[ GitHub ]

  
# File 'ext/openssl/ossl_pkey_ec.c', line 181

static VALUE ossl_ec_key_initialize(int argc, VALUE *argv, VALUE self)
{
    EVP_PKEY *pkey;
    EC_KEY *ec;
    VALUE arg, pass;

    GetPKey(self, pkey);
    if (EVP_PKEY_base_id(pkey) != EVP_PKEY_NONE)
        ossl_raise(eECError, "EC_KEY already initialized");

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

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

	GetEC(arg, other_ec);
	if (!(ec = EC_KEY_dup(other_ec)))
	    ossl_raise(eECError, NULL);
    } else if (rb_obj_is_kind_of(arg, cEC_GROUP)) {
	ec = ec_key_new_from_group(arg);
    } else {
	BIO *in;

	pass = ossl_pem_passwd_value(pass);
	in = ossl_obj2bio(&arg);

	ec = PEM_read_bio_ECPrivateKey(in, NULL, ossl_pem_passwd_cb, (void *)pass);
	if (!ec) {
	    OSSL_BIO_reset(in);
	    ec = PEM_read_bio_EC_PUBKEY(in, NULL, ossl_pem_passwd_cb, (void *)pass);
	}
	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) {
	    ossl_clear_error();
	    ec = ec_key_new_from_group(arg);
	}
    }

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

    return self;
}

Class Method Details

.builtin_curvesArray, comment

Obtains a list of all predefined curves by the ::OpenSSL. Curve names are returned as sn.

See the ::OpenSSL documentation for EC_get_builtin_curves().

[ GitHub ]

  
# File 'ext/openssl/ossl_pkey_ec.c', line 998

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

.generate(ec_group) ⇒ EC .generate(string) ⇒ EC

Creates a new EC instance with a new random private and public key.

[ GitHub ]

  
# File 'ext/openssl/ossl_pkey_ec.c', line 150

static VALUE
ossl_ec_key_s_generate(VALUE klass, VALUE arg)
{
    EC_KEY *ec;
    VALUE obj;

    ec = ec_key_new_from_group(arg);

    obj = ec_instance(klass, ec);
    if (obj == Qfalse) {
	EC_KEY_free(ec);
	ossl_raise(eECError, NULL);
    }

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

    return obj;
}

Instance Attribute Details

#group ⇒ group (rw)

Returns the EC::Group that the key is associated with. Modifying the returned group does not affect key.

[ GitHub ]

  
# File 'ext/openssl/ossl_pkey_ec.c', line 268

static VALUE
ossl_ec_key_get_group(VALUE self)
{
    EC_KEY *ec;
    const EC_GROUP *group;

    GetEC(self, ec);
    group = EC_KEY_get0_group(ec);
    if (!group)
	return Qnil;

    return ec_group_new(group);
}

#group=(group) (rw)

Sets the EC::Group for the key. The group structure is internally copied so modification to group after assigning to a key has no effect on the key.

[ GitHub ]

  
# File 'ext/openssl/ossl_pkey_ec.c', line 289

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

    GetEC(self, ec);
    GetECGroup(group_v, group);

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

    return group_v;
}

#private?Boolean (rw) Also known as: #private_key?

Returns whether this EC instance has a private key. The private key (BN) can be retrieved with #private_key.

[ GitHub ]

  
# File 'ext/openssl/ossl_pkey_ec.c', line 419

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

    GetEC(self, ec);

    return EC_KEY_get0_private_key(ec) ? Qtrue : Qfalse;
}

#private_keyOpenSSL::BN (rw)

See the ::OpenSSL documentation for EC_KEY_get0_private_key()

[ GitHub ]

  
# File 'ext/openssl/ossl_pkey_ec.c', line 310

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

    GetEC(self, ec);
    if ((bn = EC_KEY_get0_private_key(ec)) == NULL)
        return Qnil;

    return ossl_bn_new(bn);
}

#private_key=(openssl_bn) (rw)

See the ::OpenSSL documentation for EC_KEY_set_private_key()

[ GitHub ]

  
# File 'ext/openssl/ossl_pkey_ec.c', line 328

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

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

#public?Boolean (rw) Also known as: #public_key?

Returns whether this EC instance has a public key. The public key (EC::Point) can be retrieved with #public_key.

[ GitHub ]

  
# File 'ext/openssl/ossl_pkey_ec.c', line 403

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

    GetEC(self, ec);

    return EC_KEY_get0_public_key(ec) ? Qtrue : Qfalse;
}

#public_keyEC (rw)

See the ::OpenSSL documentation for EC_KEY_get0_public_key()

[ GitHub ]

  
# File 'ext/openssl/ossl_pkey_ec.c', line 356

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

    GetEC(self, ec);
    if ((point = EC_KEY_get0_public_key(ec)) == NULL)
        return Qnil;

    return ec_point_new(point, EC_KEY_get0_group(ec));
}

#public_key=(ec_point) (rw)

See the ::OpenSSL documentation for EC_KEY_set_public_key()

[ GitHub ]

  
# File 'ext/openssl/ossl_pkey_ec.c', line 374

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

    GetEC(self, ec);
    if (!NIL_P(public_key))
        GetECPoint(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;
}

Instance Method Details

#check_keytrue

Raises an exception if the key is invalid.

See the ::OpenSSL documentation for EC_KEY_check_key()

[ GitHub ]

  
# File 'ext/openssl/ossl_pkey_ec.c', line 574

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

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

    return Qtrue;
}

#dh_compute_key(pubkey) ⇒ String

See the ::OpenSSL documentation for ECDH_compute_key()

[ GitHub ]

  
# File 'ext/openssl/ossl_pkey_ec.c', line 591

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

    GetEC(self, ec);
    GetECPoint(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

See the ::OpenSSL documentation for ECDSA_sign()

[ GitHub ]

  
# File 'ext/openssl/ossl_pkey_ec.c', line 622

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

    GetEC(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));
    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_set_len(str, buf_len);

    return str;
}

#dsa_verify_asn1(data, sig) ⇒ Boolean

See the ::OpenSSL documentation for ECDSA_verify()

[ GitHub ]

  
# File 'ext/openssl/ossl_pkey_ec.c', line 648

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

    GetEC(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([cipher, pass_phrase]) ⇒ String #to_pem([cipher, pass_phrase]) ⇒ String
Also known as: #to_pem

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 instance. Note that encryption will only be effective for a private key, public keys will always be encoded in plain text.

[ GitHub ]

  
# File 'ext/openssl/ossl_pkey_ec.c', line 498

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

#generate_keyself Also known as: #generate_key!

Generates a new random private and public key.

See also the ::OpenSSL documentation for EC_KEY_generate_key()

Example

ec = OpenSSL::PKey::EC.new("prime256v1")
p ec.private_key # => nil
ec.generate_key!
p ec.private_key # => #<OpenSSL::BN XXXXXX>
[ GitHub ]

  
# File 'ext/openssl/ossl_pkey_ec.c', line 555

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

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

    return self;
}

#generate_keyself #generate_key!self

Alias for #generate_key.

#initialize_copy(other)

[ GitHub ]

  
# File 'ext/openssl/ossl_pkey_ec.c', line 239

static VALUE
ossl_ec_key_initialize_copy(VALUE self, VALUE other)
{
    EVP_PKEY *pkey;
    EC_KEY *ec, *ec_new;

    GetPKey(self, pkey);
    if (EVP_PKEY_base_id(pkey) != EVP_PKEY_NONE)
	ossl_raise(eECError, "EC already initialized");
    GetEC(other, ec);

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

    return self;
}

#private?Boolean (rw) #private_key?Boolean

Alias for #private?.

#public?Boolean (rw) #public_key?Boolean

Alias for #public?.

#to_derString

See the ::OpenSSL documentation for i2d_ECPrivateKey_bio()

[ GitHub ]

  
# File 'ext/openssl/ossl_pkey_ec.c', line 511

static VALUE ossl_ec_key_to_der(VALUE self)
{
    return ossl_ec_key_to_string(self, Qnil, Qnil, EXPORT_DER);
}

#export([cipher, pass_phrase]) ⇒ String #to_pem([cipher, pass_phrase]) ⇒ String

Alias for #export.

#to_textString

See the ::OpenSSL documentation for EC_KEY_print()

[ GitHub ]

  
# File 'ext/openssl/ossl_pkey_ec.c', line 522

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

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