1. OpenSSL::
  2. PKey::
  3. EC

class OpenSSL::PKey::EC

OpenSSL::PKey::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 respectivelyshared_key1 =ec1.dh_compute_key(ec2.public_key)shared_key2 =ec2.dh_compute_key(ec1.public_key)pshared_key1==shared_key2#=> true

Constants

EXPLICIT_CURVE
NAMED_CURVE

Public Class Methods

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

Obtains a list of all predefined curves by theOpenSSL. Curve names are returned as sn.

See theOpenSSL documentation for EC_get_builtin_curves().

Source
static VALUEossl_ec_key_s_generate(VALUE klass, VALUE arg){    EVP_PKEY *pkey;    EC_KEY *ec;    VALUE obj;    obj = rb_obj_alloc(klass);    ec = ec_key_new_from_group(arg);    pkey = EVP_PKEY_new();    if (!pkey || EVP_PKEY_assign_EC_KEY(pkey, ec) != 1) {        EVP_PKEY_free(pkey);        EC_KEY_free(ec);        ossl_raise(ePKeyError, "EVP_PKEY_assign_EC_KEY");    }    RTYPEDDATA_DATA(obj) = pkey;    if (!EC_KEY_generate_key(ec))        ossl_raise(ePKeyError, "EC_KEY_generate_key");    return obj;}

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

Source
static VALUE ossl_ec_key_initialize(int argc, VALUE *argv, VALUE self){    EVP_PKEY *pkey;    EC_KEY *ec;    BIO *in;    VALUE arg, pass;    int type;    TypedData_Get_Struct(self, EVP_PKEY, &ossl_evp_pkey_type, pkey);    if (pkey)        rb_raise(rb_eTypeError, "pkey already initialized");    rb_scan_args(argc, argv, "02", &arg, &pass);    if (NIL_P(arg)) {#ifdef OSSL_HAVE_IMMUTABLE_PKEY        rb_raise(rb_eArgError, "OpenSSL::PKey::EC.new cannot be called " \                 "without arguments; pkeys are immutable with OpenSSL 3.0");#else        if (!(ec = EC_KEY_new()))            ossl_raise(ePKeyError, "EC_KEY_new");        goto legacy;#endif    }    else if (rb_obj_is_kind_of(arg, cEC_GROUP)) {        ec = ec_key_new_from_group(arg);        goto legacy;    }    pass = ossl_pem_passwd_value(pass);    arg = ossl_to_der_if_possible(arg);    in = ossl_obj2bio(&arg);    pkey = ossl_pkey_read_generic(in, pass);    BIO_free(in);    if (!pkey) {        ossl_clear_error();        ec = ec_key_new_from_group(arg);        goto legacy;    }    type = EVP_PKEY_base_id(pkey);    if (type != EVP_PKEY_EC) {        EVP_PKEY_free(pkey);        rb_raise(ePKeyError, "incorrect pkey type: %s", OBJ_nid2sn(type));    }    RTYPEDDATA_DATA(self) = pkey;    return self;  legacy:    pkey = EVP_PKEY_new();    if (!pkey || EVP_PKEY_assign_EC_KEY(pkey, ec) != 1) {        EVP_PKEY_free(pkey);        EC_KEY_free(ec);        ossl_raise(ePKeyError, "EVP_PKEY_assign_EC_KEY");    }    RTYPEDDATA_DATA(self) = pkey;    return self;}

Creates a newEC object from given arguments.

Public Instance Methods

Source
static VALUE ossl_ec_key_check_key(VALUE self){#ifdef HAVE_EVP_PKEY_CHECK    EVP_PKEY *pkey;    EVP_PKEY_CTX *pctx;    const EC_KEY *ec;    GetPKey(self, pkey);    GetEC(self, ec);    pctx = EVP_PKEY_CTX_new(pkey, /* engine */NULL);    if (!pctx)        ossl_raise(ePKeyError, "EVP_PKEY_CTX_new");    if (EC_KEY_get0_private_key(ec) != NULL) {        if (EVP_PKEY_check(pctx) != 1) {            EVP_PKEY_CTX_free(pctx);            ossl_raise(ePKeyError, "EVP_PKEY_check");        }    }    else {        if (EVP_PKEY_public_check(pctx) != 1) {            EVP_PKEY_CTX_free(pctx);            ossl_raise(ePKeyError, "EVP_PKEY_public_check");        }    }    EVP_PKEY_CTX_free(pctx);#else    EC_KEY *ec;    GetEC(self, ec);    if (EC_KEY_check_key(ec) != 1)        ossl_raise(ePKeyError, "EC_KEY_check_key");#endif    return Qtrue;}

Raises an exception if the key is invalid.

See also the man page EVP_PKEY_public_check(3).

Source
# File ext/openssl/lib/openssl/pkey.rb, line 307defdh_compute_key(pubkey)obj =OpenSSL::ASN1.Sequence([OpenSSL::ASN1.Sequence([OpenSSL::ASN1.ObjectId("id-ecPublicKey"),group.to_der,    ]),OpenSSL::ASN1.BitString(pubkey.to_octet_string(:uncompressed)),  ])derive(OpenSSL::PKey.read(obj.to_der))end

Derives a shared secret by ECDH.pubkey must be an instance ofOpenSSL::PKey::EC::Point and must belong to the same group.

This method is provided for backwards compatibility, and callsderive internally.

Source
# File ext/openssl/lib/openssl/pkey.rb, line 286defdsa_sign_asn1(data)sign_raw(nil,data)end

Deprecated in version 3.0. Consider usingPKey::PKey#sign_raw andPKey::PKey#verify_raw instead.

Source
# File ext/openssl/lib/openssl/pkey.rb, line 295defdsa_verify_asn1(data,sig)verify_raw(nil,sig,data)end

Deprecated in version 3.0. Consider usingPKey::PKey#sign_raw andPKey::PKey#verify_raw instead.

Source
static VALUEossl_ec_key_export(int argc, VALUE *argv, VALUE self){    OSSL_3_const EC_KEY *ec;    GetEC(self, ec);    if (EC_KEY_get0_public_key(ec) == NULL)        ossl_raise(ePKeyError, "can't export - no public key set");    if (EC_KEY_get0_private_key(ec))        return ossl_pkey_export_traditional(argc, argv, self, 0);    else        return ossl_pkey_export_spki(self, 0);}

Serializes a private or public key to a PEM-encoding.

When the key contains public components only

Serializes it into an X.509 SubjectPublicKeyInfo. The parameterscipher andpassword are ignored.

A PEM-encoded key will look like:

-----BEGIN PUBLIC KEY-----[...]-----END PUBLIC KEY-----

Consider usingpublic_to_pem instead. This serializes the key into an X.509 SubjectPublicKeyInfo regardless of whether it is a public key or a private key.

When the key contains private components, and no parameters are given

Serializes it into a SEC 1/RFC 5915 ECPrivateKey.

A PEM-encoded key will look like:

-----BEGIN EC PRIVATE KEY-----[...]-----END EC PRIVATE KEY-----
When the key contains private components, andcipher andpassword are given

Serializes it into a SEC 1/RFC 5915 ECPrivateKey and encrypts it in OpenSSL’s traditional PEM encryption format.cipher must be a cipher name understood byOpenSSL::Cipher.new or an instance ofOpenSSL::Cipher.

An encrypted PEM-encoded key will look like:

-----BEGIN EC PRIVATE KEY-----Proc-Type: 4,ENCRYPTEDDEK-Info: AES-128-CBC,733F5302505B34701FC41F5C0746E4C0[...]-----END EC PRIVATE KEY-----

Note that this format uses MD5 to derive the encryption key, and hence will not be available on FIPS-compliant systems.

This method is kept for compatibility. This should only be used when the SEC 1/RFC 5915 ECPrivateKey format is required.

Consider usingpublic_to_pem (X.509 SubjectPublicKeyInfo) orprivate_to_pem (PKCS #8 PrivateKeyInfo or EncryptedPrivateKeyInfo) instead.

Also aliased as:to_pem
Alias for:generate_key!
Source
static VALUE ossl_ec_key_generate_key(VALUE self){#ifdef OSSL_HAVE_IMMUTABLE_PKEY    rb_raise(ePKeyError, "pkeys are immutable on OpenSSL 3.0");#else    EC_KEY *ec;    GetEC(self, ec);    if (EC_KEY_generate_key(ec) != 1)        ossl_raise(ePKeyError, "EC_KEY_generate_key");    return self;#endif}

Generates a new random private and public key.

See also theOpenSSL documentation for EC_KEY_generate_key()

Example

ec =OpenSSL::PKey::EC.new("prime256v1")pec.private_key# => nilec.generate_key!pec.private_key# => #<OpenSSL::BN XXXXXX>
Also aliased as:generate_key
Source
static VALUEossl_ec_key_get_group(VALUE self){    OSSL_3_const 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);}

Returns theEC::Group that the key is associated with. Modifying the returned group does not affectkey.

Source
static VALUEossl_ec_key_set_group(VALUE self, VALUE group_v){#ifdef OSSL_HAVE_IMMUTABLE_PKEY    rb_raise(ePKeyError, "pkeys are immutable on OpenSSL 3.0");#else    EC_KEY *ec;    EC_GROUP *group;    GetEC(self, ec);    GetECGroup(group_v, group);    if (EC_KEY_set_group(ec, group) != 1)        ossl_raise(ePKeyError, "EC_KEY_set_group");    return group_v;#endif}

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

Source
static VALUE ossl_ec_key_is_private(VALUE self){    OSSL_3_const EC_KEY *ec;    GetEC(self, ec);    return EC_KEY_get0_private_key(ec) ? Qtrue : Qfalse;}

Returns whether thisEC instance has a private key. The private key (BN) can be retrieved withEC#private_key.

Also aliased as:private_key?
Source
static VALUE ossl_ec_key_get_private_key(VALUE self){    OSSL_3_const 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);}

See theOpenSSL documentation for EC_KEY_get0_private_key()

Source
static VALUE ossl_ec_key_set_private_key(VALUE self, VALUE private_key){#ifdef OSSL_HAVE_IMMUTABLE_PKEY    rb_raise(ePKeyError, "pkeys are immutable on OpenSSL 3.0");#else    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;        /* fallthrough */    default:        ossl_raise(ePKeyError, "EC_KEY_set_private_key");    }    return private_key;#endif}

See theOpenSSL documentation for EC_KEY_set_private_key()

Alias for:private?
Source
static VALUE ossl_ec_key_is_public(VALUE self){    OSSL_3_const EC_KEY *ec;    GetEC(self, ec);    return EC_KEY_get0_public_key(ec) ? Qtrue : Qfalse;}

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

Also aliased as:public_key?
Source
static VALUE ossl_ec_key_get_public_key(VALUE self){    OSSL_3_const 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));}

See theOpenSSL documentation for EC_KEY_get0_public_key()

Source
static VALUE ossl_ec_key_set_public_key(VALUE self, VALUE public_key){#ifdef OSSL_HAVE_IMMUTABLE_PKEY    rb_raise(ePKeyError, "pkeys are immutable on OpenSSL 3.0");#else    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;        /* fallthrough */    default:        ossl_raise(ePKeyError, "EC_KEY_set_public_key");    }    return public_key;#endif}

See theOpenSSL documentation for EC_KEY_set_public_key()

Alias for:public?
Source
static VALUEossl_ec_key_to_der(VALUE self){    OSSL_3_const EC_KEY *ec;    GetEC(self, ec);    if (EC_KEY_get0_public_key(ec) == NULL)        ossl_raise(ePKeyError, "can't export - no public key set");    if (EC_KEY_get0_private_key(ec))        return ossl_pkey_export_traditional(0, NULL, self, 1);    else        return ossl_pkey_export_spki(self, 1);}

Serializes a private or public key to a DER-encoding.

Seeto_pem for details.

This method is kept for compatibility. This should only be used when the SEC 1/RFC 5915 ECPrivateKey format is required.

Consider usingpublic_to_der orprivate_to_der instead.

Serializes a private or public key to a PEM-encoding.

When the key contains public components only

Serializes it into an X.509 SubjectPublicKeyInfo. The parameterscipher andpassword are ignored.

A PEM-encoded key will look like:

-----BEGIN PUBLIC KEY-----[...]-----END PUBLIC KEY-----

Consider usingpublic_to_pem instead. This serializes the key into an X.509 SubjectPublicKeyInfo regardless of whether it is a public key or a private key.

When the key contains private components, and no parameters are given

Serializes it into a SEC 1/RFC 5915 ECPrivateKey.

A PEM-encoded key will look like:

-----BEGIN EC PRIVATE KEY-----[...]-----END EC PRIVATE KEY-----
When the key contains private components, andcipher andpassword are given

Serializes it into a SEC 1/RFC 5915 ECPrivateKey and encrypts it in OpenSSL’s traditional PEM encryption format.cipher must be a cipher name understood byOpenSSL::Cipher.new or an instance ofOpenSSL::Cipher.

An encrypted PEM-encoded key will look like:

-----BEGIN EC PRIVATE KEY-----Proc-Type: 4,ENCRYPTEDDEK-Info: AES-128-CBC,733F5302505B34701FC41F5C0746E4C0[...]-----END EC PRIVATE KEY-----

Note that this format uses MD5 to derive the encryption key, and hence will not be available on FIPS-compliant systems.

This method is kept for compatibility. This should only be used when the SEC 1/RFC 5915 ECPrivateKey format is required.

Consider usingpublic_to_pem (X.509 SubjectPublicKeyInfo) orprivate_to_pem (PKCS #8 PrivateKeyInfo or EncryptedPrivateKeyInfo) instead.

Alias for:export