Extended maintenance of Ruby 1.9.3 ended on February 23, 2015. Read more

In Files

  • openssl/ossl_pkey.c

Class/Module Index [+]

Quicksearch

OpenSSL::PKey::DH

An implementation of the Diffie-Hellman key exchange protocol based on discrete logarithms in finite fields, the same basis that DSA is built on.

Accessor methods for the Diffie-Hellman parameters

  • DH#p

The prime (an OpenSSL::BN) of the Diffie-Hellman parameters.

  • DH#g

The generator (an OpenSSL::BN) g of the Diffie-Hellman parameters.

  • DH#pub_key

The per-session public key (an OpenSSL::BN) matching the private key. This needs to be passed to #compute_key.

  • DH#priv_key

The per-session private key, an OpenSSL::BN.

Example of a key exchange

dh1 = OpenSSL::PKey::DH.new(2048)
der = dh1.public_key.to_der #you may send this publicly to the participating party
dh2 = OpenSSL::PKey::DH.new(der)
dh2.generate_key! #generate the per-session key pair
symm_key1 = dh1.compute_key(dh2.pub_key)
symm_key2 = dh2.compute_key(dh1.pub_key)

puts symm_key1 == symm_key2 # => true

Public Class Methods

generate(size [, generator]) → dh click to toggle source

Creates a new DH instance from scratch by generating the private and public components alike.

Parameters

  • size is an integer representing the desired key size. Keys smaller than 1024 bits should be considered insecure.

  • generator is a small number > 1, typically 2 or 5.

 
               static VALUE
ossl_dh_s_generate(int argc, VALUE *argv, VALUE klass)
{
    DH *dh ;
    int g = 2;
    VALUE size, gen, obj;

    if (rb_scan_args(argc, argv, "11", &size, &gen) == 2) {
        g = NUM2INT(gen);
    }
    dh = dh_generate(NUM2INT(size), g);
    obj = dh_instance(klass, dh);
    if (obj == Qfalse) {
        DH_free(dh);
        ossl_raise(eDHError, NULL);
    }

    return obj;
}
            
new([size [, generator] | string]) → dh click to toggle source

Either generates a DH instance from scratch or by reading already existing DH parameters from string. Note that when reading a DH instance from data that was encoded from a DH instance by using #to_pem or #to_der the result will not contain a public/private key pair yet. This needs to be generated using #generate_key! first.

Parameters

  • size is an integer representing the desired key size. Keys smaller than 1024 bits should be considered insecure.

  • generator is a small number > 1, typically 2 or 5.

  • string contains the DER or PEM encoded key.

Examples

DH.new # -> dh
DH.new(1024) # -> dh
DH.new(1024, 5) # -> dh
#Reading DH parameters
dh = DH.new(File.read('parameters.pem')) # -> dh, but no public/private key yet
dh.generate_key! # -> dh with public and private key
 
               static VALUE
ossl_dh_initialize(int argc, VALUE *argv, VALUE self)
{
    EVP_PKEY *pkey;
    DH *dh;
    int g = 2;
    BIO *in;
    VALUE arg, gen;

    GetPKey(self, pkey);
    if(rb_scan_args(argc, argv, "02", &arg, &gen) == 0) {
      dh = DH_new();
    }
    else if (FIXNUM_P(arg)) {
        if (!NIL_P(gen)) {
            g = NUM2INT(gen);
        }
        if (!(dh = dh_generate(FIX2INT(arg), g))) {
            ossl_raise(eDHError, NULL);
        }
    }
    else {
        arg = ossl_to_der_if_possible(arg);
        in = ossl_obj2bio(arg);
        dh = PEM_read_bio_DHparams(in, NULL, NULL, NULL);
        if (!dh){
            OSSL_BIO_reset(in);
            dh = d2i_DHparams_bio(in, NULL);
        }
        BIO_free(in);
        if (!dh) {
            ossl_raise(eDHError, NULL);
        }
    }
    if (!EVP_PKEY_assign_DH(pkey, dh)) {
        DH_free(dh);
        ossl_raise(eDHError, NULL);
    }
    return self;
}
            

Public Instance Methods

compute_key(pub_bn) → aString click to toggle source

Returns a String containing a shared secret computed from the other party’s public value. See DH_compute_key() for further information.

Parameters

#public_key as that contains the DH parameters only.

 
               static VALUE
ossl_dh_compute_key(VALUE self, VALUE pub)
{
    DH *dh;
    EVP_PKEY *pkey;
    BIGNUM *pub_key;
    VALUE str;
    int len;

    GetPKeyDH(self, pkey);
    dh = pkey->pkey.dh;
    pub_key = GetBNPtr(pub);
    len = DH_size(dh);
    str = rb_str_new(0, len);
    if ((len = DH_compute_key((unsigned char *)RSTRING_PTR(str), pub_key, dh)) < 0) {
        ossl_raise(eDHError, NULL);
    }
    rb_str_set_len(str, len);

    return str;
}
            
to_pem → aString click to toggle source

Encodes this DH to its PEM encoding. Note that any existing per-session public/private keys will not get encoded, just the Diffie-Hellman parameters will be encoded.

 
               static VALUE
ossl_dh_export(VALUE self)
{
    EVP_PKEY *pkey;
    BIO *out;
    VALUE str;

    GetPKeyDH(self, pkey);
    if (!(out = BIO_new(BIO_s_mem()))) {
        ossl_raise(eDHError, NULL);
    }
    if (!PEM_write_bio_DHparams(out, pkey->pkey.dh)) {
        BIO_free(out);
        ossl_raise(eDHError, NULL);
    }
    str = ossl_membio2str(out);

    return str;
}
            
Also aliased as: to_pem, to_s
generate_key! → self click to toggle source

Generates a private and public key unless a private key already exists. If this DH instance was generated from public DH parameters (e.g. by encoding the result of #public_key), then this method needs to be called first in order to generate the per-session keys before performing the actual key exchange.

Example

dh = OpenSSL::PKey::DH.new(2048)
public_key = dh.public_key #contains no private/public key yet
public_key.generate_key!
puts public_key.private? # => true
 
               static VALUE
ossl_dh_generate_key(VALUE self)
{
    DH *dh;
    EVP_PKEY *pkey;

    GetPKeyDH(self, pkey);
    dh = pkey->pkey.dh;

    if (!DH_generate_key(dh))
        ossl_raise(eDHError, "Failed to generate key");
    return self;
}
            
params → hash click to toggle source

Stores all parameters of key to the hash INSECURE: PRIVATE INFORMATIONS CAN LEAK OUT!!! Don’t use :-)) (I’s up to you)

 
               static VALUE
ossl_dh_get_params(VALUE self)
{
    EVP_PKEY *pkey;
    VALUE hash;

    GetPKeyDH(self, pkey);

    hash = rb_hash_new();

    rb_hash_aset(hash, rb_str_new2("p"), ossl_bn_new(pkey->pkey.dh->p));
    rb_hash_aset(hash, rb_str_new2("g"), ossl_bn_new(pkey->pkey.dh->g));
    rb_hash_aset(hash, rb_str_new2("pub_key"), ossl_bn_new(pkey->pkey.dh->pub_key));
    rb_hash_aset(hash, rb_str_new2("priv_key"), ossl_bn_new(pkey->pkey.dh->priv_key));

    return hash;
}
            
check_params → true | false click to toggle source

Validates the Diffie-Hellman parameters associated with this instance. It checks whether a safe prime and a suitable generator are used. If this is not the case, false is returned.

 
               static VALUE
ossl_dh_check_params(VALUE self)
{
    DH *dh;
    EVP_PKEY *pkey;
    int codes;

    GetPKeyDH(self, pkey);
    dh = pkey->pkey.dh;

    if (!DH_check(dh, &codes)) {
        return Qfalse;
    }

    return codes == 0 ? Qtrue : Qfalse;
}
            
private? → true | false click to toggle source

Indicates whether this DH instance has a private key associated with it or not. The private key may be retrieved with DH#priv_key.

 
               static VALUE
ossl_dh_is_private(VALUE self)
{
    EVP_PKEY *pkey;

    GetPKeyDH(self, pkey);

    return (DH_PRIVATE(pkey->pkey.dh)) ? Qtrue : Qfalse;
}
            
public? → true | false click to toggle source

Indicates whether this DH instance has a public key associated with it or not. The public key may be retrieved with DH#pub_key.

 
               static VALUE
ossl_dh_is_public(VALUE self)
{
    EVP_PKEY *pkey;

    GetPKeyDH(self, pkey);

    return (pkey->pkey.dh->pub_key) ? Qtrue : Qfalse;
}
            
public_key → aDH click to toggle source

Returns a new DH instance that carries just the public information, i.e. the prime p and the generator g, but no public/private key yet. Such a pair may be generated using #generate_key!. The “public key” needed for a key exchange with #compute_key is considered as per-session information and may be retrieved with DH#pub_key once a key pair has been generated. If the current instance already contains private information (and thus a valid public/private key pair), this information will no longer be present in the new instance generated by #public_key. This feature is helpful for publishing the Diffie-Hellman parameters without leaking any of the private per-session information.

Example

dh = OpenSSL::PKey::DH.new(2048) # has public and private key set
public_key = dh.public_key # contains only prime and generator
parameters = public_key.to_der # it's safe to publish this
 
               static VALUE
ossl_dh_to_public_key(VALUE self)
{
    EVP_PKEY *pkey;
    DH *dh;
    VALUE obj;

    GetPKeyDH(self, pkey);
    dh = DHparams_dup(pkey->pkey.dh); /* err check perfomed by dh_instance */
    obj = dh_instance(CLASS_OF(self), dh);
    if (obj == Qfalse) {
        DH_free(dh);
        ossl_raise(eDHError, NULL);
    }

    return obj;
}
            
to_der → aString click to toggle source

Encodes this DH to its DER encoding. Note that any existing per-session public/private keys will not get encoded, just the Diffie-Hellman parameters will be encoded.

 
               static VALUE
ossl_dh_to_der(VALUE self)
{
    EVP_PKEY *pkey;
    unsigned char *p;
    long len;
    VALUE str;

    GetPKeyDH(self, pkey);
    if((len = i2d_DHparams(pkey->pkey.dh, NULL)) <= 0)
        ossl_raise(eDHError, NULL);
    str = rb_str_new(0, len);
    p = (unsigned char *)RSTRING_PTR(str);
    if(i2d_DHparams(pkey->pkey.dh, &p) < 0)
        ossl_raise(eDHError, NULL);
    ossl_str_adjust(str, p);

    return str;
}
            
to_pem() click to toggle source
Alias for: export
to_s() click to toggle source
Alias for: export
to_text → aString click to toggle source

Prints all parameters of key to buffer INSECURE: PRIVATE INFORMATIONS CAN LEAK OUT!!! Don’t use :-)) (I’s up to you)

 
               static VALUE
ossl_dh_to_text(VALUE self)
{
    EVP_PKEY *pkey;
    BIO *out;
    VALUE str;

    GetPKeyDH(self, pkey);
    if (!(out = BIO_new(BIO_s_mem()))) {
        ossl_raise(eDHError, NULL);
    }
    if (!DHparams_print(out, pkey->pkey.dh)) {
        BIO_free(out);
        ossl_raise(eDHError, NULL);
    }
    str = ossl_membio2str(out);

    return str;
}
            

Commenting is here to help enhance the documentation. For example, code samples, or clarification of the documentation.

If you have questions about Ruby or the documentation, please post to one of the Ruby mailing lists. You will get better, faster, help that way.

If you wish to post a correction of the docs, please do so, but also file bug report so that it can be corrected for the next release. Thank you.

If you want to help improve the Ruby documentation, please visit Documenting-ruby.org.