Class: OpenSSL::PKey::RSA
Relationships & Source Files | |
Super Chains via Extension / Inclusion / Inheritance | |
Class Chain:
self,
PKey
|
|
Instance Chain:
self,
PKey
|
|
Inherits: |
OpenSSL::PKey::PKey
|
Defined in: | ext/openssl/ossl_pkey_rsa.c |
Overview
RSA
is an asymmetric public key algorithm that has been formalized in RFC 3447. It is in widespread use in public key infrastructures (PKI) where certificates (cf. ::OpenSSL::X509::Certificate
) often are issued on the basis of a public/private RSA
key pair. RSA
is used in a wide field of applications such as secure (symmetric) key exchange, e.g. when establishing a secure TLS/SSL connection. It is also used in various digital signature schemes.
Class Method Summary
-
.generate(size) ⇒ RSA
Generates an
RSA
keypair. -
.new(key_size) ⇒ RSA
constructor
Generates or loads an
RSA
keypair.
PKey
- Inherited
.new | Because PKey is an abstract class, actually calling this method explicitly will raise a NotImplementedError. |
Instance Attribute Summary
-
#private? ⇒ Boolean
readonly
Does this keypair contain a private key?
-
#public? ⇒ Boolean
readonly
The return value is always
true
since every private key is also a public key.
Instance Method Summary
-
#export([cipher, pass_phrase]) ⇒ PEM-format String
Alias for #to_s.
- #initialize_copy(other)
-
#params ⇒ Hash
THIS METHOD IS INSECURE, PRIVATE INFORMATION CAN LEAK OUT!!!
-
#private_decrypt(string) ⇒ String
Decrypt string, which has been encrypted with the public key, with the private key.
-
#private_encrypt(string) ⇒ String
Encrypt string with the private key.
-
#public_decrypt(string) ⇒ String
Decrypt string, which has been encrypted with the private key, with the public key.
-
#public_encrypt(string) ⇒ String
Encrypt string with the public key.
-
#public_key ⇒ RSA
Makes new
RSA
instance containing the public key from the private key. -
#set_crt_params(dmp1, dmq1, iqmp) ⇒ self
Sets dmp1, dmq1, iqmp for the
RSA
instance. -
#set_factors(p, q) ⇒ self
Sets p, q for the
RSA
instance. -
#set_key(n, e, d) ⇒ self
Sets n, e, d for the
RSA
instance. -
#sign_pss(digest, data, salt_length:, mgf1_hash:) ⇒ String
Signs data using the Probabilistic Signature Scheme (RSA-PSS) and returns the calculated signature.
-
#to_der ⇒ DER-format String
Outputs this keypair in DER encoding.
-
#to_pem([cipher, pass_phrase]) ⇒ PEM-format String
Alias for #to_s.
-
#to_s([cipher, pass_phrase]) ⇒ PEM-format String
(also: #export, #to_pem)
Outputs this keypair in PEM encoding.
-
#to_text ⇒ String
THIS METHOD IS INSECURE, PRIVATE INFORMATION CAN LEAK OUT!!!
-
#verify_pss(digest, signature, data, salt_length:, mgf1_hash:) ⇒ Boolean
Verifies data using the Probabilistic Signature Scheme (RSA-PSS).
PKey
- Inherited
#sign | To sign the String data, digest, an instance of |
#verify | To verify the String signature, digest, an instance of |
Constructor Details
.new(key_size) ⇒ RSA
.new(encoded_key) ⇒ RSA
.new(encoded_key, pass_phrase) ⇒ RSA
RSA
.new(encoded_key) ⇒ RSA
.new(encoded_key, pass_phrase) ⇒ RSA
Generates or loads an RSA
keypair. If an integer key_size is given it represents the desired key size. Keys less than 1024 bits should be considered insecure.
A key can instead be loaded from an encoded_key which must be PEM or DER encoded. A pass_phrase can be used to decrypt the key. If none is given ::OpenSSL
will prompt for the pass phrase.
Examples
OpenSSL::PKey::RSA.new 2048
OpenSSL::PKey::RSA.new File.read 'rsa.pem'
OpenSSL::PKey::RSA.new File.read('rsa.pem'), 'my pass phrase'
# File 'ext/openssl/ossl_pkey_rsa.c', line 220
static VALUE ossl_rsa_initialize(int argc, VALUE *argv, VALUE self) { EVP_PKEY *pkey; RSA *rsa; BIO *in; VALUE arg, pass; GetPKey(self, pkey); if(rb_scan_args(argc, argv, "02", &arg, &pass) == 0) { rsa = RSA_new(); } else if (RB_INTEGER_TYPE_P(arg)) { rsa = rsa_generate(NUM2INT(arg), NIL_P(pass) ? RSA_F4 : NUM2ULONG(pass)); if (!rsa) ossl_raise(eRSAError, NULL); } else { pass = ossl_pem_passwd_value(pass); arg = ossl_to_der_if_possible(arg); in = ossl_obj2bio(&arg); rsa = PEM_read_bio_RSAPrivateKey(in, NULL, ossl_pem_passwd_cb, (void *)pass); if (!rsa) { OSSL_BIO_reset(in); rsa = PEM_read_bio_RSA_PUBKEY(in, NULL, NULL, NULL); } if (!rsa) { OSSL_BIO_reset(in); rsa = d2i_RSAPrivateKey_bio(in, NULL); } if (!rsa) { OSSL_BIO_reset(in); rsa = d2i_RSA_PUBKEY_bio(in, NULL); } if (!rsa) { OSSL_BIO_reset(in); rsa = PEM_read_bio_RSAPublicKey(in, NULL, NULL, NULL); } if (!rsa) { OSSL_BIO_reset(in); rsa = d2i_RSAPublicKey_bio(in, NULL); } BIO_free(in); if (!rsa) { ossl_raise(eRSAError, "Neither PUB key nor PRIV key"); } } if (!EVP_PKEY_assign_RSA(pkey, rsa)) { RSA_free(rsa); ossl_raise(eRSAError, NULL); } return self; }
Class Method Details
.generate(size) ⇒ RSA
.generate(size, exponent) ⇒ RSA
RSA
.generate(size, exponent) ⇒ RSA
Generates an RSA
keypair. size is an integer representing the desired key size. Keys smaller than 1024 should be considered insecure. exponent is an odd number normally 3, 17, or 65537.
# File 'ext/openssl/ossl_pkey_rsa.c', line 179
static VALUE ossl_rsa_s_generate(int argc, VALUE *argv, VALUE klass) { /* why does this method exist? why can't initialize take an optional exponent? */ RSA *rsa; VALUE size, exp; VALUE obj; rb_scan_args(argc, argv, "11", &size, &exp); rsa = rsa_generate(NUM2INT(size), NIL_P(exp) ? RSA_F4 : NUM2ULONG(exp)); /* err handled by rsa_instance */ obj = rsa_instance(klass, rsa); if (obj == Qfalse) { RSA_free(rsa); ossl_raise(eRSAError, NULL); } return obj; }
Instance Attribute Details
#private? ⇒ Boolean
(readonly)
Does this keypair contain a private key?
# File 'ext/openssl/ossl_pkey_rsa.c', line 320
static VALUE ossl_rsa_is_private(VALUE self) { RSA *rsa; GetRSA(self, rsa); return RSA_PRIVATE(self, rsa) ? Qtrue : Qfalse; }
#public? ⇒ Boolean
(readonly)
The return value is always true
since every private key is also a public key.
# File 'ext/openssl/ossl_pkey_rsa.c', line 301
static VALUE ossl_rsa_is_public(VALUE self) { RSA *rsa; GetRSA(self, rsa); /* * This method should check for n and e. BUG. */ (void)rsa; return Qtrue; }
Instance Method Details
#export([cipher, pass_phrase]) ⇒ PEM
-format
String
#to_pem([cipher, pass_phrase]) ⇒ PEM
-format
String
#to_s([cipher, pass_phrase]) ⇒ PEM
-format
String
PEM
-format
String
#to_pem([cipher, pass_phrase]) ⇒ PEM
-format
String
#to_s([cipher, pass_phrase]) ⇒ PEM
-format
String
Alias for #to_s.
#initialize_copy(other)
[ GitHub ]# File 'ext/openssl/ossl_pkey_rsa.c', line 274
static VALUE ossl_rsa_initialize_copy(VALUE self, VALUE other) { EVP_PKEY *pkey; RSA *rsa, *rsa_new; GetPKey(self, pkey); if (EVP_PKEY_base_id(pkey) != EVP_PKEY_NONE) ossl_raise(eRSAError, "RSA already initialized"); GetRSA(other, rsa); rsa_new = ASN1_dup((i2d_of_void *)i2d_RSAPrivateKey, (d2i_of_void *)d2i_RSAPrivateKey, (char *)rsa); if (!rsa_new) ossl_raise(eRSAError, "ASN1_dup"); EVP_PKEY_assign_RSA(pkey, rsa_new); return self; }
#params ⇒ Hash
THIS METHOD IS INSECURE, PRIVATE INFORMATION CAN LEAK OUT!!!
Stores all parameters of key to the hash. The hash has keys ‘n’, ‘e’, ‘d’, ‘p’, ‘q’, ‘dmp1’, ‘dmq1’, ‘iqmp’.
Don’t use :-)) (It’s up to you)
# File 'ext/openssl/ossl_pkey_rsa.c', line 740
static VALUE ossl_rsa_get_params(VALUE self) { RSA *rsa; VALUE hash; const BIGNUM *n, *e, *d, *p, *q, *dmp1, *dmq1, *iqmp; GetRSA(self, rsa); RSA_get0_key(rsa, &n, &e, &d); RSA_get0_factors(rsa, &p, &q); RSA_get0_crt_params(rsa, &dmp1, &dmq1, &iqmp); hash = rb_hash_new(); rb_hash_aset(hash, rb_str_new2("n"), ossl_bn_new(n)); rb_hash_aset(hash, rb_str_new2("e"), ossl_bn_new(e)); rb_hash_aset(hash, rb_str_new2("d"), ossl_bn_new(d)); 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("dmp1"), ossl_bn_new(dmp1)); rb_hash_aset(hash, rb_str_new2("dmq1"), ossl_bn_new(dmq1)); rb_hash_aset(hash, rb_str_new2("iqmp"), ossl_bn_new(iqmp)); return hash; }
#private_decrypt(string) ⇒ String
#private_decrypt(string, padding) ⇒ String
String
#private_decrypt(string, padding) ⇒ String
Decrypt string, which has been encrypted with the public key, with the private key. padding defaults to PKCS1_PADDING.
# File 'ext/openssl/ossl_pkey_rsa.c', line 513
static VALUE ossl_rsa_private_decrypt(int argc, VALUE *argv, VALUE self) { RSA *rsa; const BIGNUM *rsa_n; int buf_len, pad; VALUE str, buffer, padding; GetRSA(self, rsa); RSA_get0_key(rsa, &rsa_n, NULL, NULL); if (!rsa_n) ossl_raise(eRSAError, "incomplete RSA"); if (!RSA_PRIVATE(self, rsa)) ossl_raise(eRSAError, "private key needed."); rb_scan_args(argc, argv, "11", &buffer, &padding); pad = (argc == 1) ? RSA_PKCS1_PADDING : NUM2INT(padding); StringValue(buffer); str = rb_str_new(0, RSA_size(rsa)); buf_len = RSA_private_decrypt(RSTRING_LENINT(buffer), (unsigned char *)RSTRING_PTR(buffer), (unsigned char *)RSTRING_PTR(str), rsa, pad); if (buf_len < 0) ossl_raise(eRSAError, NULL); rb_str_set_len(str, buf_len); return str; }
#private_encrypt(string) ⇒ String
#private_encrypt(string, padding) ⇒ String
String
#private_encrypt(string, padding) ⇒ String
Encrypt string with the private key. padding defaults to PKCS1_PADDING. The encrypted string output can be decrypted using #public_decrypt.
# File 'ext/openssl/ossl_pkey_rsa.c', line 479
static VALUE ossl_rsa_private_encrypt(int argc, VALUE *argv, VALUE self) { RSA *rsa; const BIGNUM *rsa_n; int buf_len, pad; VALUE str, buffer, padding; GetRSA(self, rsa); RSA_get0_key(rsa, &rsa_n, NULL, NULL); if (!rsa_n) ossl_raise(eRSAError, "incomplete RSA"); if (!RSA_PRIVATE(self, rsa)) ossl_raise(eRSAError, "private key needed."); rb_scan_args(argc, argv, "11", &buffer, &padding); pad = (argc == 1) ? RSA_PKCS1_PADDING : NUM2INT(padding); StringValue(buffer); str = rb_str_new(0, RSA_size(rsa)); buf_len = RSA_private_encrypt(RSTRING_LENINT(buffer), (unsigned char *)RSTRING_PTR(buffer), (unsigned char *)RSTRING_PTR(str), rsa, pad); if (buf_len < 0) ossl_raise(eRSAError, NULL); rb_str_set_len(str, buf_len); return str; }
#public_decrypt(string) ⇒ String
#public_decrypt(string, padding) ⇒ String
String
#public_decrypt(string, padding) ⇒ String
Decrypt string, which has been encrypted with the private key, with the public key. padding defaults to PKCS1_PADDING.
# File 'ext/openssl/ossl_pkey_rsa.c', line 447
static VALUE ossl_rsa_public_decrypt(int argc, VALUE *argv, VALUE self) { RSA *rsa; const BIGNUM *rsa_n; int buf_len, pad; VALUE str, buffer, padding; GetRSA(self, rsa); RSA_get0_key(rsa, &rsa_n, NULL, NULL); if (!rsa_n) ossl_raise(eRSAError, "incomplete RSA"); rb_scan_args(argc, argv, "11", &buffer, &padding); pad = (argc == 1) ? RSA_PKCS1_PADDING : NUM2INT(padding); StringValue(buffer); str = rb_str_new(0, RSA_size(rsa)); buf_len = RSA_public_decrypt(RSTRING_LENINT(buffer), (unsigned char *)RSTRING_PTR(buffer), (unsigned char *)RSTRING_PTR(str), rsa, pad); if (buf_len < 0) ossl_raise(eRSAError, NULL); rb_str_set_len(str, buf_len); return str; }
#public_encrypt(string) ⇒ String
#public_encrypt(string, padding) ⇒ String
String
#public_encrypt(string, padding) ⇒ String
Encrypt string with the public key. padding defaults to PKCS1_PADDING. The encrypted string output can be decrypted using #private_decrypt.
# File 'ext/openssl/ossl_pkey_rsa.c', line 415
static VALUE ossl_rsa_public_encrypt(int argc, VALUE *argv, VALUE self) { RSA *rsa; const BIGNUM *rsa_n; int buf_len, pad; VALUE str, buffer, padding; GetRSA(self, rsa); RSA_get0_key(rsa, &rsa_n, NULL, NULL); if (!rsa_n) ossl_raise(eRSAError, "incomplete RSA"); rb_scan_args(argc, argv, "11", &buffer, &padding); pad = (argc == 1) ? RSA_PKCS1_PADDING : NUM2INT(padding); StringValue(buffer); str = rb_str_new(0, RSA_size(rsa)); buf_len = RSA_public_encrypt(RSTRING_LENINT(buffer), (unsigned char *)RSTRING_PTR(buffer), (unsigned char *)RSTRING_PTR(str), rsa, pad); if (buf_len < 0) ossl_raise(eRSAError, NULL); rb_str_set_len(str, buf_len); return str; }
#public_key ⇒ RSA
Makes new RSA
instance containing the public key from the private key.
# File 'ext/openssl/ossl_pkey_rsa.c', line 801
static VALUE ossl_rsa_to_public_key(VALUE self) { EVP_PKEY *pkey; RSA *rsa; VALUE obj; GetPKeyRSA(self, pkey); /* err check performed by rsa_instance */ rsa = RSAPublicKey_dup(EVP_PKEY_get0_RSA(pkey)); obj = rsa_instance(rb_obj_class(self), rsa); if (obj == Qfalse) { RSA_free(rsa); ossl_raise(eRSAError, NULL); } return obj; }
#set_crt_params(dmp1, dmq1, iqmp) ⇒ self
Sets dmp1, dmq1, iqmp for the RSA
instance. They are calculated by d mod (p - 1)
, d mod (q - 1)
and q^(-1) mod p
respectively.
#set_factors(p, q) ⇒ self
Sets p, q for the RSA
instance.
#set_key(n, e, d) ⇒ self
Sets n, e, d for the RSA
instance.
#sign_pss(digest, data, salt_length:, mgf1_hash:) ⇒ String
Signs data using the Probabilistic Signature Scheme (RSA-PSS) and returns the calculated signature.
RSAError
will be raised if an error occurs.
See #verify_pss for the verification operation.
Parameters
- digest
-
A String containing the message digest algorithm name.
- data
-
A String. The data to be signed.
- salt_length
-
The length in octets of the salt. Two special values are reserved:
:digest
means the digest length, and:max
means the maximum possible length for the combination of the private key and the selected message digest algorithm. - mgf1_hash
-
The hash algorithm used in MGF1 (the currently supported mask generation function (MGF)).
Example
data = "Sign me!"
pkey = OpenSSL::PKey::RSA.new(2048)
signature = pkey.sign_pss("SHA256", data, salt_length: :max, mgf1_hash: "SHA256")
pub_key = pkey.public_key
puts pub_key.verify_pss("SHA256", signature, data,
salt_length: :auto, mgf1_hash: "SHA256") # => true
# File 'ext/openssl/ossl_pkey_rsa.c', line 572
static VALUE ossl_rsa_sign_pss(int argc, VALUE *argv, VALUE self) { VALUE digest, data, options, kwargs[2], signature; static ID kwargs_ids[2]; EVP_PKEY *pkey; EVP_PKEY_CTX *pkey_ctx; const EVP_MD *md, *mgf1md; EVP_MD_CTX *md_ctx; size_t buf_len; int salt_len; if (!kwargs_ids[0]) { kwargs_ids[0] = rb_intern_const("salt_length"); kwargs_ids[1] = rb_intern_const("mgf1_hash"); } rb_scan_args(argc, argv, "2:", &digest, &data, &options); rb_get_kwargs(options, kwargs_ids, 2, 0, kwargs); if (kwargs[0] == ID2SYM(rb_intern("max"))) salt_len = -2; /* RSA_PSS_SALTLEN_MAX_SIGN */ else if (kwargs[0] == ID2SYM(rb_intern("digest"))) salt_len = -1; /* RSA_PSS_SALTLEN_DIGEST */ else salt_len = NUM2INT(kwargs[0]); mgf1md = ossl_evp_get_digestbyname(kwargs[1]); pkey = GetPrivPKeyPtr(self); buf_len = EVP_PKEY_size(pkey); md = ossl_evp_get_digestbyname(digest); StringValue(data); signature = rb_str_new(NULL, (long)buf_len); md_ctx = EVP_MD_CTX_new(); if (!md_ctx) goto err; if (EVP_DigestSignInit(md_ctx, &pkey_ctx, md, NULL, pkey) != 1) goto err; if (EVP_PKEY_CTX_set_rsa_padding(pkey_ctx, RSA_PKCS1_PSS_PADDING) != 1) goto err; if (EVP_PKEY_CTX_set_rsa_pss_saltlen(pkey_ctx, salt_len) != 1) goto err; if (EVP_PKEY_CTX_set_rsa_mgf1_md(pkey_ctx, mgf1md) != 1) goto err; if (EVP_DigestSignUpdate(md_ctx, RSTRING_PTR(data), RSTRING_LEN(data)) != 1) goto err; if (EVP_DigestSignFinal(md_ctx, (unsigned char *)RSTRING_PTR(signature), &buf_len) != 1) goto err; rb_str_set_len(signature, (long)buf_len); EVP_MD_CTX_free(md_ctx); return signature; err: EVP_MD_CTX_free(md_ctx); ossl_raise(eRSAError, NULL); }
#to_der ⇒ DER
-format
String
Outputs this keypair in DER encoding.
# File 'ext/openssl/ossl_pkey_rsa.c', line 382
static VALUE ossl_rsa_to_der(VALUE self) { RSA *rsa; int (*i2d_func)(const RSA *, unsigned char **); unsigned char *p; long len; VALUE str; GetRSA(self, rsa); if (RSA_HAS_PRIVATE(rsa)) i2d_func = i2d_RSAPrivateKey; else i2d_func = (int (*)(const RSA *, unsigned char **))i2d_RSA_PUBKEY; if((len = i2d_func(rsa, NULL)) <= 0) ossl_raise(eRSAError, NULL); str = rb_str_new(0, len); p = (unsigned char *)RSTRING_PTR(str); if(i2d_func(rsa, &p) < 0) ossl_raise(eRSAError, NULL); ossl_str_adjust(str, p); return str; }
#export([cipher, pass_phrase]) ⇒ PEM
-format
String
#to_pem([cipher, pass_phrase]) ⇒ PEM
-format
String
#to_s([cipher, pass_phrase]) ⇒ PEM
-format
String
PEM
-format
String
#to_pem([cipher, pass_phrase]) ⇒ PEM
-format
String
#to_s([cipher, pass_phrase]) ⇒ PEM
-format
String
Alias for #to_s.
#export([cipher, pass_phrase]) ⇒ PEM
-format
String
#to_pem([cipher, pass_phrase]) ⇒ PEM
-format
String
#to_s([cipher, pass_phrase]) ⇒ PEM
-format
String
Also known as: #export, #to_pem
PEM
-format
String
#to_pem([cipher, pass_phrase]) ⇒ PEM
-format
String
#to_s([cipher, pass_phrase]) ⇒ PEM
-format
String
Outputs this keypair in PEM encoding. If cipher and pass_phrase are given they will be used to encrypt the key. cipher must be an ::OpenSSL::Cipher
instance.
# File 'ext/openssl/ossl_pkey_rsa.c', line 340
static VALUE ossl_rsa_export(int argc, VALUE *argv, VALUE self) { RSA *rsa; BIO *out; const EVP_CIPHER *ciph = NULL; VALUE cipher, pass, str; GetRSA(self, rsa); rb_scan_args(argc, argv, "02", &cipher, &pass); if (!NIL_P(cipher)) { ciph = ossl_evp_get_cipherbyname(cipher); pass = ossl_pem_passwd_value(pass); } if (!(out = BIO_new(BIO_s_mem()))) { ossl_raise(eRSAError, NULL); } if (RSA_HAS_PRIVATE(rsa)) { if (!PEM_write_bio_RSAPrivateKey(out, rsa, ciph, NULL, 0, ossl_pem_passwd_cb, (void *)pass)) { BIO_free(out); ossl_raise(eRSAError, NULL); } } else { if (!PEM_write_bio_RSA_PUBKEY(out, rsa)) { BIO_free(out); ossl_raise(eRSAError, NULL); } } str = ossl_membio2str(out); return str; }
#to_text ⇒ String
THIS METHOD IS INSECURE, PRIVATE INFORMATION CAN LEAK OUT!!!
Dumps all parameters of a keypair to a String
Don’t use :-)) (It’s up to you)
# File 'ext/openssl/ossl_pkey_rsa.c', line 775
static VALUE ossl_rsa_to_text(VALUE self) { RSA *rsa; BIO *out; VALUE str; GetRSA(self, rsa); if (!(out = BIO_new(BIO_s_mem()))) { ossl_raise(eRSAError, NULL); } if (!RSA_print(out, rsa, 0)) { /* offset = 0 */ BIO_free(out); ossl_raise(eRSAError, NULL); } str = ossl_membio2str(out); return str; }
#verify_pss(digest, signature, data, salt_length:, mgf1_hash:) ⇒ Boolean
Verifies data using the Probabilistic Signature Scheme (RSA-PSS).
The return value is true
if the signature is valid, false
otherwise. RSAError
will be raised if an error occurs.
See #sign_pss for the signing operation and an example code.
Parameters
- digest
-
A String containing the message digest algorithm name.
- data
-
A String. The data to be signed.
- salt_length
-
The length in octets of the salt. Two special values are reserved:
:digest
means the digest length, and:auto
means automatically determining the length based on the signature. - mgf1_hash
-
The hash algorithm used in MGF1.
# File 'ext/openssl/ossl_pkey_rsa.c', line 659
static VALUE ossl_rsa_verify_pss(int argc, VALUE *argv, VALUE self) { VALUE digest, signature, data, options, kwargs[2]; static ID kwargs_ids[2]; EVP_PKEY *pkey; EVP_PKEY_CTX *pkey_ctx; const EVP_MD *md, *mgf1md; EVP_MD_CTX *md_ctx; int result, salt_len; if (!kwargs_ids[0]) { kwargs_ids[0] = rb_intern_const("salt_length"); kwargs_ids[1] = rb_intern_const("mgf1_hash"); } rb_scan_args(argc, argv, "3:", &digest, &signature, &data, &options); rb_get_kwargs(options, kwargs_ids, 2, 0, kwargs); if (kwargs[0] == ID2SYM(rb_intern("auto"))) salt_len = -2; /* RSA_PSS_SALTLEN_AUTO */ else if (kwargs[0] == ID2SYM(rb_intern("digest"))) salt_len = -1; /* RSA_PSS_SALTLEN_DIGEST */ else salt_len = NUM2INT(kwargs[0]); mgf1md = ossl_evp_get_digestbyname(kwargs[1]); GetPKey(self, pkey); md = ossl_evp_get_digestbyname(digest); StringValue(signature); StringValue(data); md_ctx = EVP_MD_CTX_new(); if (!md_ctx) goto err; if (EVP_DigestVerifyInit(md_ctx, &pkey_ctx, md, NULL, pkey) != 1) goto err; if (EVP_PKEY_CTX_set_rsa_padding(pkey_ctx, RSA_PKCS1_PSS_PADDING) != 1) goto err; if (EVP_PKEY_CTX_set_rsa_pss_saltlen(pkey_ctx, salt_len) != 1) goto err; if (EVP_PKEY_CTX_set_rsa_mgf1_md(pkey_ctx, mgf1md) != 1) goto err; if (EVP_DigestVerifyUpdate(md_ctx, RSTRING_PTR(data), RSTRING_LEN(data)) != 1) goto err; result = EVP_DigestVerifyFinal(md_ctx, (unsigned char *)RSTRING_PTR(signature), RSTRING_LEN(signature)); switch (result) { case 0: ossl_clear_error(); EVP_MD_CTX_free(md_ctx); return Qfalse; case 1: EVP_MD_CTX_free(md_ctx); return Qtrue; default: goto err; } err: EVP_MD_CTX_free(md_ctx); ossl_raise(eRSAError, NULL); }