Class: OpenSSL::PKey::DSA
- Defined in:
- ext/rubysl/openssl/ossl_pkey_dsa.c,
ext/rubysl/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. Please note that for OpenSSL versions prior to 1.0.0 the digest algorithms OpenSSL::Digest::DSS (equivalent to SHA) or OpenSSL::Digest::DSS1 (equivalent to SHA-1) must be used for issuing signatures with a DSA key using OpenSSL::PKey#sign. Starting with OpenSSL 1.0.0, digest algorithms are no longer restricted, any Digest may be used for signing.
Class Method Summary collapse
-
.generate(size) ⇒ Object
Creates a new DSA instance by generating a private/public key pair from scratch.
Instance Method Summary collapse
-
#export(*args) ⇒ Object
(also: #to_pem, #to_s)
Encodes this DSA to its PEM encoding.
-
#initialize(*args) ⇒ Object
constructor
Creates a new DSA instance by reading an existing key from
string
. -
#params ⇒ Hash
Stores all parameters of key to the hash INSECURE: PRIVATE INFORMATIONS CAN LEAK OUT!!! Don’t use :-)) (I’s up to you).
-
#private? ⇒ Boolean
Indicates whether this DSA instance has a private key associated with it or not.
-
#public? ⇒ Boolean
Indicates whether this DSA instance has a public key associated with it or not.
-
#public_key ⇒ Object
Returns a new DSA instance that carries just the public key information.
-
#set_key(pub_key, priv_key) ⇒ self
Sets
pub_key
andpriv_key
for the DSA instance. -
#set_pqg(p, q, g) ⇒ self
Sets
p
,q
,g
for the DSA instance. -
#syssign(string) ⇒ aString
Computes and returns the DSA signature of
string
, wherestring
is expected to be an already-computed message digest of the original input data. -
#sysverify(digest, sig) ⇒ Object
Verifies whether the signature is valid given the message digest input.
-
#to_der ⇒ aString
Encodes this DSA to its DER encoding.
-
#to_text ⇒ aString
Prints all parameters of key to buffer INSECURE: PRIVATE INFORMATIONS CAN LEAK OUT!!! Don’t use :-)) (I’s up to you).
Methods inherited from PKey
Constructor Details
#new ⇒ Object #new(size) ⇒ Object #new(string[, pass]) ⇒ Object
Creates a new DSA instance by reading an existing key from string
.
Parameters
-
size
is an integer representing the desired key size. -
string
contains a DER or PEM encoded key. -
pass
is a string that contains an optional password.
Examples
DSA.new -> dsa DSA.new(1024) -> dsa DSA.new(File.read(‘dsa.pem’)) -> dsa DSA.new(File.read(‘dsa.pem’), ‘mypassword’) -> dsa
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 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 |
# File 'ext/rubysl/openssl/ossl_pkey_dsa.c', line 212
static VALUE
ossl_dsa_initialize(int argc, VALUE *argv, VALUE self)
{
EVP_PKEY *pkey;
DSA *dsa;
BIO *in;
VALUE arg, pass;
GetPKey(self, pkey);
if(rb_scan_args(argc, argv, "02", &arg, &pass) == 0) {
dsa = DSA_new();
}
else if (RB_INTEGER_TYPE_P(arg)) {
if (!(dsa = dsa_generate(NUM2INT(arg)))) {
ossl_raise(eDSAError, NULL);
}
}
else {
pass = ossl_pem_passwd_value(pass);
arg = ossl_to_der_if_possible(arg);
in = ossl_obj2bio(&arg);
dsa = PEM_read_bio_DSAPrivateKey(in, NULL, ossl_pem_passwd_cb, (void *)pass);
if (!dsa) {
OSSL_BIO_reset(in);
dsa = PEM_read_bio_DSA_PUBKEY(in, NULL, NULL, NULL);
}
if (!dsa) {
OSSL_BIO_reset(in);
dsa = d2i_DSAPrivateKey_bio(in, NULL);
}
if (!dsa) {
OSSL_BIO_reset(in);
dsa = d2i_DSA_PUBKEY_bio(in, NULL);
}
if (!dsa) {
OSSL_BIO_reset(in);
#define PEM_read_bio_DSAPublicKey(bp,x,cb,u) (DSA *)PEM_ASN1_read_bio( \
(d2i_of_void *)d2i_DSAPublicKey, PEM_STRING_DSA_PUBLIC, (bp), (void **)(x), (cb), (u))
dsa = PEM_read_bio_DSAPublicKey(in, NULL, NULL, NULL);
#undef PEM_read_bio_DSAPublicKey
}
BIO_free(in);
if (!dsa) {
ossl_clear_error();
ossl_raise(eDSAError, "Neither PUB key nor PRIV key");
}
}
if (!EVP_PKEY_assign_DSA(pkey, dsa)) {
DSA_free(dsa);
ossl_raise(eDSAError, NULL);
}
return self;
}
|
Class Method Details
.generate(size) ⇒ Object
Creates a new DSA instance by generating a private/public key pair from scratch.
Parameters
-
size
is an integer representing the desired key size.
178 179 180 181 182 183 184 185 186 187 188 189 190 |
# File 'ext/rubysl/openssl/ossl_pkey_dsa.c', line 178
static VALUE
ossl_dsa_s_generate(VALUE klass, VALUE size)
{
DSA *dsa = dsa_generate(NUM2INT(size)); /* err handled by dsa_instance */
VALUE obj = dsa_instance(klass, dsa);
if (obj == Qfalse) {
DSA_free(dsa);
ossl_raise(eDSAError, NULL);
}
return obj;
}
|
Instance Method Details
#export([cipher, password]) ⇒ aString #to_pem([cipher, password]) ⇒ aString #to_s([cipher, password]) ⇒ aString Also known as: to_pem, to_s
Encodes this DSA to its PEM encoding.
Parameters
-
cipher
is an OpenSSL::Cipher. -
password
is a string containing your password.
Examples
DSA.to_pem -> aString DSA.to_pem(cipher, ‘mypassword’) -> aString
340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 |
# File 'ext/rubysl/openssl/ossl_pkey_dsa.c', line 340
static VALUE
ossl_dsa_export(int argc, VALUE *argv, VALUE self)
{
DSA *dsa;
BIO *out;
const EVP_CIPHER *ciph = NULL;
VALUE cipher, pass, str;
GetDSA(self, dsa);
rb_scan_args(argc, argv, "02", &cipher, &pass);
if (!NIL_P(cipher)) {
ciph = GetCipherPtr(cipher);
pass = ossl_pem_passwd_value(pass);
}
if (!(out = BIO_new(BIO_s_mem()))) {
ossl_raise(eDSAError, NULL);
}
if (DSA_HAS_PRIVATE(dsa)) {
if (!PEM_write_bio_DSAPrivateKey(out, dsa, ciph, NULL, 0,
ossl_pem_passwd_cb, (void *)pass)){
BIO_free(out);
ossl_raise(eDSAError, NULL);
}
} else {
if (!PEM_write_bio_DSA_PUBKEY(out, dsa)) {
BIO_free(out);
ossl_raise(eDSAError, NULL);
}
}
str = ossl_membio2str(out);
return str;
}
|
#params ⇒ Hash
Stores all parameters of key to the hash INSECURE: PRIVATE INFORMATIONS CAN LEAK OUT!!! Don’t use :-)) (I’s up to you)
415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 |
# File 'ext/rubysl/openssl/ossl_pkey_dsa.c', line 415
static VALUE
ossl_dsa_get_params(VALUE self)
{
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.
313 314 315 316 317 318 319 320 321 |
# File 'ext/rubysl/openssl/ossl_pkey_dsa.c', line 313
static VALUE
ossl_dsa_is_private(VALUE self)
{
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.
294 295 296 297 298 299 300 301 302 303 304 |
# File 'ext/rubysl/openssl/ossl_pkey_dsa.c', line 294
static VALUE
ossl_dsa_is_public(VALUE self)
{
DSA *dsa;
const BIGNUM *bn;
GetDSA(self, dsa);
DSA_get0_key(dsa, &bn, NULL);
return bn ? Qtrue : Qfalse;
}
|
#public_key ⇒ Object
Returns a new DSA instance that carries just the public key information. If the current instance has also private key information, this will no longer be present in the new instance. This feature is helpful for publishing the public key information without leaking any of the private information.
Example
dsa = OpenSSL::PKey::DSA.new(2048) # has public and private information pub_key = dsa.public_key # has only the public part available pub_key_der = pub_key.to_der # it’s safe to publish this
481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 |
# File 'ext/rubysl/openssl/ossl_pkey_dsa.c', line 481
static VALUE
ossl_dsa_to_public_key(VALUE self)
{
EVP_PKEY *pkey;
DSA *dsa;
VALUE obj;
GetPKeyDSA(self, pkey);
/* err check performed by dsa_instance */
#define DSAPublicKey_dup(dsa) (DSA *)ASN1_dup( \
(i2d_of_void *)i2d_DSAPublicKey, (d2i_of_void *)d2i_DSAPublicKey, (char *)(dsa))
dsa = DSAPublicKey_dup(EVP_PKEY_get0_DSA(pkey));
#undef DSAPublicKey_dup
obj = dsa_instance(rb_obj_class(self), dsa);
if (obj == Qfalse) {
DSA_free(dsa);
ossl_raise(eDSAError, NULL);
}
return obj;
}
|
#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
for the DSA instance.
#syssign(string) ⇒ aString
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.
Parameters
-
string
is a message digest of the original input data to be signed
Example
dsa = OpenSSL::PKey::DSA.new(2048) doc = “Sign me” digest = OpenSSL::Digest::SHA1.digest(doc) sig = dsa.syssign(digest)
521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 |
# File 'ext/rubysl/openssl/ossl_pkey_dsa.c', line 521
static VALUE
ossl_dsa_sign(VALUE self, VALUE data)
{
DSA *dsa;
const BIGNUM *dsa_q;
unsigned int buf_len;
VALUE str;
GetDSA(self, dsa);
DSA_get0_pqg(dsa, NULL, &dsa_q, NULL);
if (!dsa_q)
ossl_raise(eDSAError, "incomplete DSA");
if (!DSA_PRIVATE(self, dsa))
ossl_raise(eDSAError, "Private DSA key needed!");
StringValue(data);
str = rb_str_new(0, DSA_size(dsa));
if (!DSA_sign(0, (unsigned char *)RSTRING_PTR(data), RSTRING_LENINT(data),
(unsigned char *)RSTRING_PTR(str),
&buf_len, dsa)) { /* type is ignored (0) */
ossl_raise(eDSAError, NULL);
}
rb_str_set_len(str, buf_len);
return str;
}
|
#sysverify(digest, sig) ⇒ Object
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.
Parameters
-
digest
is a message digest of the original input data to be signed -
sig
is a DSA signature value
Example
dsa = OpenSSL::PKey::DSA.new(2048) doc = “Sign me” digest = OpenSSL::Digest::SHA1.digest(doc) sig = dsa.syssign(digest) puts dsa.sysverify(digest, sig) # => true
566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 |
# File 'ext/rubysl/openssl/ossl_pkey_dsa.c', line 566
static VALUE
ossl_dsa_verify(VALUE self, VALUE digest, VALUE sig)
{
DSA *dsa;
int ret;
GetDSA(self, dsa);
StringValue(digest);
StringValue(sig);
/* type is ignored (0) */
ret = DSA_verify(0, (unsigned char *)RSTRING_PTR(digest), RSTRING_LENINT(digest),
(unsigned char *)RSTRING_PTR(sig), RSTRING_LENINT(sig), dsa);
if (ret < 0) {
ossl_raise(eDSAError, NULL);
}
else if (ret == 1) {
return Qtrue;
}
return Qfalse;
}
|
#to_der ⇒ aString
Encodes this DSA to its DER encoding.
381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 |
# File 'ext/rubysl/openssl/ossl_pkey_dsa.c', line 381
static VALUE
ossl_dsa_to_der(VALUE self)
{
DSA *dsa;
int (*i2d_func)(DSA *, unsigned char **);
unsigned char *p;
long len;
VALUE str;
GetDSA(self, dsa);
if(DSA_HAS_PRIVATE(dsa))
i2d_func = (int (*)(DSA *,unsigned char **))i2d_DSAPrivateKey;
else
i2d_func = i2d_DSA_PUBKEY;
if((len = i2d_func(dsa, NULL)) <= 0)
ossl_raise(eDSAError, NULL);
str = rb_str_new(0, len);
p = (unsigned char *)RSTRING_PTR(str);
if(i2d_func(dsa, &p) < 0)
ossl_raise(eDSAError, NULL);
ossl_str_adjust(str, p);
return str;
}
|
#to_text ⇒ aString
Prints all parameters of key to buffer INSECURE: PRIVATE INFORMATIONS CAN LEAK OUT!!! Don’t use :-)) (I’s up to you)
444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 |
# File 'ext/rubysl/openssl/ossl_pkey_dsa.c', line 444
static VALUE
ossl_dsa_to_text(VALUE self)
{
DSA *dsa;
BIO *out;
VALUE str;
GetDSA(self, dsa);
if (!(out = BIO_new(BIO_s_mem()))) {
ossl_raise(eDSAError, NULL);
}
if (!DSA_print(out, dsa, 0)) { /* offset = 0 */
BIO_free(out);
ossl_raise(eDSAError, NULL);
}
str = ossl_membio2str(out);
return str;
}
|