Class: OpenSSL::PKey::DH
| Relationships & Source Files | |
| Super Chains via Extension / Inclusion / Inheritance | |
| Class Chain: 
          self,
           PKey | |
| Instance Chain: 
          self,
           ::OpenSSL::Marshal,PKey | |
| Inherits: | OpenSSL::PKey::PKey 
 | 
| Defined in: | ext/openssl/ossl_pkey_dh.c, ext/openssl/lib/openssl/pkey.rb | 
Overview
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 DH#compute_key. 
- DH#priv_key
- 
The per-session private key, an OpenSSL::BN. 
Example of a key exchange
# you may send the parameters (der) and own public key (pub1) publicly
# to the participating party
dh1 = OpenSSL::PKey::DH.new(2048)
der = dh1.to_der
pub1 = dh1.pub_key
# the other party generates its per-session key pair
dhparams = OpenSSL::PKey::DH.new(der)
dh2 = OpenSSL::PKey.generate_key(dhparams)
pub2 = dh2.pub_key
symm_key1 = dh1.compute_key(pub2)
symm_key2 = dh2.compute_key(pub1)
puts symm_key1 == symm_key2 # => trueClass Method Summary
- 
    
      .generate(size, generator = 2)  ⇒ DH 
    
    Creates a new DHinstance from scratch by generating random parameters and a key pair.
- 
    
      .new  ⇒ DH 
    
    constructor
    Internal use only
    Creates a new instance of DH.
PKey - Inherited
| .new | Because PKey is an abstract class, actually calling this method explicitly will raise a NotImplementedError. | 
Instance Attribute Summary
- 
    
      #params_ok?  ⇒ Boolean 
    
    readonly
    Validates the Diffie-Hellman parameters associated with this instance. 
- 
    
      #private?  ⇒ Boolean 
    
    readonly
    Indicates whether this DHinstance has a private key associated with it or not.
- 
    
      #public?  ⇒ Boolean 
    
    readonly
    Indicates whether this DHinstance has a public key associated with it or not.
Instance Method Summary
- 
    
      #compute_key(pub_bn)  ⇒ String 
    
    Returns a String containing a shared secret computed from the other party’s public value. 
- 
    
      #export  ⇒ String 
    
    Alias for #to_s. 
- 
    
      #generate_key!  ⇒ self 
    
    Generates a private and public key unless a private key already exists. 
- #initialize_copy(other)
- 
    
      #params  ⇒ Hash 
    
    Stores all parameters of key to the hash INSECURE: PRIVATE INFORMATIONS CAN LEAK OUT!!! Don’t use :-)) (I’s up to you). 
- 
    
      #public_key  ⇒ DH 
    
    Returns a new DHinstance that carries just the DH parameters.
- 
    
      #set_key(pub_key, priv_key)  ⇒ self 
    
    Sets pub_key and priv_key for the DHinstance.
- 
    
      #set_pqg(p, q, g)  ⇒ self 
    
    Sets p, q, g to the DHinstance.
- 
    
      #to_der  ⇒ String 
    
    Serializes the DHparameters to a DER-encoding.
- 
    
      #to_pem  ⇒ String 
    
    Alias for #to_s. 
- 
    
      #to_s  ⇒ String 
      (also: #export, #to_pem)
    
    Serializes the DHparameters to a PEM-encoding.
::OpenSSL::Marshal - Included
PKey - Inherited
| #compare? | Used primarily to check if an X509::Certificate#public_key compares to its private key. | 
| #decrypt | Performs a public key decryption operation using  | 
| #derive | Derives a shared secret from pkey and peer_pkey. | 
| #encrypt | Performs a public key encryption operation using  | 
| #initialize_copy, | |
| #inspect | Returns a string describing the  | 
| #oid | Returns the short name of the OID associated with pkey. | 
| #private_to_der | Serializes the private key to DER-encoded PKCS #8 format. | 
| #private_to_pem | Serializes the private key to PEM-encoded PKCS #8 format. | 
| #public_to_der | Serializes the public key to DER-encoded X.509 SubjectPublicKeyInfo format. | 
| #public_to_pem | Serializes the public key to PEM-encoded X.509 SubjectPublicKeyInfo format. | 
| #raw_private_key | See the  | 
| #raw_public_key | See the  | 
| #sign | Hashes and signs the  | 
| #sign_raw | Signs  | 
| #to_text | Dumps key parameters, public key, and private key components contained in the key into a human-readable text. | 
| #verify | Verifies the  | 
| #verify_raw | Verifies the  | 
| #verify_recover | Recovers the signed data from  | 
Constructor Details
    
      .new  ⇒ DH 
      .new(string)  ⇒ DH 
      .new(size [, generator])  ⇒ DH 
    
  
  DH 
      .new(string)  ⇒ DH 
      .new(size [, generator])  ⇒ DH 
    Creates a new instance of DH.
If called without arguments, an empty instance without any parameter or key components is created. Use #set_pqg to manually set the parameters afterwards (and optionally #set_key to set private and public key components).
If a String is given, tries to parse it as a DER- or PEM- encoded parameters. See also OpenSSL::PKey.read which can parse keys of any kinds.
The .new(size [, generator]) form is an alias of .generate.
- string
- 
A String that contains the DER or PEM encoded key. 
- size
- 
See DH.generate. 
- generator
- 
See DH.generate. 
Examples:
# Creating an instance from scratch
# Note that this is deprecated and will not work on OpenSSL 3.0 or later.
dh = OpenSSL::PKey::DH.new
dh.set_pqg(bn_p, nil, bn_g)
# Generating a parameters and a key pair
dh = OpenSSL::PKey::DH.new(2048) # An alias of OpenSSL::PKey::DH.generate(2048)
# Reading DH parameters
dh_params = OpenSSL::PKey::DH.new(File.read('parameters.pem')) # loads parameters only
dh = OpenSSL::PKey.generate_key(dh_params) # generates a key pair# File 'ext/openssl/ossl_pkey_dh.c', line 72
static VALUE
ossl_dh_initialize(int argc, VALUE *argv, VALUE self)
{
    EVP_PKEY *pkey;
    int type;
    DH *dh;
    BIO *in = NULL;
    VALUE arg;
    TypedData_Get_Struct(self, EVP_PKEY, &ossl_evp_pkey_type, pkey);
    if (pkey)
        rb_raise(rb_eTypeError, "pkey already initialized");
    /* The DH.new(size, generator) form is handled by lib/openssl/pkey.rb */
    if (rb_scan_args(argc, argv, "01", &arg) == 0) {
        dh = DH_new();
        if (!dh)
            ossl_raise(eDHError, "DH_new");
        goto legacy;
    }
    arg = ossl_to_der_if_possible(arg);
    in = ossl_obj2bio(&arg);
    /*
     * On OpenSSL <= 1.1.1 and current versions of LibreSSL, the generic
     * routine does not support DER-encoded parameters
     */
    dh = d2i_DHparams_bio(in, NULL);
    if (dh)
        goto legacy;
    OSSL_BIO_reset(in);
    pkey = ossl_pkey_read_generic(in, Qnil);
    BIO_free(in);
    if (!pkey)
        ossl_raise(eDHError, "could not parse pkey");
    type = EVP_PKEY_base_id(pkey);
    if (type != EVP_PKEY_DH) {
        EVP_PKEY_free(pkey);
        rb_raise(eDHError, "incorrect pkey type: %s", OBJ_nid2sn(type));
    }
    RTYPEDDATA_DATA(self) = pkey;
    return self;
  legacy:
    BIO_free(in);
    pkey = EVP_PKEY_new();
    if (!pkey || EVP_PKEY_assign_DH(pkey, dh) != 1) {
        EVP_PKEY_free(pkey);
        DH_free(dh);
        ossl_raise(eDHError, "EVP_PKEY_assign_DH");
    }
    RTYPEDDATA_DATA(self) = pkey;
    return self;
}
  Class Method Details
    .generate(size, generator = 2)  ⇒ DH   
Creates a new DH instance from scratch by generating random parameters and a key pair.
See also OpenSSL::PKey.generate_parameters and OpenSSL::PKey.generate_key.
- size
- 
The desired key size in bits. 
- generator
- 
The generator. 
# File 'ext/openssl/lib/openssl/pkey.rb', line 118
def generate(size, generator = 2, &blk) dhparams = OpenSSL::PKey.generate_parameters("DH", { "dh_paramgen_prime_len" => size, "dh_paramgen_generator" => generator, }, &blk) OpenSSL::PKey.generate_key(dhparams) end
Instance Attribute Details
    #params_ok?  ⇒ Boolean  (readonly)  
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.
See also the man page EVP_PKEY_param_check(3).
# File 'ext/openssl/ossl_pkey_dh.c', line 326
static VALUE
ossl_dh_check_params(VALUE self)
{
    int ret;
#ifdef HAVE_EVP_PKEY_CHECK
    EVP_PKEY *pkey;
    EVP_PKEY_CTX *pctx;
    GetPKey(self, pkey);
    pctx = EVP_PKEY_CTX_new(pkey, /* engine */NULL);
    if (!pctx)
        ossl_raise(eDHError, "EVP_PKEY_CTX_new");
    ret = EVP_PKEY_param_check(pctx);
    EVP_PKEY_CTX_free(pctx);
#else
    DH *dh;
    int codes;
    GetDH(self, dh);
    ret = DH_check(dh, &codes) == 1 && codes == 0;
#endif
    if (ret == 1)
        return Qtrue;
    else {
        /* DH_check_ex() will put error entry on failure */
        ossl_clear_error();
        return Qfalse;
    }
}
  
    #private?  ⇒ Boolean  (readonly)  
Indicates whether this DH instance has a private key associated with it or not. The private key may be retrieved with DH#priv_key.
# File 'ext/openssl/ossl_pkey_dh.c', line 197
static VALUE
ossl_dh_is_private(VALUE self)
{
    OSSL_3_const DH *dh;
    const BIGNUM *bn;
    GetDH(self, dh);
    DH_get0_key(dh, NULL, &bn);
#if !defined(OPENSSL_NO_ENGINE)
    return (bn || DH_get0_engine((DH *)dh)) ? Qtrue : Qfalse;
#else
    return bn ? Qtrue : Qfalse;
#endif
}
  
    #public?  ⇒ Boolean  (readonly)  
Indicates whether this DH instance has a public key associated with it or not. The public key may be retrieved with DH#pub_key.
# File 'ext/openssl/ossl_pkey_dh.c', line 178
static VALUE
ossl_dh_is_public(VALUE self)
{
    OSSL_3_const DH *dh;
    const BIGNUM *bn;
    GetDH(self, dh);
    DH_get0_key(dh, &bn, NULL);
    return bn ? Qtrue : Qfalse;
}
  Instance Method Details
    #compute_key(pub_bn)  ⇒ String   
Returns a String containing a shared secret computed from the other party’s public value.
This method is provided for backwards compatibility, and calls #derive internally.
Parameters
- 
pub_bn is a ::OpenSSL::BN, not theDHinstance returned by DH#public_key as that contains the DH parameters only.
# File 'ext/openssl/lib/openssl/pkey.rb', line 49
def compute_key(pub_bn) # FIXME: This is constructing an X.509 SubjectPublicKeyInfo and is very # inefficient obj = OpenSSL::ASN1.Sequence([ OpenSSL::ASN1.Sequence([ OpenSSL::ASN1.ObjectId("dhKeyAgreement"), OpenSSL::ASN1.Sequence([ OpenSSL::ASN1.Integer(p), OpenSSL::ASN1.Integer(g), ]), ]), OpenSSL::ASN1.BitString(OpenSSL::ASN1.Integer(pub_bn).to_der), ]) derive(OpenSSL::PKey.read(obj.to_der)) end
    
      #export  ⇒ String 
      #to_pem  ⇒ String 
      #to_s  ⇒ String 
    
  
String 
      #to_pem  ⇒ String 
      #to_s  ⇒ String 
    Alias for #to_s.
    #generate_key!  ⇒ self   
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.
Deprecated in version 3.0. This method is incompatible with ::OpenSSL 3.0.0 or later.
See also OpenSSL::PKey.generate_key.
Example:
# DEPRECATED USAGE: This will not work on OpenSSL 3.0 or later
dh0 = OpenSSL::PKey::DH.new(2048)
dh = dh0.public_key # #public_key only copies the DH parameters (contrary to the name)
dh.generate_key!
puts dh.private? # => true
puts dh0.pub_key == dh.pub_key #=> false
# With OpenSSL::PKey.generate_key
dh0 = OpenSSL::PKey::DH.new(2048)
dh = OpenSSL::PKey.generate_key(dh0)
puts dh0.pub_key == dh.pub_key #=> false# File 'ext/openssl/lib/openssl/pkey.rb', line 91
def generate_key! if OpenSSL::OPENSSL_VERSION_NUMBER >= 0x30000000 raise DHError, "OpenSSL::PKey::DH is immutable on OpenSSL 3.0; " \ "use OpenSSL::PKey.generate_key instead" end unless priv_key tmp = OpenSSL::PKey.generate_key(self) set_key(tmp.pub_key, tmp.priv_key) end self end
#initialize_copy(other)
[ GitHub ]# File 'ext/openssl/ossl_pkey_dh.c', line 131
static VALUE
ossl_dh_initialize_copy(VALUE self, VALUE other)
{
    EVP_PKEY *pkey;
    DH *dh, *dh_other;
    const BIGNUM *pub, *priv;
    TypedData_Get_Struct(self, EVP_PKEY, &ossl_evp_pkey_type, pkey);
    if (pkey)
        rb_raise(rb_eTypeError, "pkey already initialized");
    GetDH(other, dh_other);
    dh = DHparams_dup(dh_other);
    if (!dh)
	ossl_raise(eDHError, "DHparams_dup");
    DH_get0_key(dh_other, &pub, &priv);
    if (pub) {
	BIGNUM *pub2 = BN_dup(pub);
	BIGNUM *priv2 = BN_dup(priv);
        if (!pub2 || (priv && !priv2)) {
	    BN_clear_free(pub2);
	    BN_clear_free(priv2);
	    ossl_raise(eDHError, "BN_dup");
	}
	DH_set0_key(dh, pub2, priv2);
    }
    pkey = EVP_PKEY_new();
    if (!pkey || EVP_PKEY_assign_DH(pkey, dh) != 1) {
        EVP_PKEY_free(pkey);
        DH_free(dh);
        ossl_raise(eDHError, "EVP_PKEY_assign_DH");
    }
    RTYPEDDATA_DATA(self) = pkey;
    return self;
}
  
    #params  ⇒ Hash   
Stores all parameters of key to the hash INSECURE: PRIVATE INFORMATIONS CAN LEAK OUT!!! Don’t use :-)) (I’s up to you)
# File 'ext/openssl/ossl_pkey_dh.c', line 295
static VALUE
ossl_dh_get_params(VALUE self)
{
    OSSL_3_const DH *dh;
    VALUE hash;
    const BIGNUM *p, *q, *g, *pub_key, *priv_key;
    GetDH(self, dh);
    DH_get0_pqg(dh, &p, &q, &g);
    DH_get0_key(dh, &pub_key, &priv_key);
    hash = rb_hash_new();
    rb_hash_aset(hash, rb_str_new2("p"), ossl_bn_new(p));
    rb_hash_aset(hash, rb_str_new2("q"), ossl_bn_new(q));
    rb_hash_aset(hash, rb_str_new2("g"), ossl_bn_new(g));
    rb_hash_aset(hash, rb_str_new2("pub_key"), ossl_bn_new(pub_key));
    rb_hash_aset(hash, rb_str_new2("priv_key"), ossl_bn_new(priv_key));
    return hash;
}
  
    #public_key  ⇒ DH   
Returns a new DH instance that carries just the DH parameters.
Contrary to the method name, the returned DH object contains only parameters and not the public key.
This method is provided for backwards compatibility. In most cases, there is no need to call this method.
For the purpose of re-generating the key pair while keeping the parameters, check OpenSSL::PKey.generate_key.
Example:
# OpenSSL::PKey::DH.generate by default generates a random key pair
dh1 = OpenSSL::PKey::DH.generate(2048)
p dh1.priv_key #=> #<OpenSSL::BN 1288347...>
dhcopy = dh1.public_key
p dhcopy.priv_key #=> nil
    #set_key(pub_key, priv_key)  ⇒ self   
Sets pub_key and priv_key for the DH instance. priv_key may be nil.
    #set_pqg(p, q, g)  ⇒ self   
Sets p, q, g to the DH instance.
    #to_der  ⇒ String   
Serializes the DH parameters to a DER-encoding
Note that any existing per-session public/private keys will not get encoded, just the Diffie-Hellman parameters will be encoded.
See also #public_to_der (X.509 SubjectPublicKeyInfo) and #private_to_der (PKCS #8 PrivateKeyInfo or EncryptedPrivateKeyInfo) for serialization with the private or public key components.
# File 'ext/openssl/ossl_pkey_dh.c', line 267
static VALUE
ossl_dh_to_der(VALUE self)
{
    OSSL_3_const DH *dh;
    unsigned char *p;
    long len;
    VALUE str;
    GetDH(self, dh);
    if((len = i2d_DHparams(dh, NULL)) <= 0)
	ossl_raise(eDHError, NULL);
    str = rb_str_new(0, len);
    p = (unsigned char *)RSTRING_PTR(str);
    if(i2d_DHparams(dh, &p) < 0)
	ossl_raise(eDHError, NULL);
    ossl_str_adjust(str, p);
    return str;
}
  
    
      #export  ⇒ String 
      #to_pem  ⇒ String 
      #to_s  ⇒ String 
    
  
String 
      #to_pem  ⇒ String 
      #to_s  ⇒ String 
    Alias for #to_s.
    
      #export  ⇒ String 
      #to_pem  ⇒ String 
      #to_s  ⇒ String 
    
    Also known as: #export, #to_pem
  
String 
      #to_pem  ⇒ String 
      #to_s  ⇒ String 
    Serializes the DH parameters to a PEM-encoding.
Note that any existing per-session public/private keys will not get encoded, just the Diffie-Hellman parameters will be encoded.
PEM-encoded parameters will look like:
-----BEGIN DH PARAMETERS-----
[...]
-----END DH PARAMETERS-----See also #public_to_pem (X.509 SubjectPublicKeyInfo) and #private_to_pem (PKCS #8 PrivateKeyInfo or EncryptedPrivateKeyInfo) for serialization with the private or public key components.
# File 'ext/openssl/ossl_pkey_dh.c', line 234
static VALUE
ossl_dh_export(VALUE self)
{
    OSSL_3_const DH *dh;
    BIO *out;
    VALUE str;
    GetDH(self, dh);
    if (!(out = BIO_new(BIO_s_mem()))) {
	ossl_raise(eDHError, NULL);
    }
    if (!PEM_write_bio_DHparams(out, dh)) {
	BIO_free(out);
	ossl_raise(eDHError, NULL);
    }
    str = ossl_membio2str(out);
    return str;
}