class OpenSSL::PKey::DSA - Documentation for Ruby 3.3

# class OpenSSL::PKey::DSA

`DSA`, the Digital Signature Algorithm, is specified in NIST’s FIPS 186-3. It is an asymmetric public key algorithm that may be used similar to e.g. `RSA`.

### Public Class Methods

generate(size) → dsa click to toggle source

Creates a new `DSA` instance by generating a private/public key pair from scratch.

See also `OpenSSL::PKey.generate_parameters` and `OpenSSL::PKey.generate_key`.

`size`

  The desired key size in bits.

    # File ext/openssl/lib/openssl/pkey.rb, line 169
    def generate(size, &blk)
      # FIPS 186-4 specifies four (L,N) pairs: (1024,160), (2048,224),
      # (2048,256), and (3072,256).
      #
      # q size is derived here with compatibility with
      # DSA_generator_parameters_ex() which previous versions of ruby/openssl
      # used to call.
      qsize = size >= 2048 ? 256 : 160
      dsaparams = OpenSSL::PKey.generate_parameters("DSA", {
        "dsa_paramgen_bits" => size,
        "dsa_paramgen_q_bits" => qsize,
      }, &blk)
      OpenSSL::PKey.generate_key(dsaparams)
    end

new → dsa click to toggle source
new(string [, pass]) → dsa
new(size) → dsa

Creates a new `DSA` instance by reading an existing key from string.

If called without arguments, creates a new instance with no key components set. They can be set individually by `set_pqg` and `set_key`.

If called with a `String`, tries to parse as DER or PEM encoding of a DSA key. See also `OpenSSL::PKey.read` which can parse keys of any kinds.

If called with a number, generates random parameters and a key pair. This form works as an alias of `DSA.generate`.

`string`

  A `String` that contains a DER or PEM encoded key.

`pass`

  A `String` that contains an optional password.

`size`

  See `DSA.generate`.

Examples:

    p OpenSSL::PKey::DSA.new(1024)
    #=> #<OpenSSL::PKey::DSA:0x000055a8d6025bf0 oid=DSA>

    p OpenSSL::PKey::DSA.new(File.read('dsa.pem'))
    #=> #<OpenSSL::PKey::DSA:0x000055555d6b8110 oid=DSA>

    p OpenSSL::PKey::DSA.new(File.read('dsa.pem'), 'mypassword')
    #=> #<OpenSSL::PKey::DSA:0x0000556f973c40b8 oid=DSA>

    static VALUE
    ossl_dsa_initialize(int argc, VALUE *argv, VALUE self)
    {
        EVP_PKEY *pkey;
        DSA *dsa;
        BIO *in = NULL;
        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");

        /* The DSA.new(size, generator) form is handled by lib/openssl/pkey.rb */
        rb_scan_args(argc, argv, "02", &arg, &pass);
        if (argc == 0) {
            dsa = DSA_new();
            if (!dsa)
                ossl_raise(eDSAError, "DSA_new");
            goto legacy;
        }

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

        /* DER-encoded DSAPublicKey format isn't supported by the generic routine */
        dsa = (DSA *)PEM_ASN1_read_bio((d2i_of_void *)d2i_DSAPublicKey,
                                       PEM_STRING_DSA_PUBLIC,
                                       in, NULL, NULL, NULL);
        if (dsa)
            goto legacy;
        OSSL_BIO_reset(in);

        pkey = ossl_pkey_read_generic(in, pass);
        BIO_free(in);
        if (!pkey)
            ossl_raise(eDSAError, "Neither PUB key nor PRIV key");

        type = EVP_PKEY_base_id(pkey);
        if (type != EVP_PKEY_DSA) {
            EVP_PKEY_free(pkey);
            rb_raise(eDSAError, "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_DSA(pkey, dsa) != 1) {
            EVP_PKEY_free(pkey);
            DSA_free(dsa);
            ossl_raise(eDSAError, "EVP_PKEY_assign_DSA");
        }
        RTYPEDDATA_DATA(self) = pkey;
        return self;
    }

### Public Instance Methods

export([cipher, password]) → aString click to toggle source

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 parameters cipher and password are ignored.

  A PEM-encoded key will look like:

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

  Consider using `public_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 traditional OpenSSL DSAPrivateKey.

  A PEM-encoded key will look like:

      -----BEGIN DSA PRIVATE KEY-----
      [...]
      -----END DSA PRIVATE KEY-----

When the key contains private components, and cipher and password are given

  Serializes it into a traditional OpenSSL DSAPrivateKey and encrypts it in OpenSSL’s traditional PEM encryption format. cipher must be a cipher name understood by `OpenSSL::Cipher.new` or an instance of `OpenSSL::Cipher`.

  An encrypted PEM-encoded key will look like:

      -----BEGIN DSA PRIVATE KEY-----
      Proc-Type: 4,ENCRYPTED
      DEK-Info: AES-128-CBC,733F5302505B34701FC41F5C0746E4C0

      [...]
      -----END DSA 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 traditional, non-standard OpenSSL format is required.

Consider using `public_to_pem` (X.509 SubjectPublicKeyInfo) or `private_to_pem` (PKCS #8 PrivateKeyInfo or EncryptedPrivateKeyInfo) instead.

    static VALUE
    ossl_dsa_export(int argc, VALUE *argv, VALUE self)
    {
        OSSL_3_const DSA *dsa;

        GetDSA(self, dsa);
        if (DSA_HAS_PRIVATE(dsa))
            return ossl_pkey_export_traditional(argc, argv, self, 0);
        else
            return ossl_pkey_export_spki(self, 0);
    }

Also aliased as: to_pem, to_s
initialize_copy(p1) click to toggle source

    HAVE_EVP_PKEY_DUP
    static VALUE
    ossl_dsa_initialize_copy(VALUE self, VALUE other)
    {
        EVP_PKEY *pkey;
        DSA *dsa, *dsa_new;

        TypedData_Get_Struct(self, EVP_PKEY, &ossl_evp_pkey_type, pkey);
        if (pkey)
            rb_raise(rb_eTypeError, "pkey already initialized");
        GetDSA(other, dsa);

        dsa_new = (DSA *)ASN1_dup((i2d_of_void *)i2d_DSAPrivateKey,
                                  (d2i_of_void *)d2i_DSAPrivateKey,
                                  (char *)dsa);
        if (!dsa_new)
            ossl_raise(eDSAError, "ASN1_dup");

        pkey = EVP_PKEY_new();
        if (!pkey || EVP_PKEY_assign_DSA(pkey, dsa_new) != 1) {
            EVP_PKEY_free(pkey);
            DSA_free(dsa_new);
            ossl_raise(eDSAError, "EVP_PKEY_assign_DSA");
        }
        RTYPEDDATA_DATA(self) = pkey;

        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_dsa_get_params(VALUE self)
    {
        OSSL_3_const DSA *dsa;
        VALUE hash;
        const BIGNUM *p, *q, *g, *pub_key, *priv_key;

        GetDSA(self, dsa);
        DSA_get0_pqg(dsa, &p, &q, &g);
        DSA_get0_key(dsa, &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;
    }

private? → true | false click to toggle source

Indicates whether this `DSA` instance has a private key associated with it or not. The private key may be retrieved with DSA#private_key.

    static VALUE
    ossl_dsa_is_private(VALUE self)
    {
        OSSL_3_const DSA *dsa;

        GetDSA(self, dsa);

        return DSA_PRIVATE(self, dsa) ? Qtrue : Qfalse;
    }

public? → true | false click to toggle source

Indicates whether this `DSA` instance has a public key associated with it or not. The public key may be retrieved with `DSA#public_key`.

    static VALUE
    ossl_dsa_is_public(VALUE self)
    {
        const DSA *dsa;
        const BIGNUM *bn;

        GetDSA(self, dsa);
        DSA_get0_key(dsa, &bn, NULL);

        return bn ? Qtrue : Qfalse;
    }

public_key → dsanew click to toggle source

Returns a new `DSA` instance that carries just the DSA parameters and 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 serializing the public key, to PEM or DER encoding of X.509 SubjectPublicKeyInfo format, check `PKey#public_to_pem` and `PKey#public_to_der`.

    # File ext/openssl/lib/openssl/pkey.rb, line 153
    def public_key
      OpenSSL::PKey.read(public_to_der)
    end

set_key(pub_key, priv_key) → self

Sets pub_key and priv_key for the `DSA` instance. priv_key may be `nil`.

set_pqg(p, q, g) → self

Sets p, q, g to the `DSA` instance.

syssign(string) → string click to toggle source

Computes and returns the DSA signature of `string`, where `string` is expected to be an already-computed message digest of the original input data. The signature is issued using the private key of this `DSA` instance.

Deprecated in version 3.0. Consider using `PKey::PKey#sign_raw` and `PKey::PKey#verify_raw` instead.

`string`

  A message digest of the original input data to be signed.

Example:

    dsa = OpenSSL::PKey::DSA.new(2048)
    doc = "Sign me"
    digest = OpenSSL::Digest.digest('SHA1', doc)

    # With legacy #syssign and #sysverify:
    sig = dsa.syssign(digest)
    p dsa.sysverify(digest, sig) #=> true

    # With #sign_raw and #verify_raw:
    sig = dsa.sign_raw(nil, digest)
    p dsa.verify_raw(nil, sig, digest) #=> true

    # File ext/openssl/lib/openssl/pkey.rb, line 220
    def syssign(string)
      q or raise OpenSSL::PKey::DSAError, "incomplete DSA"
      private? or raise OpenSSL::PKey::DSAError, "Private DSA key needed!"
      begin
        sign_raw(nil, string)
      rescue OpenSSL::PKey::PKeyError
        raise OpenSSL::PKey::DSAError, $!.message
      end
    end

sysverify(digest, sig) → true | false click to toggle source

Verifies whether the signature is valid given the message digest input. It does so by validating `sig` using the public key of this `DSA` instance.

Deprecated in version 3.0. Consider using `PKey::PKey#sign_raw` and `PKey::PKey#verify_raw` instead.

`digest`

  A message digest of the original input data to be signed.

`sig`

  A DSA signature value.

    # File ext/openssl/lib/openssl/pkey.rb, line 243
    def sysverify(digest, sig)
      verify_raw(nil, sig, digest)
    rescue OpenSSL::PKey::PKeyError
      raise OpenSSL::PKey::DSAError, $!.message
    end

to_der → aString click to toggle source

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

See `to_pem` for details.

This method is kept for compatibility. This should only be used when the traditional, non-standard OpenSSL format is required.

Consider using `public_to_der` or `private_to_der` instead.

    static VALUE
    ossl_dsa_to_der(VALUE self)
    {
        OSSL_3_const DSA *dsa;

        GetDSA(self, dsa);
        if (DSA_HAS_PRIVATE(dsa))
            return ossl_pkey_export_traditional(0, NULL, self, 1);
        else
            return ossl_pkey_export_spki(self, 1);
    }

to_pem([cipher, password]) → aString

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 parameters cipher and password are ignored.

  A PEM-encoded key will look like:

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

  Consider using `public_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 traditional OpenSSL DSAPrivateKey.

  A PEM-encoded key will look like:

      -----BEGIN DSA PRIVATE KEY-----
      [...]
      -----END DSA PRIVATE KEY-----

When the key contains private components, and cipher and password are given

  Serializes it into a traditional OpenSSL DSAPrivateKey and encrypts it in OpenSSL’s traditional PEM encryption format. cipher must be a cipher name understood by `OpenSSL::Cipher.new` or an instance of `OpenSSL::Cipher`.

  An encrypted PEM-encoded key will look like:

      -----BEGIN DSA PRIVATE KEY-----
      Proc-Type: 4,ENCRYPTED
      DEK-Info: AES-128-CBC,733F5302505B34701FC41F5C0746E4C0

      [...]
      -----END DSA 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 traditional, non-standard OpenSSL format is required.

Consider using `public_to_pem` (X.509 SubjectPublicKeyInfo) or `private_to_pem` (PKCS #8 PrivateKeyInfo or EncryptedPrivateKeyInfo) instead.

Alias for: export
to_s([cipher, password]) → aString

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 parameters cipher and password are ignored.

  A PEM-encoded key will look like:

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

  Consider using `public_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 traditional OpenSSL DSAPrivateKey.

  A PEM-encoded key will look like:

      -----BEGIN DSA PRIVATE KEY-----
      [...]
      -----END DSA PRIVATE KEY-----

When the key contains private components, and cipher and password are given

  Serializes it into a traditional OpenSSL DSAPrivateKey and encrypts it in OpenSSL’s traditional PEM encryption format. cipher must be a cipher name understood by `OpenSSL::Cipher.new` or an instance of `OpenSSL::Cipher`.

  An encrypted PEM-encoded key will look like:

      -----BEGIN DSA PRIVATE KEY-----
      Proc-Type: 4,ENCRYPTED
      DEK-Info: AES-128-CBC,733F5302505B34701FC41F5C0746E4C0

      [...]
      -----END DSA 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 traditional, non-standard OpenSSL format is required.

Consider using `public_to_pem` (X.509 SubjectPublicKeyInfo) or `private_to_pem` (PKCS #8 PrivateKeyInfo or EncryptedPrivateKeyInfo) instead.

Alias for: export