Class: OpenSSL::PKey::DSA

Inherits:
PKey
  • Object
show all
Includes:
Marshal
Defined in:
ext/openssl/ossl_pkey_dsa.c,
lib/openssl/pkey.rb,
ext/openssl/ossl_pkey_dsa.c

Overview

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.

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Marshal

#_dump, included

Constructor Details

#newObject #new(string[, pass]) ⇒ Object #new(size) ⇒ Object

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>


83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
# File 'ext/openssl/ossl_pkey_dsa.c', line 83

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

Class Method Details

.generate(size, &blk) ⇒ Object

:call-seq:

DSA.generate(size) -> dsa

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.



169
170
171
172
173
174
175
176
177
178
179
180
181
182
# File '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(*args, &blk) ⇒ Object

Handle DSA.new(size) form here; new(str) and new() forms are handled by #initialize



186
187
188
189
190
191
192
# File 'lib/openssl/pkey.rb', line 186

def new(*args, &blk) # :nodoc:
  if args[0].is_a?(Integer)
    generate(*args, &blk)
  else
    super
  end
end

Instance Method Details

#export([cipher, password]) ⇒ aString #to_pem([cipher, password]) ⇒ aString #to_s([cipher, password]) ⇒ aString Also known as: to_pem, to_s

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.

Overloads:

  • #export([cipher, password]) ⇒ aString

    Returns:

    • (aString)
  • #to_pem([cipher, password]) ⇒ aString

    Returns:

    • (aString)
  • #to_s([cipher, password]) ⇒ aString

    Returns:

    • (aString)


267
268
269
270
271
272
273
274
275
276
277
# File 'ext/openssl/ossl_pkey_dsa.c', line 267

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

#initialize_copy(other) ⇒ Object



143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
# File 'ext/openssl/ossl_pkey_dsa.c', line 143

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

#paramsHash

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

Returns:

  • (Hash)


314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
# File 'ext/openssl/ossl_pkey_dsa.c', line 314

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

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

Returns:

  • (Boolean)


198
199
200
201
202
203
204
205
206
# File 'ext/openssl/ossl_pkey_dsa.c', line 198

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

    GetDSA(self, dsa);

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

#public?Boolean

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

Returns:

  • (Boolean)


179
180
181
182
183
184
185
186
187
188
189
# File 'ext/openssl/ossl_pkey_dsa.c', line 179

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_keyObject

:call-seq:

dsa.public_key -> dsanew

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.



153
154
155
# File '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.

Returns:

  • (self)

#set_pqg(p, q, g) ⇒ self

Sets p, q, g to the DSA instance.

Returns:

  • (self)

#syssign(string) ⇒ Object

:call-seq:

dsa.syssign(string) -> string

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


220
221
222
223
224
225
226
227
228
# File '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) ⇒ Object

:call-seq:

dsa.sysverify(digest, sig) -> true | false

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.



243
244
245
246
247
# File '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_deraString

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.

Returns:

  • (aString)


293
294
295
296
297
298
299
300
301
302
303
# File 'ext/openssl/ossl_pkey_dsa.c', line 293

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