Class: OpenSSL::PKey::EC

Inherits:
PKey
  • Object
show all
Defined in:
ossl_pkey_ec.c,
ossl_pkey_ec.c

Overview

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

Defined Under Namespace

Classes: Group, Point, Point

Constant Summary collapse

NAMED_CURVE =
INT2NUM(OPENSSL_EC_NAMED_CURVE)
EXPLICIT_CURVE =
INT2NUM(OPENSSL_EC_EXPLICIT_CURVE)

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from PKey

#sign, #verify

Constructor Details

#OpenSSL::PKey::EC.newObject #OpenSSL::PKey::EC.new(ec_key) ⇒ Object #OpenSSL::PKey::EC.new(ec_group) ⇒ Object #OpenSSL::PKey::EC.new("secp112r1") ⇒ Object #OpenSSL::PKey::EC.new(pem_string[, pwd]) ⇒ Object #OpenSSL::PKey::EC.new(der_string) ⇒ Object

Creates a new EC object from given arguments.



181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
# File '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

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().

Returns:

  • (Array)


998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
# File '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) ⇒ Object .generate(string) ⇒ Object

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



150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
# File '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 Method Details

#check_keytrue

Raises an exception if the key is invalid.

See the OpenSSL documentation for EC_KEY_check_key()

Returns:

  • (true)


574
575
576
577
578
579
580
581
582
583
# File '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()

Returns:

  • (String)


591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
# File '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()

Returns:

  • (String)


622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
# File '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()

Returns:

  • (Boolean)


648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
# File '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.

Overloads:

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

    Returns:

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

    Returns:

    • (String)


498
499
500
501
502
503
# File '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_key!self 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>

Returns:

  • (self)


555
556
557
558
559
560
561
562
563
564
# File '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;
}

#groupObject

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



268
269
270
271
272
273
274
275
276
277
278
279
280
# File '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) ⇒ Object

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.



289
290
291
292
293
294
295
296
297
298
299
300
301
302
# File '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;
}

#initialize_copy(other) ⇒ Object



239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
# File '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 Also known as: private_key?

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

Returns:

  • (Boolean)


419
420
421
422
423
424
425
426
# File '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

See the OpenSSL documentation for EC_KEY_get0_private_key()

Returns:



310
311
312
313
314
315
316
317
318
319
320
# File '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) ⇒ Object

See the OpenSSL documentation for EC_KEY_set_private_key()



328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
# File '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 Also known as: public_key?

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

Returns:

  • (Boolean)


403
404
405
406
407
408
409
410
# File '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_keyOpenSSL::PKey::EC::Point

See the OpenSSL documentation for EC_KEY_get0_public_key()



356
357
358
359
360
361
362
363
364
365
366
# File '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) ⇒ Object

See the OpenSSL documentation for EC_KEY_set_public_key()



374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
# File '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;
}

#to_derString

See the OpenSSL documentation for i2d_ECPrivateKey_bio()

Returns:

  • (String)


511
512
513
514
# File '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);
}

#to_textString

See the OpenSSL documentation for EC_KEY_print()

Returns:

  • (String)


522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
# File '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;
}